summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorSerge Pavlov <sepavloff@gmail.com>2013-12-31 06:26:03 +0000
committerSerge Pavlov <sepavloff@gmail.com>2013-12-31 06:26:03 +0000
commit2e3ecb660ad8d66fffb3a86628f3c952e10f6963 (patch)
treed12577a4984ecc62795128e51131289855de801d /clang/lib/Parse/ParseDecl.cpp
parentdf912ba6ecf4848fd60a00a04bc8982ae7883994 (diff)
downloadbcm5719-llvm-2e3ecb660ad8d66fffb3a86628f3c952e10f6963.tar.gz
bcm5719-llvm-2e3ecb660ad8d66fffb3a86628f3c952e10f6963.zip
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 llvm-svn: 198259
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp34
1 files changed, 29 insertions, 5 deletions
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;
}
}
OpenPOWER on IntegriCloud