summaryrefslogtreecommitdiffstats
path: root/clang/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-06-25 21:37:02 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-06-25 21:37:02 +0000
commit369b9f997cc2bf19aebe0220ab484b80c5932eb2 (patch)
treeca6bfb0919b31794f0c6e133bbe2a81b55a48a7f /clang/lib/Parse/ParseDecl.cpp
parentc272bab5a51067accdfc29d6339d3ce8717baf9e (diff)
downloadbcm5719-llvm-369b9f997cc2bf19aebe0220ab484b80c5932eb2.tar.gz
bcm5719-llvm-369b9f997cc2bf19aebe0220ab484b80c5932eb2.zip
Extend the "expected ';' after struct" logic to also apply to enums, and to
struct and enum forward-declarations. llvm-svn: 159164
Diffstat (limited to 'clang/lib/Parse/ParseDecl.cpp')
-rw-r--r--clang/lib/Parse/ParseDecl.cpp27
1 files changed, 23 insertions, 4 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 96c57581e85..7d0f9c22cb0 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3156,8 +3156,17 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
} else {
TUK = Sema::TUK_Definition;
}
- } else if (Tok.is(tok::semi) && DSC != DSC_type_specifier) {
- TUK = (DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration);
+ } else if (DSC != DSC_type_specifier &&
+ (Tok.is(tok::semi) ||
+ (Tok.isAtStartOfLine() && !isValidAfterTypeSpecifier()))) {
+ TUK = DS.isFriendSpecified() ? Sema::TUK_Friend : Sema::TUK_Declaration;
+ if (Tok.isNot(tok::semi)) {
+ // A semicolon was missing after this declaration. Diagnose and recover.
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl,
+ "enum");
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::semi);
+ }
} else {
TUK = Sema::TUK_Reference;
}
@@ -3248,9 +3257,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS,
return;
}
- if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference) {
+ if (Tok.is(tok::l_brace) && TUK != Sema::TUK_Reference)
ParseEnumBody(StartLoc, TagDecl);
- }
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
@@ -3355,6 +3363,17 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
EnumScope.Exit();
Actions.ActOnTagFinishDefinition(getCurScope(), EnumDecl,
T.getCloseLocation());
+
+ // The next token must be valid after an enum definition. If not, a ';'
+ // was probably forgotten.
+ if (!isValidAfterTypeSpecifier()) {
+ ExpectAndConsume(tok::semi, diag::err_expected_semi_after_tagdecl, "enum");
+ // Push this token back into the preprocessor and change our current token
+ // to ';' so that the rest of the code recovers as though there were an
+ // ';' after the definition.
+ PP.EnterToken(Tok);
+ Tok.setKind(tok::semi);
+ }
}
/// isTypeSpecifierQualifier - Return true if the current token could be the
OpenPOWER on IntegriCloud