Properly reenter multiple contexts when parsing a late-parsed function template

within a dependent context. Patch by Will Wilson (+clang-format)!

llvm-svn: 180702
This commit is contained in:
Richard Smith
2013-04-29 08:53:40 +00:00
parent a3519fa347
commit 07cea1911a
2 changed files with 34 additions and 35 deletions

View File

@@ -1259,44 +1259,42 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
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);
}
TemplateParamScopeStack.push_back(new ParseScope(this,
Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
// Get the list of DeclContexts to reenter.
SmallVector<DeclContext*, 4> DeclContextsToReenter;
DeclContext *DD = FD->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);
} 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());
}
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>(FD);
if (Declarator && Declarator->getNumTemplateParameterLists() != 0)
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
assert(!LMT.Toks.empty() && "Empty body!");
// Append the current token at the end of the new token stream so that it

View File

@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
// RUN: %clang_cc1 -fms-extensions -fdelayed-template-parsing -fsyntax-only -verify %s
class A {