<div dir="ltr">Reverted in r300658.</div><br><div class="gmail_quote"><div dir="ltr">On Tue, Apr 18, 2017 at 8:30 PM Chandler Carruth <<a href="mailto:chandlerc@google.com">chandlerc@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Consider code like the following:<div><br></div><div>```</div><div><div>#include <memory></div><div><br></div><div>template <class T></div><div>class MyAllocator : public std::allocator<T> {</div><div> public:</div><div>  typedef std::allocator<T> Alloc;</div><div>  typedef typename Alloc::pointer pointer;</div><div>  typedef typename Alloc::size_type size_type;</div><div><br></div><div>  MyAllocator() {}</div><div><br></div><div>  template <typename U></div><div>  MyAllocator(const MyAllocator<U>& x) : Alloc(x) {}</div><div><br></div><div>  pointer allocate(size_type n,</div><div>                   std::allocator<void>::const_pointer /*hint*/ = nullptr) {</div><div>    void* p = malloc(n * sizeof(T));</div><div>    return static_cast<pointer>(p);</div><div>  }</div><div><br></div><div>  void deallocate(pointer p, size_type) { free(p); }</div><div><br></div><div>  template <typename U></div><div>  struct rebind {</div><div>    typedef MyAllocator<U> other;</div><div>  };</div><div><br></div><div> private:</div><div>  template <class U></div><div>  friend class MyAllocator;</div><div>};</div><div><br></div><div>std::shared_ptr<int> x = std::allocate_shared<int>(MyAllocator<int>(), 0);</div></div><div>```</div><div><br></div><div>This will fail to compile against libstdc++ 4.9's alloc_traits.h, when that header comes from a module, with an error message along the lines of:</div><div>.../bits/alloc_traits.h:197:2: error: too few template arguments for class template '__alloctr_rebind'</div><div>        using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;</div><div><br></div><div>I think this is enough for you to debug, but let me know if not. I'm going to revert this temporarily to unbreak our modules builds using this version of libstdc++.</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Apr 18, 2017 at 8:14 PM Chandler Carruth <<a href="mailto:chandlerc@google.com" target="_blank">chandlerc@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">This appears to break a pretty straightforward use of things like libstdc++'s __alloctr_rebind (undefined template with a default argument, specializations, etc):<div><a href="https://github.com/gcc-mirror/gcc/blob/gcc-4_9-branch/libstdc++-v3/include/bits/alloc_traits.h#L58-L73" target="_blank">https://github.com/gcc-mirror/gcc/blob/gcc-4_9-branch/libstdc++-v3/include/bits/alloc_traits.h#L58-L73</a><br></div><div><br></div><div>At least, I'm getting errors from this. I'm working on a test case, but as usual, the test case may be... large.</div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Apr 18, 2017 at 6:49 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Tue Apr 18 20:36:43 2017<br>
New Revision: 300650<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=300650&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=300650&view=rev</a><br>
Log:<br>
[modules] Properly look up the owning module for an instantiation of a merged template.<br>
<br>
When looking for the template instantiation pattern of a templated entity,<br>
consistently select the definition of the pattern if there is one. This means<br>
we'll pick the same owning module when we start instantiating a template that<br>
we'll later pick when determining which modules are visible during that<br>
instantiation.<br>
<br>
Modified:<br>
    cfe/trunk/lib/AST/Decl.cpp<br>
    cfe/trunk/lib/AST/DeclCXX.cpp<br>
    cfe/trunk/lib/Sema/SemaLookup.cpp<br>
    cfe/trunk/test/Modules/Inputs/template-default-args/a.h<br>
    cfe/trunk/test/Modules/template-default-args.cpp<br>
