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:
parent
fce2ca9f66
commit
e6664762ec
|
@ -1163,9 +1163,6 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
|
||||||
if(!LMT.D)
|
if(!LMT.D)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If this is a member template, introduce the template parameter scope.
|
|
||||||
ParseScope TemplateScope(this, Scope::TemplateParamScope);
|
|
||||||
|
|
||||||
// Get the FunctionDecl.
|
// Get the FunctionDecl.
|
||||||
FunctionDecl *FD = 0;
|
FunctionDecl *FD = 0;
|
||||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
|
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LMT.D))
|
||||||
|
@ -1173,19 +1170,20 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
|
||||||
else
|
else
|
||||||
FD = cast<FunctionDecl>(LMT.D);
|
FD = cast<FunctionDecl>(LMT.D);
|
||||||
|
|
||||||
// Reinject the template parameters.
|
// To restore the context after late parsing.
|
||||||
|
Sema::ContextRAII GlobalSavedContext(Actions, Actions.CurContext);
|
||||||
|
|
||||||
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.
|
// Get the list of DeclContext to reenter.
|
||||||
SmallVector<DeclContext*, 4> DeclContextToReenter;
|
SmallVector<DeclContext*, 4> DeclContextToReenter;
|
||||||
DeclContext *DD = FD->getLexicalParent();
|
DeclContext *DD = FD->getLexicalParent();
|
||||||
while (DD && DD->isRecord()) {
|
while (DD && !DD->isTranslationUnit()) {
|
||||||
DeclContextToReenter.push_back(DD);
|
DeclContextToReenter.push_back(DD);
|
||||||
DD = DD->getLexicalParent();
|
DD = DD->getLexicalParent();
|
||||||
}
|
}
|
||||||
|
@ -1206,8 +1204,14 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
|
||||||
Actions.ActOnReenterTemplateScope(getCurScope(),
|
Actions.ActOnReenterTemplateScope(getCurScope(),
|
||||||
MD->getDescribedClassTemplate());
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!LMT.Toks.empty() && "Empty body!");
|
assert(!LMT.Toks.empty() && "Empty body!");
|
||||||
|
|
||||||
// Append the current token at the end of the new token stream so that it
|
// Append the current token at the end of the new token stream so that it
|
||||||
|
@ -1224,8 +1228,8 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT) {
|
||||||
// to be re-used for method bodies as well.
|
// to be re-used for method bodies as well.
|
||||||
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
|
ParseScope FnScope(this, Scope::FnScope|Scope::DeclScope);
|
||||||
|
|
||||||
// Recreate the DeclContext.
|
// Recreate the containing function DeclContext.
|
||||||
Sema::ContextRAII SavedContext(Actions, Actions.getContainingDC(FD));
|
Sema::ContextRAII FunctionSavedContext(Actions, Actions.getContainingDC(FD));
|
||||||
|
|
||||||
if (FunctionTemplateDecl *FunctionTemplate
|
if (FunctionTemplateDecl *FunctionTemplate
|
||||||
= dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
|
= dyn_cast_or_null<FunctionTemplateDecl>(LMT.D))
|
||||||
|
|
|
@ -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*)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue