[PATCH] Recover from errors in enum definition.

Serge Pavlov sepavloff at gmail.com
Mon Dec 30 10:13:50 PST 2013


  Updated patch according to Alp Toker's notes.

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

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D2116?vs=6309&id=6316#toc

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
@@ -354,6 +354,8 @@
   "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<
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -3888,7 +3888,16 @@
   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 @@
     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,19 +3936,34 @@
       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 :
                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,37 @@
   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
+};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D2116.3.patch
Type: text/x-patch
Size: 4865 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131230/b26098bf/attachment.bin>


More information about the cfe-commits mailing list