diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-01-02 19:18:08 +0000 |
commit | bab175ec4b075c8076ba14c762900392533f6ee4 (patch) | |
tree | 01f4f29419a2cb10abe13c1e63cd2a66068b0137 /lib/Parse/ParseCXXInlineMethods.cpp | |
parent | 8b7a8012d223fac5d17d16a66bb39168a9a1dfc0 (diff) |
Notes
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 39fcc8270419c..c52b61e7e9832 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -319,7 +319,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Introduce the parameter into scope. bool HasUnparsed = Param->hasUnparsedDefaultArg(); Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); - if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { + std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks); + if (Toks) { // Mark the end of the default argument so that we know when to stop when // we parse it later on. Token LastDefaultArgToken = Toks->back(); @@ -377,9 +378,6 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { if (Tok.is(tok::eof) && Tok.getEofData() == Param) ConsumeAnyToken(); - - delete Toks; - LM.DefaultArgs[I].Toks = nullptr; } else if (HasUnparsed) { assert(Param->hasInheritedDefaultArg()); FunctionDecl *Old = cast<FunctionDecl>(LM.Method)->getPreviousDecl(); @@ -832,22 +830,30 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { } } - if (Tok.isOneOf(tok::identifier, tok::kw_template)) { + if (Tok.is(tok::identifier)) { Toks.push_back(Tok); ConsumeToken(); - } else if (Tok.is(tok::code_completion)) { - Toks.push_back(Tok); - ConsumeCodeCompletionToken(); - // Consume the rest of the initializers permissively. - // FIXME: We should be able to perform code-completion here even if - // there isn't a subsequent '{' token. - MightBeTemplateArgument = true; - break; } else { break; } } while (Tok.is(tok::coloncolon)); + if (Tok.is(tok::code_completion)) { + Toks.push_back(Tok); + ConsumeCodeCompletionToken(); + if (Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype)) { + // Could be the start of another member initializer (the ',' has not + // been written yet) + continue; + } + } + + if (Tok.is(tok::comma)) { + // The initialization is missing, we'll diagnose it later. + Toks.push_back(Tok); + ConsumeToken(); + continue; + } if (Tok.is(tok::less)) MightBeTemplateArgument = true; @@ -888,6 +894,26 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { // means the initializer is malformed; we'll diagnose it later. if (!getLangOpts().CPlusPlus11) return false; + + const Token &PreviousToken = Toks[Toks.size() - 2]; + if (!MightBeTemplateArgument && + !PreviousToken.isOneOf(tok::identifier, tok::greater, + tok::greatergreater)) { + // If the opening brace is not preceded by one of these tokens, we are + // missing the mem-initializer-id. In order to recover better, we need + // to use heuristics to determine if this '{' is most likely the + // begining of a brace-init-list or the function body. + // Check the token after the corresponding '}'. + TentativeParsingAction PA(*this); + if (SkipUntil(tok::r_brace) && + !Tok.isOneOf(tok::comma, tok::ellipsis, tok::l_brace)) { + // Consider there was a malformed initializer and this is the start + // of the function body. We'll diagnose it later. + PA.Revert(); + return false; + } + PA.Revert(); + } } // Grab the initializer (or the subexpression of the template argument). |