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:
parent
b5d1a73988
commit
70b13043a2
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue