summaryrefslogtreecommitdiff
path: root/lib/Parse/ParseCXXInlineMethods.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseCXXInlineMethods.cpp')
-rw-r--r--lib/Parse/ParseCXXInlineMethods.cpp203
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;
}
}