<br>
Modified: cfe/trunk/lib/AST/Decl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=300650&r1=300649&r2=300650&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=300650&r1=300649&r2=300650&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/Decl.cpp (original)<br>
+++ cfe/trunk/lib/AST/Decl.cpp Tue Apr 18 20:36:43 2017<br>
@@ -2251,6 +2251,13 @@ bool VarDecl::checkInitIsICE() const {<br>
   return Eval->IsICE;<br>
 }<br>
<br>
+template<typename DeclT><br>
+static DeclT *getDefinitionOrSelf(DeclT *D) {<br>
+  if (auto *Def = D->getDefinition())<br>
+    return Def;<br>
+  return D;<br>
+}<br>
+<br>
 VarDecl *VarDecl::getTemplateInstantiationPattern() const {<br>
   // If it's a variable template specialization, find the template or partial<br>
   // specialization from which it was instantiated.<br>
@@ -2262,7 +2269,7 @@ VarDecl *VarDecl::getTemplateInstantiati<br>
           break;<br>
         VTD = NewVTD;<br>
       }<br>
-      return VTD->getTemplatedDecl()->getDefinition();<br>
+      return getDefinitionOrSelf(VTD->getTemplatedDecl());<br>
     }<br>
     if (auto *VTPSD =<br>
             From.dyn_cast<VarTemplatePartialSpecializationDecl *>()) {<br>
@@ -2271,7 +2278,7 @@ VarDecl *VarDecl::getTemplateInstantiati<br>
           break;<br>
         VTPSD = NewVTPSD;<br>
       }<br>
-      return VTPSD->getDefinition();<br>
+      return getDefinitionOrSelf<VarDecl>(VTPSD);<br>
     }<br>
   }<br>
<br>
@@ -2280,23 +2287,18 @@ VarDecl *VarDecl::getTemplateInstantiati<br>
       VarDecl *VD = getInstantiatedFromStaticDataMember();<br>
       while (auto *NewVD = VD->getInstantiatedFromStaticDataMember())<br>
         VD = NewVD;<br>
-      return VD->getDefinition();<br>
+      return getDefinitionOrSelf(VD);<br>
     }<br>
   }<br>
<br>
   if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {<br>
-<br>
     while (VarTemplate->getInstantiatedFromMemberTemplate()) {<br>
       if (VarTemplate->isMemberSpecialization())<br>
         break;<br>
       VarTemplate = VarTemplate->getInstantiatedFromMemberTemplate();<br>
     }<br>
<br>
-    assert((!VarTemplate->getTemplatedDecl() ||<br>
-            !isTemplateInstantiation(getTemplateSpecializationKind())) &&<br>
-           "couldn't find pattern for variable instantiation");<br>
-<br>
-    return VarTemplate->getTemplatedDecl();<br>
+    return getDefinitionOrSelf(VarTemplate->getTemplatedDecl());<br>
   }<br>
   return nullptr;<br>
 }<br>
@@ -3201,7 +3203,7 @@ bool FunctionDecl::isTemplateInstantiati<br>
 FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const {<br>
   // Handle class scope explicit specialization special case.<br>
   if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization)<br>
-    return getClassScopeSpecializationPattern();<br>
+    return getDefinitionOrSelf(getClassScopeSpecializationPattern());<br>
<br>
   // If this is a generic lambda call operator specialization, its<br>
   // instantiation pattern is always its primary template's pattern<br>
@@ -3214,16 +3216,10 @@ FunctionDecl *FunctionDecl::getTemplateI<br>
<br>
   if (isGenericLambdaCallOperatorSpecialization(<br>
           dyn_cast<CXXMethodDecl>(this))) {<br>
-    assert(getPrimaryTemplate() && "A generic lambda specialization must be "<br>
-                                   "generated from a primary call operator "<br>
-                                   "template");<br>
-    assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() &&<br>
-           "A generic lambda call operator template must always have a body - "<br>
-           "even if instantiated from a prototype (i.e. as written) member "<br>
-           "template");<br>
-    return getPrimaryTemplate()->getTemplatedDecl();<br>
+    assert(getPrimaryTemplate() && "not a generic lambda call operator?");<br>
+    return getDefinitionOrSelf(getPrimaryTemplate()->getTemplatedDecl());<br>
   }<br>
-<br>
+<br>
   if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {<br>
     while (Primary->getInstantiatedFromMemberTemplate()) {<br>
       // If we have hit a point where the user provided a specialization of<br>
@@ -3232,11 +3228,14 @@ FunctionDecl *FunctionDecl::getTemplateI<br>
         break;<br>
       Primary = Primary->getInstantiatedFromMemberTemplate();<br>
     }<br>
-<br>
-    return Primary->getTemplatedDecl();<br>
+<br>
+    return getDefinitionOrSelf(Primary->getTemplatedDecl());<br>
   }<br>
-<br>
-  return getInstantiatedFromMemberFunction();<br>
+<br>
+  if (auto *MFD = getInstantiatedFromMemberFunction())<br>
+    return getDefinitionOrSelf(MFD);<br>
+<br>
+  return nullptr;<br>
 }<br>
<br>
 FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const {<br>
@@ -3780,7 +3779,7 @@ EnumDecl *EnumDecl::getTemplateInstantia<br>
       EnumDecl *ED = getInstantiatedFromMemberEnum();<br>
       while (auto *NewED = ED->getInstantiatedFromMemberEnum())<br>
         ED = NewED;<br>
-      return ED;<br>
+      return getDefinitionOrSelf(ED);<br>
     }<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=300650&r1=300649&r2=300650&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=300650&r1=300649&r2=300650&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclCXX.cpp Tue Apr 18 20:36:43 2017<br>
@@ -1364,6 +1364,13 @@ CXXRecordDecl::setTemplateSpecialization<br>
 }<br>
<br>
 const CXXRecordDecl *CXXRecordDecl::getTemplateInstantiationPattern() const {<br>
+  auto GetDefinitionOrSelf =<br>
+      [](const CXXRecordDecl *D) -> const CXXRecordDecl * {<br>
+    if (auto *Def = D->getDefinition())<br>
+      return Def;<br>
+    return D;<br>
+  };<br>
+<br>
   // If it's a class template specialization, find the template or partial<br>
   // specialization from which it was instantiated.<br>
   if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {<br>
@@ -1374,7 +1381,7 @@ const CXXRecordDecl *CXXRecordDecl::getT<br>
           break;<br>
         CTD = NewCTD;<br>
       }<br>
-      return CTD->getTemplatedDecl()->getDefinition();<br>
+      return GetDefinitionOrSelf(CTD->getTemplatedDecl());<br>
     }<br>
     if (auto *CTPSD =<br>
             From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {<br>
@@ -1383,7 +1390,7 @@ const CXXRecordDecl *CXXRecordDecl::getT<br>
           break;<br>
         CTPSD = NewCTPSD;<br>
       }<br>
-      return CTPSD->getDefinition();<br>
+      return GetDefinitionOrSelf(CTPSD);<br>
     }<br>
   }<br>
<br>
@@ -1392,7 +1399,7 @@ const CXXRecordDecl *CXXRecordDecl::getT<br>
       const CXXRecordDecl *RD = this;<br>
       while (auto *NewRD = RD->getInstantiatedFromMemberClass())<br>
         RD = NewRD;<br>
-      return RD->getDefinition();<br>
+      return GetDefinitionOrSelf(RD);<br>
     }<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=300650&r1=300649&r2=300650&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=300650&r1=300649&r2=300650&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Apr 18 20:36:43 2017<br>
@@ -1326,12 +1326,6 @@ bool Sema::CppLookupName(LookupResult &R<br>
   return !R.empty();<br>
 }<br>
