Skip to content

Commit d6fe1e9

Browse files
committed
Teach IRGen to Emit Invalid @objc Enums
In order to remove the enum raw value check request in validateDecl, IRGen must now tolerate recieving an invalid raw value expression. Switch the assert to instead check for this condition and emit an invalid negative discriminator.
1 parent 3815eff commit d6fe1e9

File tree

3 files changed

+14
-18
lines changed

3 files changed

+14
-18
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,10 +1127,12 @@ namespace {
11271127
protected:
11281128
int64_t getDiscriminatorIndex(EnumElementDecl *target) const override {
11291129
// The elements are assigned discriminators ABI-compatible with their
1130-
// raw values from C.
1131-
assert(target->getRawValueExpr()
1132-
&& "c-compatible enum elt has no raw value?!");
1133-
auto intExpr = cast<IntegerLiteralExpr>(target->getRawValueExpr());
1130+
// raw values from C. An invalid raw value is assigned the error index -1.
1131+
auto intExpr =
1132+
dyn_cast_or_null<IntegerLiteralExpr>(target->getRawValueExpr());
1133+
if (!intExpr) {
1134+
return -1;
1135+
}
11341136
auto intType = getDiscriminatorType();
11351137

11361138
APInt intValue =

lib/Sema/TypeCheckDecl.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4187,20 +4187,6 @@ void TypeChecker::validateDecl(ValueDecl *D) {
41874187
auto nominal = cast<NominalTypeDecl>(D);
41884188
Type declaredInterfaceTy = nominal->getDeclaredInterfaceType();
41894189
nominal->setInterfaceType(MetatypeType::get(declaredInterfaceTy, Context));
4190-
4191-
if (auto *ED = dyn_cast<EnumDecl>(nominal)) {
4192-
// @objc enums use their raw values as the value representation, so we
4193-
// need to force the values to be checked even in non-primaries.
4194-
//
4195-
// FIXME: This check can be removed once IRGen can be made tolerant of
4196-
// semantic failures post-Sema.
4197-
if (ED->isObjC()) {
4198-
(void)evaluateOrDefault(
4199-
Context.evaluator,
4200-
EnumRawValuesRequest{ED, TypeResolutionStage::Interface}, true);
4201-
}
4202-
}
4203-
42044190
break;
42054191
}
42064192

test/decl/enum/objc_enum_multi_file.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NO_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NO_RAW_TYPE %s
22
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D BAD_RAW_TYPE 2>&1 | %FileCheck -check-prefix=BAD_RAW_TYPE %s
33
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NON_INT_RAW_TYPE 2>&1 | %FileCheck -check-prefix=NON_INT_RAW_TYPE %s
4+
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NON_INT_RAW_VALUE 2>&1 | %FileCheck -check-prefix=NON_INT_RAW_VALUE %s
45
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D NO_CASES 2>&1 | %FileCheck -check-prefix=NO_CASES %s
56
// RUN: not %target-swift-frontend -module-name main %s -primary-file %S/Inputs/objc_enum_multi_file_helper.swift -emit-ir -D DUPLICATE_CASES 2>&1 | %FileCheck -check-prefix=DUPLICATE_CASES %s
67
// Note that the *other* file is the primary file in this test!
@@ -38,6 +39,13 @@
3839
// DUPLICATE_CASES: :[[@LINE-4]]:8: note: raw value implicitly auto-incremented from zero
3940
}
4041

42+
#elseif NON_INT_RAW_VALUE
43+
@objc enum TheEnum : Int32 {
44+
case A = 0
45+
case B = "B"
46+
// NON_INT_RAW_VALUE: :[[@LINE-1]]:12: error: cannot convert value of type 'String' to raw type 'Int32'
47+
}
48+
4149
#else
4250
enum TheEnum: Invalid { // should never be hit
4351
case A

0 commit comments

Comments
 (0)