Skip to content

Commit 639d331

Browse files
authored
Merge pull request #85670 from hamishknight/bool-fix
2 parents 715cba1 + 7bca421 commit 639d331

File tree

5 files changed

+67
-14
lines changed

5 files changed

+67
-14
lines changed

lib/ClangImporter/ClangImporter.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,22 @@ bool importer::isForwardDeclOfType(const clang::Decl *D) {
440440
return false;
441441
}
442442

443+
bool importer::isBoolOrBoolEnumType(Type ty) {
444+
if (ty->isBool())
445+
return true;
446+
447+
// Check if this is a C++ enum with an underlying type of "bool".
448+
if (auto *SD = ty->getStructOrBoundGenericStruct()) {
449+
if (auto *clangD = SD->getClangDecl()) {
450+
if (auto *ED = dyn_cast<clang::EnumDecl>(clangD)) {
451+
if (ED->getIntegerType()->isBooleanType())
452+
return true;
453+
}
454+
}
455+
}
456+
return false;
457+
}
458+
443459
bool ClangImporter::Implementation::shouldIgnoreBridgeHeaderTopLevelDecl(
444460
clang::Decl *D) {
445461
return importer::isForwardDeclOfType(D);

lib/ClangImporter/ImportMacro.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,16 @@ static ValueDecl *importNumericLiteral(ClangImporter::Implementation &Impl,
146146
}
147147

148148
// Make sure the destination type actually conforms to the builtin literal
149-
// protocol before attempting to import, otherwise we'll crash since
150-
// `createConstant` expects it to.
149+
// protocol or is Bool before attempting to import, otherwise we'll crash
150+
// since `createConstant` expects it to.
151151
// FIXME: We ought to be careful checking conformance here since it can
152152
// result in cycles. Additionally we ought to consider checking for the
153153
// non-builtin literal protocol to allow any ExpressibleByIntegerLiteral
154154
// type to be supported.
155-
if (!ctx.getIntBuiltinInitDecl(constantTyNominal))
155+
if (!isBoolOrBoolEnumType(constantType) &&
156+
!ctx.getIntBuiltinInitDecl(constantTyNominal)) {
156157
return nullptr;
157-
158+
}
158159
return createMacroConstant(Impl, MI, name, DC, constantType,
159160
clang::APValue(value),
160161
ConstantConvertKind::None,

lib/ClangImporter/ImporterImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,10 @@ bool recordHasReferenceSemantics(const clang::RecordDecl *decl,
19851985
/// declarations in certain cases, and instead process the real declarations.
19861986
bool isForwardDeclOfType(const clang::Decl *decl);
19871987

1988+
/// Checks whether this type is bool or is a C++ enum with a bool underlying
1989+
/// type.
1990+
bool isBoolOrBoolEnumType(Type ty);
1991+
19881992
/// Whether we should suppress the import of the given Clang declaration.
19891993
bool shouldSuppressDeclImport(const clang::Decl *decl);
19901994

lib/ClangImporter/SwiftDeclSynthesizer.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,16 +276,9 @@ ValueDecl *SwiftDeclSynthesizer::createConstant(Identifier name,
276276
// Create the expression node.
277277
StringRef printedValueCopy(context.AllocateCopy(printedValue));
278278
if (value.getKind() == clang::APValue::Int) {
279-
bool isBool = type->getCanonicalType()->isBool();
280-
// Check if "type" is a C++ enum with an underlying type of "bool".
281-
if (!isBool && type->getStructOrBoundGenericStruct() &&
282-
type->getStructOrBoundGenericStruct()->getClangDecl()) {
283-
if (auto enumDecl = dyn_cast<clang::EnumDecl>(
284-
type->getStructOrBoundGenericStruct()->getClangDecl())) {
285-
isBool = enumDecl->getIntegerType()->isBooleanType();
286-
}
287-
}
288-
if (isBool) {
279+
// Check if "type" is Bool or a C++ enum with an underlying type of Bool.
280+
// NOTE: This must match the condition in `importNumericLiteral`.
281+
if (isBoolOrBoolEnumType(type)) {
289282
auto *boolExpr = new (context)
290283
BooleanLiteralExpr(value.getInt().getBoolValue(), SourceLoc(),
291284
/*Implicit=*/true);
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t
3+
// RUN: %target-swift-frontend -emit-sil %t/valid.swift -I %t
4+
// RUN: %target-swift-frontend -typecheck -verify %t/invalid.swift -I %t -disable-typo-correction
5+
6+
// REQUIRES: objc_interop
7+
// REQUIRES: OS=macosx
8+
9+
//--- cmodule.h
10+
#include <stdbool.h>
11+
12+
typedef _Bool UnderscoreBoolAlias;
13+
#define usesUnderscoreBoolAlias ((UnderscoreBoolAlias)0)
14+
#define usesUnderscoreBool ((_Bool)0)
15+
16+
typedef bool BoolAlias;
17+
#define usesBoolAlias ((BoolAlias)0)
18+
#define usesBool ((bool)0)
19+
20+
//--- module.modulemap
21+
module CModule {
22+
header "cmodule.h"
23+
requires objc
24+
export *
25+
}
26+
27+
//--- valid.swift
28+
import CModule
29+
30+
// Make sure we can import these constants.
31+
print(usesUnderscoreBoolAlias)
32+
print(usesBoolAlias)
33+
34+
//--- invalid.swift
35+
import CModule
36+
37+
// FIXME: These ought to work too
38+
print(usesUnderscoreBool) // expected-error {{cannot find 'usesUnderscoreBool' in scope}}
39+
print(usesBool) // expected-error {{cannot find 'usesBool' in scope}}

0 commit comments

Comments
 (0)