mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[ClangImporter] Add check for Bool in importNumericLiteral
I somehow missed this in my original patch, make sure we also handle the bool case here. rdar://164916048
This commit is contained in:
@@ -440,6 +440,22 @@ bool importer::isForwardDeclOfType(const clang::Decl *D) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool importer::isBoolOrBoolEnumType(Type ty) {
|
||||
if (ty->isBool())
|
||||
return true;
|
||||
|
||||
// Check if this is a C++ enum with an underlying type of "bool".
|
||||
if (auto *SD = ty->getStructOrBoundGenericStruct()) {
|
||||
if (auto *clangD = SD->getClangDecl()) {
|
||||
if (auto *ED = dyn_cast<clang::EnumDecl>(clangD)) {
|
||||
if (ED->getIntegerType()->isBooleanType())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ClangImporter::Implementation::shouldIgnoreBridgeHeaderTopLevelDecl(
|
||||
clang::Decl *D) {
|
||||
return importer::isForwardDeclOfType(D);
|
||||
|
||||
@@ -146,15 +146,16 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
|
||||
}
|
||||
|
||||
// Make sure the destination type actually conforms to the builtin literal
|
||||
// protocol before attempting to import, otherwise we'll crash since
|
||||
// `createConstant` expects it to.
|
||||
// protocol or is Bool before attempting to import, otherwise we'll crash
|
||||
// since `createConstant` expects it to.
|
||||
// FIXME: We ought to be careful checking conformance here since it can
|
||||
// result in cycles. Additionally we ought to consider checking for the
|
||||
// non-builtin literal protocol to allow any ExpressibleByIntegerLiteral
|
||||
// type to be supported.
|
||||
if (!ctx.getIntBuiltinInitDecl(constantTyNominal))
|
||||
if (!isBoolOrBoolEnumType(constantType) &&
|
||||
!ctx.getIntBuiltinInitDecl(constantTyNominal)) {
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
return createMacroConstant(Impl, MI, name, DC, constantType,
|
||||
clang::APValue(value),
|
||||
ConstantConvertKind::None,
|
||||
|
||||
@@ -1985,6 +1985,10 @@ bool recordHasReferenceSemantics(const clang::RecordDecl *decl,
|
||||
/// declarations in certain cases, and instead process the real declarations.
|
||||
bool isForwardDeclOfType(const clang::Decl *decl);
|
||||
|
||||
/// Checks whether this type is bool or is a C++ enum with a bool underlying
|
||||
/// type.
|
||||
bool isBoolOrBoolEnumType(Type ty);
|
||||
|
||||
/// Whether we should suppress the import of the given Clang declaration.
|
||||
bool shouldSuppressDeclImport(const clang::Decl *decl);
|
||||
|
||||
|
||||
@@ -276,16 +276,9 @@ ValueDecl *SwiftDeclSynthesizer::createConstant(Identifier name,
|
||||
// Create the expression node.
|
||||
StringRef printedValueCopy(context.AllocateCopy(printedValue));
|
||||
if (value.getKind() == clang::APValue::Int) {
|
||||
bool isBool = type->getCanonicalType()->isBool();
|
||||
// Check if "type" is a C++ enum with an underlying type of "bool".
|
||||
if (!isBool && type->getStructOrBoundGenericStruct() &&
|
||||
type->getStructOrBoundGenericStruct()->getClangDecl()) {
|
||||
if (auto enumDecl = dyn_cast<clang::EnumDecl>(
|
||||
type->getStructOrBoundGenericStruct()->getClangDecl())) {
|
||||
isBool = enumDecl->getIntegerType()->isBooleanType();
|
||||
}
|
||||
}
|
||||
if (isBool) {
|
||||
// Check if "type" is Bool or a C++ enum with an underlying type of Bool.
|
||||
// NOTE: This must match the condition in `importNumericLiteral`.
|
||||
if (isBoolOrBoolEnumType(type)) {
|
||||
auto *boolExpr = new (context)
|
||||
BooleanLiteralExpr(value.getInt().getBoolValue(), SourceLoc(),
|
||||
/*Implicit=*/true);
|
||||
|
||||
39
test/ClangImporter/macro_bool_constants.swift
Normal file
39
test/ClangImporter/macro_bool_constants.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
// RUN: split-file %s %t
|
||||
// RUN: %target-swift-frontend -emit-sil %t/valid.swift -I %t
|
||||
// RUN: %target-swift-frontend -typecheck -verify %t/invalid.swift -I %t -disable-typo-correction
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
//--- cmodule.h
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef _Bool UnderscoreBoolAlias;
|
||||
#define usesUnderscoreBoolAlias ((UnderscoreBoolAlias)0)
|
||||
#define usesUnderscoreBool ((_Bool)0)
|
||||
|
||||
typedef bool BoolAlias;
|
||||
#define usesBoolAlias ((BoolAlias)0)
|
||||
#define usesBool ((bool)0)
|
||||
|
||||
//--- module.modulemap
|
||||
module CModule {
|
||||
header "cmodule.h"
|
||||
requires objc
|
||||
export *
|
||||
}
|
||||
|
||||
//--- valid.swift
|
||||
import CModule
|
||||
|
||||
// Make sure we can import these constants.
|
||||
print(usesUnderscoreBoolAlias)
|
||||
print(usesBoolAlias)
|
||||
|
||||
//--- invalid.swift
|
||||
import CModule
|
||||
|
||||
// FIXME: These ought to work too
|
||||
print(usesUnderscoreBool) // expected-error {{cannot find 'usesUnderscoreBool' in scope}}
|
||||
print(usesBool) // expected-error {{cannot find 'usesBool' in scope}}
|
||||
Reference in New Issue
Block a user