In -fdelayed-template-parsing mode, reenter every scope when late parsing a templated function; (Not just the template parameter scope as previously). Also enter the scope stack in the correct order.

Otherwise this breaks some invariant during name lookup especially when dealing with shadowed declaration

Fix PR11931.

llvm-svn: 151140
This commit is contained in:
Francois Pichet 2012-02-22 08:25:53 +00:00
parent fce2ca9f66
commit e6664762ec
2 changed files with 133 additions and 102 deletions

View File

@ -1157,109 +1157,113 @@ void Parser::LateTemplateParser(const FunctionDecl *FD) {
llvm_unreachable("Late templated function without associated lexed tokens"); llvm_unreachable("Late templated function without associated lexed tokens");
} }
/// \brief Late parse a C++ function template in Microsoft mode. /// \brief Late parse a C++ function template in Microsoft mode.
void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) { void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
if(!LMT.D) if(!LMT.D)
return; return;
// If this is a member template, introduce the template parameter scope. // Get the FunctionDecl.
ParseScope TemplateScope(this, Scope::TemplateParamScope); FunctionDecl *FD = 0;
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
// Get the FunctionDecl. FD = FunTmpl->getTemplatedDecl();
FunctionDecl *FD = 0; else
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D)) FD = cast<FunctionDecl>(LMT.D);
FD = FunTmpl->getTemplatedDecl();
else // To restore the context after late parsing.
FD = cast<FunctionDecl>(LMT.D); Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
// Reinject the template parameters. SmallVector<ParseScope*, 4> TemplateParamScopeStack;
SmallVector<ParseScope*, 4> TemplateParamScopeStack; DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD);
DeclaratorDecl* Declarator = dyn_cast<DeclaratorDecl>(FD); if (Declarator && Declarator->getNumTemplateParameterLists() != 0) {
if (Declarator && Declarator->getNumTemplateParameterLists() != 0) { TemplateParamScopeStack.push_back(new ParseScope(this, Scope::TemplateParamScope));
Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator); Actions.ActOnReenterDeclaratorTemplateScope(getCurScope(), Declarator);
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
} else { } else {
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D); // Get the list of DeclContext to reenter.
SmallVector<DeclContext*, 4> DeclContextToReenter;
// Get the list of DeclContext to reenter. DeclContext *DD = FD->getLexicalParent();
SmallVector<DeclContext*, 4> DeclContextToReenter; while (DD && !DD->isTranslationUnit()) {
DeclContext *DD = FD->getLexicalParent(); DeclContextToReenter.push_back(DD);
while (DD && DD->isRecord()) { DD = DD->getLexicalParent();
DeclContextToReenter.push_back(DD); }
DD = DD->getLexicalParent();
} // Reenter template scopes from outmost to innermost.
SmallVector<DeclContext*, 4>::reverse_iterator II =
// Reenter template scopes from outmost to innermost. DeclContextToReenter.rbegin();
SmallVector<DeclContext*, 4>::reverse_iterator II = for (; II != DeclContextToReenter.rend(); ++II) {
DeclContextToReenter.rbegin(); if (ClassTemplatePartialSpecializationDecl* MD =
for (; II != DeclContextToReenter.rend(); ++II) { dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) {
if (ClassTemplatePartialSpecializationDecl* MD = TemplateParamScopeStack.push_back(new ParseScope(this,
dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(*II)) { Scope::TemplateParamScope));
TemplateParamScopeStack.push_back(new ParseScope(this, Actions.ActOnReenterTemplateScope(getCurScope(), MD);
Scope::TemplateParamScope)); } else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) {
Actions.ActOnReenterTemplateScope(getCurScope(), MD); TemplateParamScopeStack.push_back(new ParseScope(this,
} else if (CXXRecordDecl* MD = dyn_cast_or_null<CXXRecordDecl>(*II)) { Scope::TemplateParamScope,
TemplateParamScopeStack.push_back(new ParseScope(this, MD->getDescribedClassTemplate() != 0 ));
Scope::TemplateParamScope, Actions.ActOnReenterTemplateScope(getCurScope(),
MD->getDescribedClassTemplate() != 0 )); MD->getDescribedClassTemplate());
Actions.ActOnReenterTemplateScope(getCurScope(), }
MD->getDescribedClassTemplate()); TemplateParamScopeStack.push_back(new ParseScope(this, Scope::DeclScope));
} Actions.PushDeclContext(Actions.getCurScope(), *II);
} }
} TemplateParamScopeStack.push_back(new ParseScope(this,
assert(!LMT.Toks.empty() && "Empty body!"); Scope::TemplateParamScope));
Actions.ActOnReenterTemplateScope(getCurScope(), LMT.D);
// Append the current token at the end of the new token stream so that it }
// doesn't get lost.
LMT.Toks.push_back(Tok); assert(!LMT.Toks.empty() && "Empty body!");
PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
// Append the current token at the end of the new token stream so that it
// Consume the previously pushed token. // doesn't get lost.
ConsumeAnyToken(); LMT.Toks.push_back(Tok);
assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try)) PP.EnterTokenStream(LMT.Toks.data(), LMT.Toks.size(), true, false);
&& "Inline method not starting with '{', ':' or 'try'");
// Consume the previously pushed token.
// Parse the method body. Function body parsing code is similar enough ConsumeAnyToken();
// to be re-used for method bodies as well. assert((Tok.is(tok::l_brace) || Tok.is(tok::colon) || Tok.is(tok::kw_try))
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope); && "Inline method not starting with '{', ':' or 'try'");
// Recreate the DeclContext. // Parse the method body. Function body parsing code is similar enough
Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD)); // to be re-used for method bodies as well.
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
if (FunctionTemplateDecl *FunctionTemplate
= dyn_cast_or_null<FunctionTemplateDecl>(LMT.D)) // Recreate the containing function DeclContext.
Actions.ActOnStartOfFunctionDef(getCurScope(), Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD));
FunctionTemplate->getTemplatedDecl());
if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D)) if (FunctionTemplateDecl *FunctionTemplate
Actions.ActOnStartOfFunctionDef(getCurScope(), Function); = dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
Actions.ActOnStartOfFunctionDef(getCurScope(),
FunctionTemplate->getTemplatedDecl());
if (Tok.is(tok::kw_try)) { if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(LMT.D))
ParseFunctionTryBlock(LMT.D, FnScope); Actions.ActOnStartOfFunctionDef(getCurScope(), Function);
} else {
if (Tok.is(tok::colon))
ParseConstructorInitializer(LMT.D); if (Tok.is(tok::kw_try)) {
else ParseFunctionTryBlock(LMT.D, FnScope);
Actions.ActOnDefaultCtorInitializers(LMT.D); } else {
if (Tok.is(tok::colon))
if (Tok.is(tok::l_brace)) { ParseConstructorInitializer(LMT.D);
ParseFunctionStatementBody(LMT.D, FnScope); else
Actions.MarkAsLateParsedTemplate(FD, false); Actions.ActOnDefaultCtorInitializers(LMT.D);
} else
Actions.ActOnFinishFunctionBody(LMT.D, 0); if (Tok.is(tok::l_brace)) {
} ParseFunctionStatementBody(LMT.D, FnScope);
Actions.MarkAsLateParsedTemplate(FD, false);
// Exit scopes. } else
Actions.ActOnFinishFunctionBody(LMT.D, 0);
}
// Exit scopes.
FnScope.Exit(); FnScope.Exit();
SmallVector<ParseScope*, 4>::reverse_iterator I = SmallVector<ParseScope*, 4>::reverse_iterator I =
TemplateParamScopeStack.rbegin(); TemplateParamScopeStack.rbegin();
for (; I != TemplateParamScopeStack.rend(); ++I) for (; I != TemplateParamScopeStack.rend(); ++I)
delete *I; delete *I;
DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D); DeclGroupPtrTy grp = Actions.ConvertDeclToDeclGroup(LMT.D);
if (grp) if (grp)
Actions.getASTConsumer().HandleTopLevelDecl(grp.get()); Actions.getASTConsumer().HandleTopLevelDecl(grp.get());
} }
/// \brief Lex a delayed template function for late parsing. /// \brief Lex a delayed template function for late parsing.

View File

@ -63,3 +63,30 @@ public:
} }
namespace PR11931 {
template <typename RunType>
struct BindState;
template<>
struct BindState<void(void*)> {
static void Run() { }
};
class Callback {
public:
typedef void RunType();
template <typename RunType>
Callback(BindState<RunType> bind_state) {
BindState<RunType>::Run();
}
};
Callback Bind() {
return Callback(BindState<void(void*)>());
}
}