aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
authorSebastian Redl <sebastian.redl@getdesigned.at>2011-09-30 08:32:17 +0000
committerSebastian Redl <sebastian.redl@getdesigned.at>2011-09-30 08:32:17 +0000
commita891a32d3762ee641a29c091d286f2a7432671a5 (patch)
tree46d7bf8dc01e934f17288c34fde07b78c183db20 /lib/Parse/ParseCXXInlineMethods.cpp
parent8dfac0baaf0f81d3945bcb306480e358ba8d1f08 (diff)
Fix a bug in the token caching for inline constructors in C++11, and improve error recovery in both dialects. This should fix the GCC test suite failures as well.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@140847 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp69
1 files changed, 41 insertions, 28 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp
index 923a5587e6..40e36f0a0b 100644
--- a/lib/Parse/ParseCXXInlineMethods.cpp
+++ b/lib/Parse/ParseCXXInlineMethods.cpp
@@ -123,31 +123,24 @@ Decl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, ParsingDeclarator &D,
CachedTokens &Toks = LM->Toks;
tok::TokenKind kind = Tok.getKind();
- // We may have a constructor initializer or function-try-block here.
- if (kind == tok::colon || kind == tok::kw_try) {
- // Consume everything up to (and including) the left brace of the
- // function body.
- if (ConsumeAndStoreTryAndInitializers(Toks)) {
- // 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();
- delete getCurrentClass().LateParsedDeclarations.back();
- getCurrentClass().LateParsedDeclarations.pop_back();
- return FnD;
- }
+ // Consume everything up to (and including) the left brace of the
+ // function body.
+ if (ConsumeAndStoreFunctionPrologue(Toks)) {
+ // 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();
+ delete getCurrentClass().LateParsedDeclarations.back();
+ getCurrentClass().LateParsedDeclarations.pop_back();
+ return FnD;
}
-
} else {
- // Begin by storing the '{' token.
- Toks.push_back(Tok);
- ConsumeBrace();
+ // Consume everything up to (and including) the matching right brace.
+ ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
}
- // Consume everything up to (and including) the matching right brace.
- ConsumeAndStoreUntil(tok::r_brace, Toks, /*StopAtSemi=*/false);
// If we're in a function-try-block, we need to store all the catch blocks.
if (kind == tok::kw_try) {
@@ -583,10 +576,11 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2,
/// \brief Consume tokens and store them in the passed token container until
/// we've passed the try keyword and constructor initializers and have consumed
-/// the opening brace of the function body.
+/// the opening brace of the function body. The opening brace will be consumed
+/// if and only if there was no error.
///
-/// \return True on error.
-bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
+/// \return True on error.
+bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) {
if (Tok.is(tok::kw_try)) {
Toks.push_back(Tok);
ConsumeToken();
@@ -613,6 +607,10 @@ bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
else {
assert(kind == tok::l_brace && "Must be left paren or brace here.");
ConsumeBrace();
+ // In C++03, this has to be the start of the function body, which
+ // means the initializer is malformed.
+ if (!getLang().CPlusPlus0x)
+ return false;
}
// Grab the initializer
@@ -620,10 +618,25 @@ bool Parser::ConsumeAndStoreTryAndInitializers(CachedTokens &Toks) {
tok::r_brace,
Toks, /*StopAtSemi=*/true))
return true;
+
+ // Grab the separating comma, if any.
+ if (Tok.is(tok::comma)) {
+ Toks.push_back(Tok);
+ ConsumeToken();
+ }
}
}
- // Grab any remaining garbage to be diagnosed later, and the opening
- // brace of the function body.
- return !ConsumeAndStoreUntil(tok::l_brace, Toks, /*StopAtSemi=*/true);
+ // Grab any remaining garbage to be diagnosed later. We stop when we reach a
+ // brace: an opening one is the function body, while a closing one probably
+ // means we've reached the end of the class.
+ if (!ConsumeAndStoreUntil(tok::l_brace, tok::r_brace, Toks,
+ /*StopAtSemi=*/true, /*ConsumeFinalToken=*/false))
+ return true;
+ if(Tok.isNot(tok::l_brace))
+ return true;
+
+ Toks.push_back(Tok);
+ ConsumeBrace();
+ return false;
}