PR22117: Fix a case where we would get confused about which function parameter

we're instantiating, if there's a ParmVarDecl within a FunctionDecl context
that is not a parameter of that function. Add some asserts to catch this kind
of issue more generally, and fix another bug exposed by those asserts where we
were missing a local instantiation scope around substitution of
explicitly-specified template arguments.

llvm-svn: 225490
This commit is contained in:
Richard Smith 2015-01-09 01:19:56 +00:00
parent b5d1a73988
commit 70b13043a2
3 changed files with 39 additions and 8 deletions

View File

@ -2588,6 +2588,9 @@ Sema::SubstituteExplicitTemplateArguments(
= Function->getType()->getAs<FunctionProtoType>();
assert(Proto && "Function template does not have a prototype?");
// Isolate our substituted parameters from our caller.
LocalInstantiationScope InstScope(*this, /*MergeWithOuterScope*/true);
// Instantiate the types of each of the function parameters given the
// explicitly-specified template arguments. If the function has a trailing
// return type, substitute it after the arguments to ensure we substitute

View File

@ -2762,8 +2762,7 @@ bool Sema::Subst(const TemplateArgumentLoc *Args, unsigned NumArgs,
return Instantiator.TransformTemplateArguments(Args, NumArgs, Result);
}
static const Decl* getCanonicalParmVarDecl(const Decl *D) {
static const Decl *getCanonicalParmVarDecl(const Decl *D) {
// When storing ParmVarDecls in the local instantiation scope, we always
// want to use the ParmVarDecl from the canonical function declaration,
// since the map is then valid for any redeclaration or definition of that
@ -2771,7 +2770,10 @@ static const Decl* getCanonicalParmVarDecl(const Decl *D) {
if (const ParmVarDecl *PV = dyn_cast<ParmVarDecl>(D)) {
if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(PV->getDeclContext())) {
unsigned i = PV->getFunctionScopeIndex();
return FD->getCanonicalDecl()->getParamDecl(i);
// This parameter might be from a freestanding function type within the
// function and isn't necessarily referring to one of FD's parameters.
if (FD->getParamDecl(i) == PV)
return FD->getCanonicalDecl()->getParamDecl(i);
}
}
return D;
@ -2820,12 +2822,22 @@ LocalInstantiationScope::findInstantiationOf(const Decl *D) {
void LocalInstantiationScope::InstantiatedLocal(const Decl *D, Decl *Inst) {
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
if (Stored.isNull())
if (Stored.isNull()) {
#ifndef NDEBUG
// It should not be present in any surrounding scope either.
LocalInstantiationScope *Current = this;
while (Current->CombineWithOuterScope && Current->Outer) {
Current = Current->Outer;
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
"Instantiated local in inner and outer scopes");
}
#endif
Stored = Inst;
else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>())
} else if (DeclArgumentPack *Pack = Stored.dyn_cast<DeclArgumentPack *>()) {
Pack->push_back(Inst);
else
} else {
assert(Stored.get<Decl *>() == Inst && "Already instantiated this local");
}
}
void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
@ -2836,9 +2848,16 @@ void LocalInstantiationScope::InstantiatedLocalPackArg(const Decl *D,
}
void LocalInstantiationScope::MakeInstantiatedLocalArgPack(const Decl *D) {
#ifndef NDEBUG
// This should be the first time we've been told about this decl.
for (LocalInstantiationScope *Current = this;
Current && Current->CombineWithOuterScope; Current = Current->Outer)
assert(Current->LocalDecls.find(D) == Current->LocalDecls.end() &&
"Creating local pack after instantiation of local");
#endif
D = getCanonicalParmVarDecl(D);
llvm::PointerUnion<Decl *, DeclArgumentPack *> &Stored = LocalDecls[D];
assert(Stored.isNull() && "Already instantiated this local");
DeclArgumentPack *Pack = new DeclArgumentPack;
Stored = Pack;
ArgumentPacks.push_back(Pack);

View File

@ -921,4 +921,13 @@ int run2 = x2.fooG3();
namespace pr21684_disambiguate_auto_followed_by_ellipsis_no_id {
int a = [](auto ...) { return 0; }();
}
}
namespace PR22117 {
int x = [](auto) {
return [](auto... run_args) {
using T = int(decltype(run_args)...);
return 0;
};
}(0)(0);
}