<br>
-/// \brief Find the declaration that a class temploid member specialization was<br>
-/// instantiated from, or the member itself if it is an explicit specialization.<br>
-static Decl *getInstantiatedFrom(Decl *D, MemberSpecializationInfo *MSInfo) {<br>
-  return MSInfo->isExplicitSpecialization() ? D : MSInfo->getInstantiatedFrom();<br>
-}<br>
-<br>
 Module *Sema::getOwningModule(Decl *Entity) {<br>
   // If it's imported, grab its owning module.<br>
   Module *M = Entity->getImportedOwningModule();<br>
@@ -1413,20 +1407,14 @@ static Module *getDefiningModule(Sema &S<br>
     if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPattern())<br>
       Entity = Pattern;<br>
   } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {<br>
-    if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInfo())<br>
-      Entity = getInstantiatedFrom(ED, MSInfo);<br>
+    if (auto *Pattern = ED->getTemplateInstantiationPattern())<br>
+      Entity = Pattern;<br>
   } else if (VarDecl *VD = dyn_cast<VarDecl>(Entity)) {<br>
-    // FIXME: Map from variable template specializations back to the template.<br>
-    if (MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo())<br>
-      Entity = getInstantiatedFrom(VD, MSInfo);<br>
+    if (VarDecl *Pattern = VD->getTemplateInstantiationPattern())<br>
+      Entity = Pattern;<br>
   }<br>
<br>
-  // Walk up to the containing context. That might also have been instantiated<br>
-  // from a template.<br>
-  DeclContext *Context = Entity->getDeclContext();<br>
-  if (Context->isFileContext())<br>
-    return S.getOwningModule(Entity);<br>
-  return getDefiningModule(S, cast<Decl>(Context));<br>
+  return S.getOwningModule(Entity);<br>
 }<br>
<br>
 llvm::DenseSet<Module*> &Sema::getLookupModules() {<br>
<br>
Modified: cfe/trunk/test/Modules/Inputs/template-default-args/a.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/template-default-args/a.h?rev=300650&r1=300649&r2=300650&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/template-default-args/a.h?rev=300650&r1=300649&r2=300650&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/Inputs/template-default-args/a.h (original)<br>
+++ cfe/trunk/test/Modules/Inputs/template-default-args/a.h Tue Apr 18 20:36:43 2017<br>
@@ -14,3 +14,11 @@ struct FriendL {<br>
   template<typename T> friend struct L;<br>
 };<br>
 END<br>
+<br>
+namespace DeferredLookup {<br>
+  template<typename T, typename U = T> using X = U;<br>
+  template<typename T> void f() { (void) X<T>(); }<br>
+  template<typename T> int n = X<T>();<br>
+  template<typename T> struct S { X<T> xt; enum E : int; };<br>
+  template<typename T> enum S<T>::E : int { a = X<T>() };<br>
+}<br>
<br>
Modified: cfe/trunk/test/Modules/template-default-args.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/template-default-args.cpp?rev=300650&r1=300649&r2=300650&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/template-default-args.cpp?rev=300650&r1=300649&r2=300650&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/Modules/template-default-args.cpp (original)<br>
+++ cfe/trunk/test/Modules/template-default-args.cpp Tue Apr 18 20:36:43 2017<br>
@@ -44,3 +44,18 @@ H<> h; // expected-error {{default argum<br>
 I<> i;<br>
 L<> *l;<br>
 END<br>
+<br>
+namespace DeferredLookup {<br>
+  template<typename T, typename U = T> using X = U;<br>
+  template<typename T> void f() { (void) X<T>(); }<br>
+  template<typename T> int n = X<T>(); // expected-warning {{extension}}<br>
+  template<typename T> struct S { X<T> xt; enum E : int; };<br>
+  template<typename T> enum S<T>::E : int { a = X<T>() };<br>
+<br>
+  void test() {<br>
+    f<int>();<br>
+    n<int> = 1;<br>
+    S<int> s;<br>
+    S<int>::E e = S<int>::E::a;<br>
+  }<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></blockquote></div></blockquote></div>