summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td2
-rw-r--r--clang/lib/Parse/ParseDecl.cpp34
-rw-r--r--clang/test/Parser/cxx0x-ambig.cpp4
-rw-r--r--clang/test/Parser/declarators.c34
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
+};
OpenPOWER on IntegriCloud