Author: rsmith Date: Thu Apr 20 20:15:13 2017 New Revision: 300938 URL: http://llvm.org/viewvc/llvm-project?rev=300938&view=rev Log: [modules] Properly look up the owning module for an instantiation of a merged template.
When looking for the template instantiation pattern of a templated entity, consistently select the definition of the pattern if there is one. This means we'll pick the same owning module when we start instantiating a template that we'll later pick when determining which modules are visible during that instantiation. This reinstates r300650, reverted in r300659, with a fix for a regression reported by Chandler after commit. Modified: cfe/trunk/lib/AST/Decl.cpp cfe/trunk/lib/AST/DeclCXX.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/test/Modules/Inputs/template-default-args/a.h cfe/trunk/test/Modules/Inputs/template-default-args/d.h cfe/trunk/test/Modules/template-default-args.cpp Modified: cfe/trunk/lib/AST/Decl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/lib/AST/Decl.cpp (original) +++ cfe/trunk/lib/AST/Decl.cpp Thu Apr 20 20:15:13 2017 @@ -2251,6 +2251,14 @@ bool VarDecl::checkInitIsICE() const { return Eval->IsICE; } +template<typename DeclT> +static DeclT *getDefinitionOrSelf(DeclT *D) { + assert(D); + if (auto *Def = D->getDefinition()) + return Def; + return D; +} + VarDecl *VarDecl::getTemplateInstantiationPattern() const { // If it's a variable template specialization, find the template or partial // specialization from which it was instantiated. @@ -2262,7 +2270,7 @@ VarDecl *VarDecl::getTemplateInstantiati break; VTD = NewVTD; } - return VTD->getTemplatedDecl()->getDefinition(); + return getDefinitionOrSelf(VTD->getTemplatedDecl()); } if (auto *VTPSD = From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) { @@ -2271,7 +2279,7 @@ VarDecl *VarDecl::getTemplateInstantiati break; VTPSD = NewVTPSD; } - return VTPSD->getDefinition(); + return getDefinitionOrSelf<VarDecl>(VTPSD); } } @@ -2280,23 +2288,18 @@ VarDecl *VarDecl::getTemplateInstantiati VarDecl *VD = getInstantiatedFromStaticDataMember(); while (auto *NewVD = VD->getInstantiatedFromStaticDataMember()) VD = NewVD; - return VD->getDefinition(); + return getDefinitionOrSelf(VD); } } if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) { - while (VarTemplate->getInstantiatedFromMemberTemplate()) { if (VarTemplate->isMemberSpecialization()) break; VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate(); } - assert((!VarTemplate->getTemplatedDecl() || - !isTemplateInstantiation(getTemplateSpecializationKind())) && - "couldn't find pattern for variable instantiation"); - - return VarTemplate->getTemplatedDecl(); + return getDefinitionOrSelf(VarTemplate->getTemplatedDecl()); } return nullptr; } @@ -3198,9 +3201,12 @@ bool FunctionDecl::isTemplateInstantiati FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. - if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) - return getClassScopeSpecializationPattern(); - + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) { + if (auto *Spec = getClassScopeSpecializationPattern()) + return getDefinitionOrSelf(Spec); + return nullptr; + } + // If this is a generic lambda call operator specialization, its // instantiation pattern is always its primary template's pattern // even if its primary template was instantiated from another @@ -3212,16 +3218,10 @@ FunctionDecl *FunctionDecl::getTemplateI if (isGenericLambdaCallOperatorSpecialization( dyn_cast<CXXMethodDecl>(this))) { - assert(getPrimaryTemplate() && "A generic lambda specialization must be " - "generated from a primary call operator " - "template"); - assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && - "A generic lambda call operator template must always have a body - " - "even if instantiated from a prototype (i.e. as written) member " - "template"); - return getPrimaryTemplate()->getTemplatedDecl(); + assert(getPrimaryTemplate() && "not a generic lambda call operator?"); + return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl()); } - + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -3230,11 +3230,14 @@ FunctionDecl *FunctionDecl::getTemplateI break; Primary = Primary->getInstantiatedFromMemberTemplate(); } - - return Primary->getTemplatedDecl(); + + return getDefinitionOrSelf(Primary->getTemplatedDecl()); } - - return getInstantiatedFromMemberFunction(); + + if (auto *MFD = getInstantiatedFromMemberFunction()) + return getDefinitionOrSelf(MFD); + + return nullptr; } FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { @@ -3778,7 +3781,7 @@ EnumDecl *EnumDecl::getTemplateInstantia EnumDecl *ED = getInstantiatedFromMemberEnum(); while (auto *NewED = ED->getInstantiatedFromMemberEnum()) ED = NewED; - return ED; + return getDefinitionOrSelf(ED); } } Modified: cfe/trunk/lib/AST/DeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclCXX.cpp (original) +++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Apr 20 20:15:13 2017 @@ -1364,6 +1364,13 @@ CXXRecordDecl::setTemplateSpecialization } const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const { + auto GetDefinitionOrSelf = + [](const CXXRecordDecl *D) -> const CXXRecordDecl * { + if (auto *Def = D->getDefinition()) + return Def; + return D; + }; + // If it's a class template specialization, find the template or partial // specialization from which it was instantiated. if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) { @@ -1374,7 +1381,7 @@ const CXXRecordDecl *CXXRecordDecl::getT break; CTD = NewCTD; } - return CTD->getTemplatedDecl()->getDefinition(); + return GetDefinitionOrSelf(CTD->getTemplatedDecl()); } if (auto *CTPSD = From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) { @@ -1383,7 +1390,7 @@ const CXXRecordDecl *CXXRecordDecl::getT break; CTPSD = NewCTPSD; } - return CTPSD->getDefinition(); + return GetDefinitionOrSelf(CTPSD); } } @@ -1392,7 +1399,7 @@ const CXXRecordDecl *CXXRecordDecl::getT const CXXRecordDecl *RD = this; while (auto *NewRD = RD->getInstantiatedFromMemberClass()) RD = NewRD; - return RD->getDefinition(); + return GetDefinitionOrSelf(RD); } } Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Thu Apr 20 20:15:13 2017 @@ -1326,12 +1326,6 @@ bool Sema::CppLookupName(LookupResult &R return !R.empty(); } -/// \brief Find the declaration that a class temploid member specialization was -/// instantiated from, or the member itself if it is an explicit specialization. -static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) { - return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom(); -} - Module *Sema::getOwningModule(Decl *Entity) { // If it's imported, grab its owning module. Module *M = Entity->getImportedOwningModule(); @@ -1413,12 +1407,11 @@ static Module *getDefiningModule(Sema &S if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern()) Entity = Pattern; } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) { - if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(ED, MSInfo); + if (auto *Pattern = ED->getTemplateInstantiationPattern()) + Entity = Pattern; } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) { - // FIXME: Map from variable template specializations back to the template. - if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo()) - Entity = getInstantiatedFrom(VD, MSInfo); + if (VarDecl *Pattern = VD->getTemplateInstantiationPattern()) + Entity = Pattern; } // Walk up to the containing context. That might also have been instantiated Modified: cfe/trunk/test/Modules/Inputs/template-default-args/a.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/template-default-args/a.h?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/test/Modules/Inputs/template-default-args/a.h (original) +++ cfe/trunk/test/Modules/Inputs/template-default-args/a.h Thu Apr 20 20:15:13 2017 @@ -14,3 +14,16 @@ struct FriendL { template<typename T> friend struct L; }; END + +namespace DeferredLookup { + template<typename T, typename U = T> using X = U; + template<typename T> void f() { (void) X<T>(); } + template<typename T> int n = X<T>(); + template<typename T> struct S { X<T> xt; enum E : int; }; + template<typename T> enum S<T>::E : int { a = X<T>() }; + + namespace Indirect { + template<typename, bool = true> struct A {}; + template<typename> struct B { template<typename T> using C = A<T>; }; + } +} Modified: cfe/trunk/test/Modules/Inputs/template-default-args/d.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/template-default-args/d.h?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/test/Modules/Inputs/template-default-args/d.h (original) +++ cfe/trunk/test/Modules/Inputs/template-default-args/d.h Thu Apr 20 20:15:13 2017 @@ -4,3 +4,10 @@ struct FriendL { template<typename T> friend struct L; }; END + +namespace DeferredLookup { + namespace Indirect { + template<typename, bool = true> struct A {}; + template<typename> struct B { template<typename T> using C = A<T>; }; + } +} Modified: cfe/trunk/test/Modules/template-default-args.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/template-default-args.cpp?rev=300938&r1=300937&r2=300938&view=diff ============================================================================== --- cfe/trunk/test/Modules/template-default-args.cpp (original) +++ cfe/trunk/test/Modules/template-default-args.cpp Thu Apr 20 20:15:13 2017 @@ -44,3 +44,20 @@ H<> h; // expected-error {{default argum I<> i; L<> *l; END + +namespace DeferredLookup { + template<typename T, typename U = T> using X = U; + template<typename T> void f() { (void) X<T>(); } + template<typename T> int n = X<T>(); // expected-warning {{extension}} + template<typename T> struct S { X<T> xt; enum E : int; }; + template<typename T> enum S<T>::E : int { a = X<T>() }; + + void test() { + f<int>(); + n<int> = 1; + S<int> s; + S<int>::E e = S<int>::E::a; + + Indirect::B<int>::C<int> indirect; + } +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits