aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-12-22 00:07:40 +0000
commitbfef399519ca9b8a4b4c6b563253bad7e0eeffe0 (patch)
treedf8df0b0067b381eab470a3b8f28d14a552a6340 /lib/Parse/ParseTemplate.cpp
parent6a0372513edbc473b538d2f724efac50405d6fef (diff)
downloadsrc-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.tar.gz
src-bfef399519ca9b8a4b4c6b563253bad7e0eeffe0.zip
Notes
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r--lib/Parse/ParseTemplate.cpp115
1 files changed, 69 insertions, 46 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 84b7df7295f6..076edb93fa11 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -120,7 +120,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return 0;
@@ -216,7 +216,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
// Error parsing the declarator?
if (!DeclaratorInfo.hasName()) {
// If so, skip until the semi-colon or a }.
- SkipUntil(tok::r_brace, true, true);
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);
if (Tok.is(tok::semi))
ConsumeToken();
return 0;
@@ -236,6 +236,35 @@ Parser::ParseSingleDeclarationAfterTemplate(
<< FixItHint::CreateRemoval(DS.getStorageClassSpecLoc());
DS.ClearStorageClassSpecs();
}
+
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) {
+ if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) {
+ // If the declarator-id is not a template-id, issue a diagnostic and
+ // recover by ignoring the 'template' keyword.
+ Diag(Tok, diag::err_template_defn_explicit_instantiation) << 0;
+ return ParseFunctionDefinition(DeclaratorInfo, ParsedTemplateInfo(),
+ &LateParsedAttrs);
+ } else {
+ SourceLocation LAngleLoc
+ = PP.getLocForEndOfToken(TemplateInfo.TemplateLoc);
+ Diag(DeclaratorInfo.getIdentifierLoc(),
+ diag::err_explicit_instantiation_with_definition)
+ << SourceRange(TemplateInfo.TemplateLoc)
+ << FixItHint::CreateInsertion(LAngleLoc, "<>");
+
+ // Recover as if it were an explicit specialization.
+ TemplateParameterLists FakedParamLists;
+ FakedParamLists.push_back(Actions.ActOnTemplateParameterList(
+ 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, 0, 0,
+ LAngleLoc));
+
+ return ParseFunctionDefinition(
+ DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists,
+ /*isSpecialization=*/true,
+ /*LastParamListWasEmpty=*/true),
+ &LateParsedAttrs);
+ }
+ }
return ParseFunctionDefinition(DeclaratorInfo, TemplateInfo,
&LateParsedAttrs);
}
@@ -247,7 +276,7 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (Tok.is(tok::comma)) {
Diag(Tok, diag::err_multiple_template_declarators)
<< (int)TemplateInfo.Kind;
- SkipUntil(tok::semi, true, false);
+ SkipUntil(tok::semi);
return ThisDecl;
}
@@ -320,7 +349,8 @@ Parser::ParseTemplateParameterList(unsigned Depth,
} else {
// If we failed to parse a template parameter, skip until we find
// a comma or closing brace.
- SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
+ SkipUntil(tok::comma, tok::greater, tok::greatergreater,
+ StopAtSemi | StopBeforeMatch);
}
// Did we find a comma or the end of the template parameter list?
@@ -334,7 +364,8 @@ Parser::ParseTemplateParameterList(unsigned Depth,
// try to get out of the expression. This error is currently
// subsumed by whatever goes on in ParseTemplateParameter.
Diag(Tok.getLocation(), diag::err_expected_comma_greater);
- SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
+ SkipUntil(tok::comma, tok::greater, tok::greatergreater,
+ StopAtSemi | StopBeforeMatch);
return false;
}
}
@@ -582,7 +613,8 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
if (DefaultArg.isInvalid()) {
Diag(Tok.getLocation(),
diag::err_default_template_template_parameter_not_template);
- SkipUntil(tok::comma, tok::greater, tok::greatergreater, true, true);
+ SkipUntil(tok::comma, tok::greater, tok::greatergreater,
+ StopAtSemi | StopBeforeMatch);
}
}
@@ -632,7 +664,7 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
DefaultArg = ParseAssignmentExpression();
if (DefaultArg.isInvalid())
- SkipUntil(tok::comma, tok::greater, true, true);
+ SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
}
// Create the parameter.
@@ -650,6 +682,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) {
/// \param RAngleLoc the location of the consumed '>'.
///
/// \param ConsumeLastToken if true, the '>' is not consumed.
+///
+/// \returns true, if current token does not start with '>', false otherwise.
bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc,
bool ConsumeLastToken) {
// What will be left once we've consumed the '>'.
@@ -794,8 +828,10 @@ Parser::ParseTemplateIdAfterTemplateName(TemplateTy Template,
if (Invalid) {
// Try to find the closing '>'.
- SkipUntil(tok::greater, true, !ConsumeLastToken);
-
+ if (ConsumeLastToken)
+ SkipUntil(tok::greater, StopAtSemi);
+ else
+ SkipUntil(tok::greater, StopAtSemi | StopBeforeMatch);
return true;
}
}
@@ -1160,7 +1196,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
}
if (Arg.isInvalid()) {
- SkipUntil(tok::comma, tok::greater, true, true);
+ SkipUntil(tok::comma, tok::greater, StopAtSemi | StopBeforeMatch);
return true;
}
@@ -1212,30 +1248,19 @@ SourceRange Parser::ParsedTemplateInfo::getSourceRange() const {
return R;
}
-void Parser::LateTemplateParserCallback(void *P, const FunctionDecl *FD) {
- ((Parser*)P)->LateTemplateParser(FD);
-}
-
-
-void Parser::LateTemplateParser(const FunctionDecl *FD) {
- LateParsedTemplatedFunction *LPT = LateParsedTemplateMap[FD];
- if (LPT) {
- ParseLateTemplatedFuncDef(*LPT);
- return;
- }
-
- llvm_unreachable("Late templated function without associated lexed tokens");
+void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) {
+ ((Parser *)P)->ParseLateTemplatedFuncDef(LPT);
}
/// \brief Late parse a C++ function template in Microsoft mode.
-void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
- if(!LMT.D)
+void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
+ if (!LPT.D)
return;
// Get the FunctionDecl.
- FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LMT.D);
+ FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D);
FunctionDecl *FunD =
- FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LMT.D);
+ FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D);
// Track template parameter depth.
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
@@ -1253,7 +1278,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
}
// Reenter template scopes from outermost to innermost.
- SmallVector<DeclContext*, 4>::reverse_iterator II =
+ SmallVectorImpl<DeclContext *>::reverse_iterator II =
DeclContextsToReenter.rbegin();
for (; II != DeclContextsToReenter.rend(); ++II) {
if (ClassTemplatePartialSpecializationDecl *MD =
@@ -1263,12 +1288,14 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
Actions.ActOnReenterTemplateScope(getCurScope(), MD);
++CurTemplateDepthTracker;
} else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
- bool ManageScope = MD->getDescribedClassTemplate() != 0;
+ bool IsClassTemplate = MD->getDescribedClassTemplate() != 0;
TemplateParamScopeStack.push_back(
- new ParseScope(this, Scope::TemplateParamScope, ManageScope));
+ new ParseScope(this, Scope::TemplateParamScope,
+ /*ManageScope*/IsClassTemplate));
Actions.ActOnReenterTemplateScope(getCurScope(),
MD->getDescribedClassTemplate());
- ++CurTemplateDepthTracker;
+ if (IsClassTemplate)
+ ++CurTemplateDepthTracker;
}
TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
Actions.PushDeclContext(Actions.getCurScope(), *II);
@@ -1281,15 +1308,15 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
++CurTemplateDepthTracker;
}
- Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
+ Actions.ActOnReenterTemplateScope(getCurScope(), LPT.D);
++CurTemplateDepthTracker;
- assert(!LMT.Toks.empty() && "Empty body!");
+ assert(!LPT.Toks.empty() && "Empty body!");
// Append the current token at the end of the new token stream so that it
// doesn't get lost.
- LMT.Toks.push_back(Tok);
- PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
+ LPT.Toks.push_back(Tok);
+ PP.EnterTokenStream(LPT.Toks.data(), LPT.Toks.size(), true, false);
// Consume the previously pushed token.
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
@@ -1306,34 +1333,30 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);
if (Tok.is(tok::kw_try)) {
- ParseFunctionTryBlock(LMT.D, FnScope);
+ ParseFunctionTryBlock(LPT.D, FnScope);
} else {
if (Tok.is(tok::colon))
- ParseConstructorInitializer(LMT.D);
+ ParseConstructorInitializer(LPT.D);
else
- Actions.ActOnDefaultCtorInitializers(LMT.D);
+ Actions.ActOnDefaultCtorInitializers(LPT.D);
if (Tok.is(tok::l_brace)) {
assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
TemplateParameterDepth) &&
"TemplateParameterDepth should be greater than the depth of "
"current template being instantiated!");
- ParseFunctionStatementBody(LMT.D, FnScope);
- Actions.MarkAsLateParsedTemplate(FunD, false);
+ ParseFunctionStatementBody(LPT.D, FnScope);
+ Actions.UnmarkAsLateParsedTemplate(FunD);
} else
- Actions.ActOnFinishFunctionBody(LMT.D, 0);
+ Actions.ActOnFinishFunctionBody(LPT.D, 0);
}
// Exit scopes.
FnScope.Exit();
- SmallVector<ParseScope*, 4>::reverse_iterator I =
+ SmallVectorImpl<ParseScope *>::reverse_iterator I =
TemplateParamScopeStack.rbegin();
for (; I != TemplateParamScopeStack.rend(); ++I)
delete *I;
-
- DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D);
- if (grp)
- Actions.getASTConsumer().HandleTopLevelDecl(grp.get());
}
/// \brief Lex a delayed template function for late parsing.