[PATCH] Recover from errors in enum definition.

Serge Pavlov sepavloff at gmail.com
Wed Nov 6 19:33:04 PST 2013


sepavloff added you to the CC list for the revision "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.

http://llvm-reviews.chandlerc.com/D2116

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

Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -475,6 +475,7 @@
 def err_expected_catch : Error<"expected catch">;
 def err_expected_lbrace_or_comma : Error<"expected '{' or ','">;
 def err_expected_rbrace_or_comma : Error<"expected '}' or ','">;
+def err_expected_rbrace_comma_or_equal : Error<"expected '}' or ',' or '='">;
 def err_expected_rsquare_or_comma : Error<"expected ']' or ','">;
 def err_using_namespace_in_class : Error<
   "'using namespace' is not allowed in classes">;
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -3724,7 +3724,15 @@
   Decl *LastEnumConstDecl = 0;
 
   // Parse the enumerator-list.
-  while (Tok.is(tok::identifier)) {
+  while (Tok.isNot(tok::r_brace)) {
+    if (Tok.isNot(tok::identifier)) {
+      Diag(Tok.getLocation(), diag::err_expected_ident);
+      SkipUntil(tok::comma, tok::r_brace, true, true);
+      if (Tok.isNot(tok::comma))
+        break;
+      ConsumeToken();
+      continue;
+    }
     IdentifierInfo *Ident = Tok.getIdentifierInfo();
     SourceLocation IdentLoc = ConsumeToken();
 
@@ -3738,7 +3746,9 @@
     ExprResult AssignedVal;
     ParsingDeclRAIIObject PD(*this, ParsingDeclRAIIObject::NoParent);
 
+    bool EqualSeen = false;
     if (Tok.is(tok::equal)) {
+      EqualSeen = true;
       EqualLoc = ConsumeToken();
       AssignedVal = ParseConstantExpression();
       if (AssignedVal.isInvalid())
@@ -3764,19 +3774,29 @@
       continue;
     }
 
-    if (Tok.isNot(tok::comma))
+    if (Tok.is(tok::r_brace))
       break;
+    if (Tok.isNot(tok::comma)) {
+      Diag(Tok.getLocation(),
+        EqualSeen ? diag::err_expected_rbrace_or_comma
+                  : diag::err_expected_rbrace_comma_or_equal);
+      SkipUntil(tok::comma, tok::r_brace, true, true);
+      if (Tok.isNot(tok::comma))
+        break;
+    }
+
     SourceLocation CommaLoc = ConsumeToken();
 
-    if (Tok.isNot(tok::identifier)) {
+    if (Tok.is(tok::r_brace)) {
       if (!getLangOpts().C99 && !getLangOpts().CPlusPlus11)
         Diag(CommaLoc, getLangOpts().CPlusPlus ?
                diag::ext_enumerator_list_comma_cxx :
                diag::ext_enumerator_list_comma_c)
           << FixItHint::CreateRemoval(CommaLoc);
       else if (getLangOpts().CPlusPlus11)
         Diag(CommaLoc, diag::warn_cxx98_compat_enumerator_list_comma)
           << FixItHint::CreateRemoval(CommaLoc);
+      break;
     }
   }
 
Index: test/Parser/cxx0x-ambig.cpp
===================================================================
--- test/Parser/cxx0x-ambig.cpp
+++ test/Parser/cxx0x-ambig.cpp
@@ -48,7 +48,7 @@
   };
   // 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 @@
   };
   // 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 {
Index: test/Parser/declarators.c
===================================================================
--- test/Parser/declarators.c
+++ test/Parser/declarators.c
@@ -113,3 +113,32 @@
   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 '}' or ',' or '='}}
+  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; }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2116.1.patch
Type: text/x-patch
Size: 4267 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131106/a2df6f37/attachment.bin>


More information about the cfe-commits mailing list