[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