diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-01-09 01:19:56 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2015-01-09 01:19:56 +0000 |
commit | b9d64a6123002fa2dfb045f61d1548523013bf71 (patch) | |
tree | 04b025f2289b7c8ccddd17c847201f26ba9090ca /lib/Sema/SemaTemplateInstantiate.cpp | |
parent | 3f15abb9bb51e8f9184b934f71d5779ab0ff48ef (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225490 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 33 |
1 files changed, 26 insertions, 7 deletions
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index c05960b571..6ac7175cf3 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -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); |