diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticParseKinds.td | 2 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 34 | ||||
-rw-r--r-- | clang/test/Parser/cxx0x-ambig.cpp | 4 | ||||
-rw-r--r-- | clang/test/Parser/declarators.c | 34 |
4 files changed, 67 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 2f14a50cf70..15804e99d9e 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -354,6 +354,8 @@ def err_paren_after_colon_colon : Error< "unexpected parenthesis after '::'">; def err_function_definition_not_allowed : Error< "function definition is not allowed here">; +def err_expected_end_of_enumerator : Error< + "expected '= constant-expression' or end of enumerator definition">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 27d8531c1fd..f664cf20409 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -3888,7 +3888,16 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { Decl *LastEnumConstDecl = 0; // Parse the enumerator-list. - while (Tok.is(tok::identifier)) { + while (Tok.isNot(tok::r_brace)) { + // Parse enumerator. If failed, try skipping till the start of the next + // enumerator definition. + if (Tok.isNot(tok::identifier)) { + Diag(Tok.getLocation(), diag::err_expected) << tok::identifier; + if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch) && + TryConsumeToken(tok::comma)) + continue; + break; + } IdentifierInfo *Ident = Tok.getIdentifierInfo(); SourceLocation IdentLoc = ConsumeToken(); @@ -3905,7 +3914,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { if (TryConsumeToken(tok::equal, EqualLoc)) { AssignedVal = ParseConstantExpression(); if (AssignedVal.isInvalid()) - SkipUntil(tok::comma, tok::r_brace, StopAtSemi | StopBeforeMatch); + SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch); } // Install the enumerator constant into EnumDecl. @@ -3927,11 +3936,25 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { continue; } + // Emumerator definition must be finished, only comma or r_brace are + // allowed here. SourceLocation CommaLoc; - if (!TryConsumeToken(tok::comma, CommaLoc)) - break; + if (Tok.isNot(tok::r_brace) && !TryConsumeToken(tok::comma, CommaLoc)) { + if (EqualLoc.isValid()) + Diag(Tok.getLocation(), diag::err_expected_either) << tok::r_brace + << tok::comma; + else + Diag(Tok.getLocation(), diag::err_expected_end_of_enumerator); + if (SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch)) { + if (TryConsumeToken(tok::comma, CommaLoc)) + continue; + } else { + break; + } + } - if (Tok.isNot(tok::identifier)) { + // If comma is followed by r_brace, emit appropriate warning. + if (Tok.is(tok::r_brace) && CommaLoc.isValid()) { if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11) Diag(CommaLoc, getLangOpts().CPlusPlus ? diag::ext_enumerator_list_comma_cxx : @@ -3940,6 +3963,7 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { else if (getLangOpts().CPlusPlus11) Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma) << FixItHint::CreateRemoval(CommaLoc); + break; } } diff --git a/clang/test/Parser/cxx0x-ambig.cpp b/clang/test/Parser/cxx0x-ambig.cpp index 4c22ed3a9bb..b06f432c435 100644 --- a/clang/test/Parser/cxx0x-ambig.cpp +++ b/clang/test/Parser/cxx0x-ambig.cpp @@ -48,7 +48,7 @@ namespace bitfield { }; // This could be a bit-field. struct S2 { - enum E : T { a = 1, b = 2, c = 3, 4 }; // expected-error {{non-integral type}} expected-error {{expected '}'}} expected-note {{to match}} + enum E : T { a = 1, b = 2, c = 3, 4 }; // expected-error {{non-integral type}} expected-error {{expected identifier}} }; struct S3 { enum E : int { a = 1, b = 2, c = 3, d }; // ok, defines an enum @@ -64,7 +64,7 @@ namespace bitfield { }; // This could be a bit-field. struct S6 { - enum E : int { 1 }; // expected-error {{expected '}'}} expected-note {{to match}} + enum E : int { 1 }; // expected-error {{expected identifier}} }; struct U { diff --git a/clang/test/Parser/declarators.c b/clang/test/Parser/declarators.c index 210a8e2befc..f77c2d2192f 100644 --- a/clang/test/Parser/declarators.c +++ b/clang/test/Parser/declarators.c @@ -113,3 +113,37 @@ struct EnumBitfield { // expected-warning {{struct without named members is a GN struct S { int n; }: // expected-error {{expected ';'}} }; + +// PR10982 +enum E11 { + A1 = 1, +}; + +enum E12 { + , // expected-error{{expected identifier}} + A2 +}; +void func_E12(enum E12 *p) { *p = A2; } + +enum E13 { + 1D, // expected-error{{expected identifier}} + A3 +}; +void func_E13(enum E13 *p) { *p = A3; } + +enum E14 { + A4 12, // expected-error{{expected '= constant-expression' or end of enumerator definition}} + A4a +}; +void func_E14(enum E14 *p) { *p = A4a; } + +enum E15 { + A5=12 4, // expected-error{{expected '}' or ','}} + A5a +}; +void func_E15(enum E15 *p) { *p = A5a; } + +enum E16 { + A6; // expected-error{{expected '= constant-expression' or end of enumerator definition}} + A6a +}; |