aboutsummaryrefslogtreecommitdiff
path: root/lib/Parse/ParseTemplate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseTemplate.cpp')
-rw-r--r--lib/Parse/ParseTemplate.cpp143
1 files changed, 66 insertions, 77 deletions
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 32a78a73a8..84b7df7295 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -39,28 +39,7 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context,
AccessAttrs);
}
-/// \brief RAII class that manages the template parameter depth.
-namespace {
- class TemplateParameterDepthCounter {
- unsigned &Depth;
- unsigned AddedLevels;
-
- public:
- explicit TemplateParameterDepthCounter(unsigned &Depth)
- : Depth(Depth), AddedLevels(0) { }
-
- ~TemplateParameterDepthCounter() {
- Depth -= AddedLevels;
- }
- void operator++() {
- ++Depth;
- ++AddedLevels;
- }
-
- operator unsigned() const { return Depth; }
- };
-}
/// \brief Parse a template declaration or an explicit specialization.
///
@@ -117,7 +96,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
bool isSpecialization = true;
bool LastParamListWasEmpty = false;
TemplateParameterLists ParamLists;
- TemplateParameterDepthCounter Depth(TemplateParameterDepth);
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+
do {
// Consume the 'export', if any.
SourceLocation ExportLoc;
@@ -137,8 +117,8 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
// Parse the '<' template-parameter-list '>'
SourceLocation LAngleLoc, RAngleLoc;
SmallVector<Decl*, 4> TemplateParams;
- if (ParseTemplateParameters(Depth, TemplateParams, LAngleLoc,
- RAngleLoc)) {
+ if (ParseTemplateParameters(CurTemplateDepthTracker.getDepth(),
+ TemplateParams, LAngleLoc, RAngleLoc)) {
// Skip until the semi-colon or a }.
SkipUntil(tok::r_brace, true, true);
if (Tok.is(tok::semi))
@@ -147,14 +127,15 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context,
}
ParamLists.push_back(
- Actions.ActOnTemplateParameterList(Depth, ExportLoc,
+ Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(),
+ ExportLoc,
TemplateLoc, LAngleLoc,
TemplateParams.data(),
TemplateParams.size(), RAngleLoc));
if (!TemplateParams.empty()) {
isSpecialization = false;
- ++Depth;
+ ++CurTemplateDepthTracker;
} else {
LastParamListWasEmpty = true;
}
@@ -214,7 +195,11 @@ Parser::ParseSingleDeclarationAfterTemplate(
if (Tok.is(tok::semi)) {
ProhibitAttributes(prefixAttrs);
DeclEnd = ConsumeToken();
- Decl *Decl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS);
+ Decl *Decl = Actions.ParsedFreeStandingDeclSpec(
+ getCurScope(), AS, DS,
+ TemplateInfo.TemplateParams ? *TemplateInfo.TemplateParams
+ : MultiTemplateParamsArg(),
+ TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation);
DS.complete(Decl);
return Decl;
}
@@ -1164,6 +1149,9 @@ bool Parser::IsTemplateArgumentList(unsigned Skip) {
/// template-argument-list ',' template-argument
bool
Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
+ // Template argument lists are constant-evaluation contexts.
+ EnterExpressionEvaluationContext EvalContext(Actions,Sema::ConstantEvaluated);
+
while (true) {
ParsedTemplateArgument Arg = ParseTemplateArgument();
if (Tok.is(tok::ellipsis)) {
@@ -1196,7 +1184,7 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) {
/// explicit-instantiation:
/// 'extern' [opt] 'template' declaration
///
-/// Note that the 'extern' is a GNU extension and C++0x feature.
+/// Note that the 'extern' is a GNU extension and C++11 feature.
Decl *Parser::ParseExplicitInstantiation(unsigned Context,
SourceLocation ExternLoc,
SourceLocation TemplateLoc,
@@ -1245,53 +1233,56 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
return;
// Get the FunctionDecl.
- FunctionDecl *FD = 0;
- if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
- FD = FunTmpl->getTemplatedDecl();
- else
- FD = cast<FunctionDecl>(LMT.D);
+ FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LMT.D);
+ FunctionDecl *FunD =
+ FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LMT.D);
+ // Track template parameter depth.
+ TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
// To restore the context after late parsing.
Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
SmallVector<ParseScope*, 4> TemplateParamScopeStack;
- DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD);
- if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
- TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope));
- Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
- Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
- } else {
- // Get the list of DeclContext to reenter.
- SmallVector<DeclContext*, 4> DeclContextToReenter;
- DeclContext *DD = FD->getLexicalParent();
- while (DD && !DD->isTranslationUnit()) {
- DeclContextToReenter.push_back(DD);
- DD = DD->getLexicalParent();
- }
- // Reenter template scopes from outmost to innermost.
- SmallVector<DeclContext*, 4>::reverse_iterator II =
- DeclContextToReenter.rbegin();
- for (; II != DeclContextToReenter.rend(); ++II) {
- if (ClassTemplatePartialSpecializationDecl* MD =
- dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
- TemplateParamScopeStack.push_back(new ParseScope(this,
- Scope::TemplateParamScope));
- Actions.ActOnReenterTemplateScope(getCurScope(), MD);
- } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
- TemplateParamScopeStack.push_back(new ParseScope(this,
- Scope::TemplateParamScope,
- MD->getDescribedClassTemplate() != 0 ));
- Actions.ActOnReenterTemplateScope(getCurScope(),
- MD->getDescribedClassTemplate());
- }
- TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
- Actions.PushDeclContext(Actions.getCurScope(), *II);
+ // Get the list of DeclContexts to reenter.
+ SmallVector<DeclContext*, 4> DeclContextsToReenter;
+ DeclContext *DD = FunD->getLexicalParent();
+ while (DD && !DD->isTranslationUnit()) {
+ DeclContextsToReenter.push_back(DD);
+ DD = DD->getLexicalParent();
+ }
+
+ // Reenter template scopes from outermost to innermost.
+ SmallVector<DeclContext*, 4>::reverse_iterator II =
+ DeclContextsToReenter.rbegin();
+ for (; II != DeclContextsToReenter.rend(); ++II) {
+ if (ClassTemplatePartialSpecializationDecl *MD =
+ dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
+ TemplateParamScopeStack.push_back(
+ new ParseScope(this, Scope::TemplateParamScope));
+ Actions.ActOnReenterTemplateScope(getCurScope(), MD);
+ ++CurTemplateDepthTracker;
+ } else if (CXXRecordDecl *MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
+ bool ManageScope = MD->getDescribedClassTemplate() != 0;
+ TemplateParamScopeStack.push_back(
+ new ParseScope(this, Scope::TemplateParamScope, ManageScope));
+ Actions.ActOnReenterTemplateScope(getCurScope(),
+ MD->getDescribedClassTemplate());
+ ++CurTemplateDepthTracker;
}
- TemplateParamScopeStack.push_back(new ParseScope(this,
- Scope::TemplateParamScope));
- Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
+ TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
+ Actions.PushDeclContext(Actions.getCurScope(), *II);
}
+ TemplateParamScopeStack.push_back(
+ new ParseScope(this, Scope::TemplateParamScope));
+
+ DeclaratorDecl *Declarator = dyn_cast<DeclaratorDecl>(FunD);
+ if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
+ Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
+ ++CurTemplateDepthTracker;
+ }
+ Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
+ ++CurTemplateDepthTracker;
assert(!LMT.Toks.empty() && "Empty body!");
@@ -1301,7 +1292,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
// Consume the previously pushed token.
- ConsumeAnyToken();
+ ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
&& "Inline method not starting with '{', ':' or 'try'");
@@ -1310,15 +1301,9 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
// Recreate the containing function DeclContext.
- Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD));
-
- if (FunctionTemplateDecl *FunctionTemplate
- = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
- Actions.ActOnStartOfFunctionDef(getCurScope(),
- FunctionTemplate->getTemplatedDecl());
- if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D))
- Actions.ActOnStartOfFunctionDef(getCurScope(), Function);
+ Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FunD));
+ Actions.ActOnStartOfFunctionDef(getCurScope(), FunD);
if (Tok.is(tok::kw_try)) {
ParseFunctionTryBlock(LMT.D, FnScope);
@@ -1329,8 +1314,12 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
Actions.ActOnDefaultCtorInitializers(LMT.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(FD, false);
+ Actions.MarkAsLateParsedTemplate(FunD, false);
} else
Actions.ActOnFinishFunctionBody(LMT.D, 0);
}