r198259 - Recover from errors in enum definition

Serge Pavlov sepavloff at gmail.com
Mon Dec 30 22:26:04 PST 2013


Author: sepavloff
Date: Tue Dec 31 00:26:03 2013
New Revision: 198259

URL: http://llvm.org/viewvc/llvm-project?rev=198259&view=rev
Log:
Recover from errors in enum definition

Previously any error in enum definition body stopped parsing it. With this
change parser tries to recover from errors.
The patch fixes PR10982.

Differential Revision: http://llvm-reviews.chandlerc.com/D2018

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/test/Parser/cxx0x-ambig.cpp
    cfe/trunk/test/Parser/declarators.c

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=198259&r1=198258&r2=198259&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Tue Dec 31 00:26:03 2013
@@ -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<

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=198259&r1=198258&r2=198259&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Tue Dec 31 00:26:03 2013
@@ -3888,7 +3888,16 @@ void Parser::ParseEnumBody(SourceLocatio
   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(SourceLocatio
     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(SourceLocatio
       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(SourceLocatio
       else if (getLangOpts().CPlusPlus11)
         Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
           << FixItHint::CreateRemoval(CommaLoc);
+      break;
     }
   }
 

Modified: cfe/trunk/test/Parser/cxx0x-ambig.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-ambig.cpp?rev=198259&r1=198258&r2=198259&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-ambig.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-ambig.cpp Tue Dec 31 00:26:03 2013
@@ -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 {

Modified: cfe/trunk/test/Parser/declarators.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/declarators.c?rev=198259&r1=198258&r2=198259&view=diff
==============================================================================
--- cfe/trunk/test/Parser/declarators.c (original)
+++ cfe/trunk/test/Parser/declarators.c Tue Dec 31 00:26:03 2013
@@ -113,3 +113,37 @@ struct EnumBitfield { // expected-warnin
   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
+};





More information about the cfe-commits mailing list