diff options
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 203 |
1 files changed, 152 insertions, 51 deletions
diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 30a9120a5106..59b491abfd15 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -218,6 +218,7 @@ void Parser::ParseCXXNonStaticMemberInitializer(Decl *VarD) { Eof.startToken(); Eof.setKind(tok::eof); Eof.setLocation(Tok.getLocation()); + Eof.setEofData(VarD); Toks.push_back(Eof); } @@ -308,10 +309,17 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Introduce the parameter into scope. Actions.ActOnDelayedCXXMethodParameter(getCurScope(), LM.DefaultArgs[I].Param); - if (CachedTokens *Toks = LM.DefaultArgs[I].Toks) { - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); + // Mark the end of the default argument so that we know when to stop when + // we parse it later on. + Token LastDefaultArgToken = Toks->back(); + Token DefArgEnd; + DefArgEnd.startToken(); + DefArgEnd.setKind(tok::eof); + DefArgEnd.setLocation(LastDefaultArgToken.getLocation().getLocWithOffset( + LastDefaultArgToken.getLength())); + DefArgEnd.setEofData(LM.DefaultArgs[I].Param); + Toks->push_back(DefArgEnd); // Parse the default argument from its saved token stream. Toks->push_back(Tok); // So that the current token doesn't get lost @@ -336,11 +344,13 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { DefArgResult = ParseBraceInitializer(); } else DefArgResult = ParseAssignmentExpression(); - if (DefArgResult.isInvalid()) + DefArgResult = Actions.CorrectDelayedTyposInExpr(DefArgResult); + if (DefArgResult.isInvalid()) { Actions.ActOnParamDefaultArgumentError(LM.DefaultArgs[I].Param, EqualLoc); - else { - if (!TryConsumeToken(tok::cxx_defaultarg_end)) { + } else { + if (Tok.isNot(tok::eof) || + Tok.getEofData() != LM.DefaultArgs[I].Param) { // The last two tokens are the terminator and the saved value of // Tok; the last token in the default argument is the one before // those. @@ -353,12 +363,12 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { DefArgResult.get()); } - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseAssignmentExpression went over the default arg tokens!"); // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + // Skip through until we reach the 'end of default argument' token. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.DefaultArgs[I].Param) ConsumeAnyToken(); delete Toks; @@ -366,6 +376,80 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { } } + // Parse a delayed exception-specification, if there is one. + if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + // Add the 'stop' token. + Token LastExceptionSpecToken = Toks->back(); + Token ExceptionSpecEnd; + ExceptionSpecEnd.startToken(); + ExceptionSpecEnd.setKind(tok::eof); + ExceptionSpecEnd.setLocation( + LastExceptionSpecToken.getLocation().getLocWithOffset( + LastExceptionSpecToken.getLength())); + ExceptionSpecEnd.setEofData(LM.Method); + Toks->push_back(ExceptionSpecEnd); + + // Parse the default argument from its saved token stream. + Toks->push_back(Tok); // So that the current token doesn't get lost + PP.EnterTokenStream(&Toks->front(), Toks->size(), true, false); + + // Consume the previously-pushed token. + ConsumeAnyToken(); + + // C++11 [expr.prim.general]p3: + // If a declaration declares a member function or member function + // template of a class X, the expression this is a prvalue of type + // "pointer to cv-qualifier-seq X" between the optional cv-qualifer-seq + // and the end of the function-definition, member-declarator, or + // declarator. + CXXMethodDecl *Method; + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(LM.Method)) + Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + else + Method = cast<CXXMethodDecl>(LM.Method); + + Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), + Method->getTypeQualifiers(), + getLangOpts().CPlusPlus11); + + // Parse the exception-specification. + SourceRange SpecificationRange; + SmallVector<ParsedType, 4> DynamicExceptions; + SmallVector<SourceRange, 4> DynamicExceptionRanges; + ExprResult NoexceptExpr; + CachedTokens *ExceptionSpecTokens; + + ExceptionSpecificationType EST + = tryParseExceptionSpecification(/*Delayed=*/false, SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, NoexceptExpr, + ExceptionSpecTokens); + + if (Tok.isNot(tok::eof) || Tok.getEofData() != LM.Method) + Diag(Tok.getLocation(), diag::err_except_spec_unparsed); + + // Attach the exception-specification to the method. + Actions.actOnDelayedExceptionSpecification(LM.Method, EST, + SpecificationRange, + DynamicExceptions, + DynamicExceptionRanges, + NoexceptExpr.isUsable()? + NoexceptExpr.get() : nullptr); + + // There could be leftover tokens (e.g. because of an error). + // Skip through until we reach the original token position. + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + // Clean up the remaining EOF token. + if (Tok.is(tok::eof) && Tok.getEofData() == LM.Method) + ConsumeAnyToken(); + + delete Toks; + LM.ExceptionSpecTokens = nullptr; + } + PrototypeScope.Exit(); // Finish the delayed C++ method declaration. @@ -400,10 +484,16 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { Actions.ActOnReenterTemplateScope(getCurScope(), LM.D); ++CurTemplateDepthTracker; } - // Save the current token position. - SourceLocation origLoc = Tok.getLocation(); assert(!LM.Toks.empty() && "Empty body!"); + Token LastBodyToken = LM.Toks.back(); + Token BodyEnd; + BodyEnd.startToken(); + BodyEnd.setKind(tok::eof); + BodyEnd.setLocation( + LastBodyToken.getLocation().getLocWithOffset(LastBodyToken.getLength())); + BodyEnd.setEofData(LM.D); + LM.Toks.push_back(BodyEnd); // Append the current token at the end of the new token stream so that it // doesn't get lost. LM.Toks.push_back(Tok); @@ -421,12 +511,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (Tok.is(tok::kw_try)) { ParseFunctionTryBlock(LM.D, FnScope); - assert(!PP.getSourceManager().isBeforeInTranslationUnit(origLoc, - Tok.getLocation()) && - "ParseFunctionTryBlock went over the cached tokens!"); - // There could be leftover tokens (e.g. because of an error). - // Skip through until we reach the original token position. - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) ConsumeAnyToken(); return; } @@ -437,7 +526,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (!Tok.is(tok::l_brace)) { FnScope.Exit(); Actions.ActOnFinishFunctionBody(LM.D, nullptr); - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) + + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) ConsumeAnyToken(); return; } @@ -457,17 +550,11 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { if (LM.D) LM.D->getAsFunction()->setLateTemplateParsed(false); - if (Tok.getLocation() != origLoc) { - // Due to parsing error, we either went over the cached tokens or - // there are still cached tokens left. If it's the latter case skip the - // leftover tokens. - // Since this is an uncommon situation that should be avoided, use the - // expensive isBeforeInTranslationUnit call. - if (PP.getSourceManager().isBeforeInTranslationUnit(Tok.getLocation(), - origLoc)) - while (Tok.getLocation() != origLoc && Tok.isNot(tok::eof)) - ConsumeAnyToken(); - } + while (Tok.isNot(tok::eof)) + ConsumeAnyToken(); + + if (Tok.is(tok::eof) && Tok.getEofData() == LM.D) + ConsumeAnyToken(); if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(LM.D)) Actions.ActOnFinishInlineMethodDef(MD); @@ -540,17 +627,21 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { // The next token should be our artificial terminating EOF token. if (Tok.isNot(tok::eof)) { - SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); - if (!EndLoc.isValid()) - EndLoc = Tok.getLocation(); - // No fixit; we can't recover as if there were a semicolon here. - Diag(EndLoc, diag::err_expected_semi_decl_list); + if (!Init.isInvalid()) { + SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); + if (!EndLoc.isValid()) + EndLoc = Tok.getLocation(); + // No fixit; we can't recover as if there were a semicolon here. + Diag(EndLoc, diag::err_expected_semi_decl_list); + } // Consume tokens until we hit the artificial EOF. while (Tok.isNot(tok::eof)) ConsumeAnyToken(); } - ConsumeAnyToken(); + // Make sure this is *our* artificial EOF token. + if (Tok.getEofData() == MI.Field) + ConsumeAnyToken(); } /// ConsumeAndStoreUntil - Consume and store the token at the passed token @@ -891,11 +982,13 @@ private: /// ConsumeAndStoreInitializer - Consume and store the token at the passed token /// container until the end of the current initializer expression (either a /// default argument or an in-class initializer for a non-static data member). -/// The final token is not consumed. +/// +/// Returns \c true if we reached the end of something initializer-shaped, +/// \c false if we bailed out. bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, CachedInitKind CIK) { // We always want this function to consume at least one token if not at EOF. - bool IsFirstTokenConsumed = true; + bool IsFirstToken = true; // Number of possible unclosed <s we've seen so far. These might be templates, // and might not, but if there were none of them (or we know for sure that @@ -942,7 +1035,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, case CIK_DefaultArgument: bool InvalidAsDeclaration = false; Result = TryParseParameterDeclarationClause( - &InvalidAsDeclaration, /*VersusTemplateArgument*/true); + &InvalidAsDeclaration, /*VersusTemplateArgument=*/true); // If this is an expression or a declaration with a missing // 'typename', assume it's not a declaration. if (Result == TPResult::Ambiguous && InvalidAsDeclaration) @@ -1014,6 +1107,7 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, Toks.push_back(Tok); ConsumeToken(); if (Tok.is(tok::less)) { + ++AngleCount; ++KnownTemplateCount; Toks.push_back(Tok); ConsumeToken(); @@ -1063,21 +1157,28 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, // Since the user wasn't looking for this token (if they were, it would // already be handled), this isn't balanced. If there is a LHS token at a // higher level, we will assume that this matches the unbalanced token - // and return it. Otherwise, this is a spurious RHS token, which we skip. + // and return it. Otherwise, this is a spurious RHS token, which we + // consume and pass on to downstream code to diagnose. case tok::r_paren: if (CIK == CIK_DefaultArgument) return true; // End of the default argument. - if (ParenCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (ParenCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeParen(); + continue; case tok::r_square: - if (BracketCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (BracketCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeBracket(); + continue; case tok::r_brace: - if (BraceCount && !IsFirstTokenConsumed) - return false; // Matches something. - goto consume_token; + if (BraceCount && !IsFirstToken) + return false; + Toks.push_back(Tok); + ConsumeBrace(); + continue; case tok::code_completion: Toks.push_back(Tok); @@ -1102,6 +1203,6 @@ bool Parser::ConsumeAndStoreInitializer(CachedTokens &Toks, ConsumeToken(); break; } - IsFirstTokenConsumed = false; + IsFirstToken = false; } } |