Skip to content

Commit 05faa07

Browse files
committed
[cxx-interop] Support bool-based enums.
This is a small fix to prevent a crash. This change simply adds another condition for the "bool" branch that checks if "type" is associated with a "clang::EnumDecl" with an underlying type of "bool", and if so, treats "type" as a "Bool".
1 parent f0f2246 commit 05faa07

File tree

4 files changed

+62
-5
lines changed

4 files changed

+62
-5
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8558,11 +8558,19 @@ ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
85588558
// Create the expression node.
85598559
StringRef printedValueCopy(context.AllocateCopy(printedValue));
85608560
if (value.getKind() == clang::APValue::Int) {
8561-
if (type->getCanonicalType()->isBool()) {
8562-
auto *boolExpr =
8563-
new (context) BooleanLiteralExpr(value.getInt().getBoolValue(),
8564-
SourceLoc(),
8565-
/**Implicit=*/true);
8561+
bool isBool = type->getCanonicalType()->isBool();
8562+
// Check if "type" is a C++ enum with an underlying type of "bool".
8563+
if (!isBool && type->getStructOrBoundGenericStruct() &&
8564+
type->getStructOrBoundGenericStruct()->getClangDecl()) {
8565+
if (auto enumDecl = dyn_cast<clang::EnumDecl>(
8566+
type->getStructOrBoundGenericStruct()->getClangDecl())) {
8567+
isBool = enumDecl->getIntegerType()->isBooleanType();
8568+
}
8569+
}
8570+
if (isBool) {
8571+
auto *boolExpr = new (context)
8572+
BooleanLiteralExpr(value.getInt().getBoolValue(), SourceLoc(),
8573+
/*Implicit=*/true);
85668574

85678575
boolExpr->setBuiltinInitializer(
85688576
context.getBoolBuiltinInitDecl());
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
enum Maybe : bool { No, Yes };
2+
enum BinaryNumbers : bool { One = 1, Zero = 0 };
3+
enum class EnumClass : bool { Foo, Bar };
4+
struct WrapperStruct {
5+
enum InnerBoolEnum : bool { A, B };
6+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module BoolEnums {
2+
header "bool-enums.h"
3+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=BoolEnums -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s
2+
3+
// TODO: these should be enums eventually (especially the enum class).
4+
5+
// CHECK: struct Maybe : Equatable, RawRepresentable {
6+
// CHECK-NEXT: init(_ rawValue: Bool)
7+
// CHECK-NEXT: init(rawValue: Bool)
8+
// CHECK-NEXT: var rawValue: Bool
9+
// CHECK-NEXT: typealias RawValue = Bool
10+
// CHECK-NEXT: }
11+
12+
// CHECK: var No: Maybe { get }
13+
// CHECK: var Yes: Maybe { get }
14+
15+
// CHECK: struct BinaryNumbers : Equatable, RawRepresentable {
16+
// CHECK-NEXT: init(_ rawValue: Bool)
17+
// CHECK-NEXT: init(rawValue: Bool)
18+
// CHECK-NEXT: var rawValue: Bool
19+
// CHECK-NEXT: typealias RawValue = Bool
20+
// CHECK-NEXT: }
21+
22+
// CHECK: var One: BinaryNumbers { get }
23+
// CHECK: var Zero: BinaryNumbers { get }
24+
// CHECK: struct EnumClass : Equatable, RawRepresentable {
25+
// CHECK-NEXT: init(_ rawValue: Bool)
26+
// CHECK-NEXT: init(rawValue: Bool)
27+
// CHECK-NEXT: var rawValue: Bool
28+
// CHECK-NEXT: typealias RawValue = Bool
29+
// CHECK-NEXT: }
30+
31+
// CHECK: struct WrapperStruct {
32+
// TODO: where is "A" and "B"? They should be member variables.
33+
// CHECK-NEXT: struct InnerBoolEnum : Equatable, RawRepresentable {
34+
// CHECK-NEXT: init(_ rawValue: Bool)
35+
// CHECK-NEXT: init(rawValue: Bool)
36+
// CHECK-NEXT: var rawValue: Bool
37+
// CHECK-NEXT: typealias RawValue = Bool
38+
// CHECK-NEXT: }
39+
// CHECK-NEXT: init()
40+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)