Improve parser error recovery after a constructor initializer
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58989 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index d9014b6..4071172 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -397,7 +397,8 @@
DeclTy *ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D);
void ParseLexedMethodDefs();
- bool ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks);
+ bool ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks,
+ tok::TokenKind EarlyAbortIf = tok::unknown);
//===--------------------------------------------------------------------===//
// C99 6.9: External Definitions.
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 7d977c1..2f5014b 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/Basic/Diagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/DeclSpec.h"
#include "clang/Parse/Scope.h"
@@ -36,7 +37,19 @@
// We may have a constructor initializer here.
if (Tok.is(tok::colon)) {
// Consume everything up to (and including) the left brace.
- ConsumeAndStoreUntil(tok::l_brace, Toks);
+ if (!ConsumeAndStoreUntil(tok::l_brace, Toks, tok::semi)) {
+ // We didn't find the left-brace we expected after the
+ // constructor initializer.
+ if (Tok.is(tok::semi)) {
+ // We found a semicolon; complain, consume the semicolon, and
+ // don't try to parse this method later.
+ Diag(Tok.getLocation(), diag::err_expected_lbrace);
+ ConsumeAnyToken();
+ getCurTopClassStack().pop();
+ return FnD;
+ }
+ }
+
} else {
// Begin by storing the '{' token.
Toks.push_back(Tok);
@@ -82,9 +95,12 @@
/// ConsumeAndStoreUntil - Consume and store the token at the passed token
/// container until the token 'T' is reached (which gets consumed/stored too).
+/// If EarlyAbortIf is specified, then we will stop early if we find that
+/// token at the top level.
/// Returns true if token 'T' was found.
/// NOTE: This is a specialized version of Parser::SkipUntil.
-bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks) {
+bool Parser::ConsumeAndStoreUntil(tok::TokenKind T, TokensTy &Toks,
+ tok::TokenKind EarlyAbortIf) {
// We always want this function to consume at least one token if the first
// token isn't T and if not at EOF.
bool isFirstTokenConsumed = true;
@@ -96,6 +112,10 @@
return true;
}
+ // If we found the early-abort token, return.
+ if (Tok.is(EarlyAbortIf))
+ return false;
+
switch (Tok.getKind()) {
case tok::eof:
// Ran out of tokens.
diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp
index 6b450b0..a79b6ca 100644
--- a/test/SemaCXX/constructor-initializer.cpp
+++ b/test/SemaCXX/constructor-initializer.cpp
@@ -41,3 +41,7 @@
{
}
};
+
+class G : A {
+ G() : A(10); // expected-error{{expected '{'}}
+};