Skip to content

Commit 908c936

Browse files
committed
Parse: Only accept certain literals as enum case raw values
Just checking for LiteralExpr is too broad, because Sema doesn't know what to do with RegexLiteralExpr for example.
1 parent 401d297 commit 908c936

File tree

6 files changed

+37
-29
lines changed

6 files changed

+37
-29
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3781,9 +3781,6 @@ ERROR(enum_non_integer_convertible_raw_type_no_value,none,
37813781
"expressible by integer or string literal", ())
37823782
ERROR(enum_raw_value_not_unique,none,
37833783
"raw value for enum case is not unique", ())
3784-
ERROR(enum_raw_value_magic_literal,none,
3785-
"use of '%0' literal as raw value for enum case is not supported",
3786-
(StringRef))
37873784
NOTE(enum_raw_value_used_here,none,
37883785
"raw value previously used here", ())
37893786
NOTE(enum_raw_value_incrementing_from_here,none,

lib/Parse/ParseDecl.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9229,6 +9229,20 @@ ParserResult<EnumDecl> Parser::parseDeclEnum(ParseDeclOptions Flags,
92299229
return DCC.fixupParserResult(Status, ED);
92309230
}
92319231

9232+
static bool isValidEnumRawValueLiteral(LiteralExpr *expr) {
9233+
if (expr == nullptr)
9234+
return false;
9235+
9236+
if (!isa<IntegerLiteralExpr>(expr) &&
9237+
!isa<FloatLiteralExpr>(expr) &&
9238+
!isa<StringLiteralExpr>(expr) &&
9239+
!isa<BooleanLiteralExpr>(expr) &&
9240+
!isa<NilLiteralExpr>(expr))
9241+
return false;
9242+
9243+
return true;
9244+
}
9245+
92329246
/// Parse a 'case' of an enum.
92339247
///
92349248
/// \verbatim
@@ -9346,8 +9360,7 @@ Parser::parseDeclEnumCase(ParseDeclOptions Flags,
93469360
}
93479361
// The raw value must be syntactically a simple literal.
93489362
LiteralRawValueExpr = dyn_cast<LiteralExpr>(RawValueExpr.getPtrOrNull());
9349-
if (!LiteralRawValueExpr
9350-
|| isa<InterpolatedStringLiteralExpr>(LiteralRawValueExpr)) {
9363+
if (!isValidEnumRawValueLiteral(LiteralRawValueExpr)) {
93519364
diagnose(RawValueExpr.getPtrOrNull()->getLoc(),
93529365
diag::nonliteral_enum_case_raw_value);
93539366
LiteralRawValueExpr = nullptr;

lib/Sema/TypeCheckDecl.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,15 +1304,6 @@ EnumRawValuesRequest::evaluate(Evaluator &eval, EnumDecl *ED,
13041304
SourceLoc diagLoc = uncheckedRawValueOf(elt)->isImplicit()
13051305
? elt->getLoc()
13061306
: uncheckedRawValueOf(elt)->getLoc();
1307-
if (auto magicLiteralExpr =
1308-
dyn_cast<MagicIdentifierLiteralExpr>(prevValue)) {
1309-
auto kindString =
1310-
magicLiteralExpr->getKindString(magicLiteralExpr->getKind());
1311-
Diags.diagnose(diagLoc, diag::enum_raw_value_magic_literal, kindString);
1312-
elt->setInvalid();
1313-
continue;
1314-
}
1315-
13161307
// Check that the raw value is unique.
13171308
RawValueKey key{prevValue};
13181309
RawValueSource source{elt, lastExplicitValueElt};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
_ = a.init
4+
_ = b.init
5+
6+
enum a : Int { case x = #/ /# } // expected-error {{raw value for enum case must be a literal}}
7+
enum b : String { case x = #file } // expected-error {{raw value for enum case must be a literal}}
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
// {"signature":"deriveBodyRawRepresentable_init(swift::AbstractFunctionDecl*, void*)"}
2-
// RUN: not --crash %target-swift-frontend -typecheck %s
2+
// RUN: not %target-swift-frontend -typecheck %s
33
a enum a : Int { case = #/

validation-test/compiler_crashers_2_fixed/issue-55443.swift

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,20 @@
22

33
// https://github.com/apple/swift/issues/55443
44

5-
enum FooString: String { // expected-error {{'FooString' declares raw type 'String', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-note {{add stubs for conformance}}
6-
case bar1 = #file // expected-error {{use of '#file' literal as raw value for enum case is not supported}}
7-
case bar2 = #function // expected-error {{use of '#function' literal as raw value for enum case is not supported}}
8-
case bar3 = #filePath // expected-error {{use of '#filePath' literal as raw value for enum case is not supported}}
9-
case bar4 = #line // expected-error {{cannot convert value of type 'Int' to raw type 'String'}}
10-
case bar5 = #column // expected-error {{cannot convert value of type 'Int' to raw type 'String'}}
11-
case bar6 = #dsohandle // expected-error {{cannot convert value of type 'UnsafeRawPointer' to raw type 'String'}}
5+
enum FooString: String {
6+
case bar1 = #file // expected-error {{raw value for enum case must be a literal}}
7+
case bar2 = #function // expected-error {{raw value for enum case must be a literal}}
8+
case bar3 = #filePath // expected-error {{raw value for enum case must be a literal}}
9+
case bar4 = #line // expected-error {{raw value for enum case must be a literal}}
10+
case bar5 = #column // expected-error {{raw value for enum case must be a literal}}
11+
case bar6 = #dsohandle // expected-error {{raw value for enum case must be a literal}}
1212
}
1313

14-
enum FooInt: Int { // expected-error {{'FooInt' declares raw type 'Int', but does not conform to RawRepresentable and conformance could not be synthesized}} expected-note {{add stubs for conformance}}
15-
case bar1 = #file // expected-error {{cannot convert value of type 'String' to raw type 'Int'}}
16-
case bar2 = #function // expected-error {{cannot convert value of type 'String' to raw type 'Int'}}
17-
case bar3 = #filePath // expected-error {{cannot convert value of type 'String' to raw type 'Int'}}
18-
case bar4 = #line // expected-error {{use of '#line' literal as raw value for enum case is not supported}}
19-
case bar5 = #column // expected-error {{use of '#column' literal as raw value for enum case is not supported}}
20-
case bar6 = #dsohandle // expected-error {{cannot convert value of type 'UnsafeRawPointer' to raw type 'Int'}}
14+
enum FooInt: Int {
15+
case bar1 = #file // expected-error {{raw value for enum case must be a literal}}
16+
case bar2 = #function // expected-error {{raw value for enum case must be a literal}}
17+
case bar3 = #filePath // expected-error {{raw value for enum case must be a literal}}
18+
case bar4 = #line // expected-error {{raw value for enum case must be a literal}}
19+
case bar5 = #column // expected-error {{raw value for enum case must be a literal}}
20+
case bar6 = #dsohandle // expected-error {{raw value for enum case must be a literal}}
2121
}

0 commit comments

Comments
 (0)