<div dir="ltr">Re-committed with fix in r<span style="font-size:12.8px">300938.</span></div><div class="gmail_extra"><br><div class="gmail_quote">On 20 April 2017 at 17:06, Richard Smith <span dir="ltr"><<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="">On 18 April 2017 at 22:41, Chandler Carruth <span dir="ltr"><<a href="mailto:chandlerc@google.com" target="_blank">chandlerc@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Reverted in r300658.</div></blockquote><div><br></div></span><div>For posterity, the above has an off-by-one error, the revert was r<span style="font-size:12.8px">300659.</span></div><div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div class="m_-7192218108927165949gmail-HOEnZb"><div class="m_-7192218108927165949gmail-h5"><div class="gmail_quote"><div dir="ltr">On Tue, Apr 18, 2017 at 8:30 PM Chandler Carruth <<a href="mailto:chandlerc@google.com" target="_blank">chandlerc@google.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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_p<wbr>ointer /*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>(MyAl<wbr>locator<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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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/<wbr>gcc/blob/gcc-4_9-branch/libstd<wbr>c++-v3/include/bits/alloc_<wbr>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:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);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-pr<wbr>oject?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.<wbr>cpp<br>
    cfe/trunk/test/Modules/Inputs/<wbr>template-default-args/a.h<br>
    cfe/trunk/test/Modules/templat<wbr>e-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-pr<wbr>oject/cfe/trunk/lib/AST/Decl.<wbr>cpp?rev=300650&r1=300649&r2=<wbr>300650&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<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::getTemplateInstantia<wbr>tionPattern() 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::getTemplateInstantia<wbr>ti<br>
           break;<br>
         VTD = NewVTD;<br>
       }<br>
-      return VTD->getTemplatedDecl()->getDe<wbr>finition();<br>
+      return getDefinitionOrSelf(VTD->getTe<wbr>mplatedDecl());<br>
     }<br>
     if (auto *VTPSD =<br>
             From.dyn_cast<VarTemplatePart<wbr>ialSpecializationDecl *>()) {<br>
@@ -2271,7 +2278,7 @@ VarDecl *VarDecl::getTemplateInstantia<wbr>ti<br>
           break;<br>
         VTPSD = NewVTPSD;<br>
       }<br>
-      return VTPSD->getDefinition();<br>
+      return getDefinitionOrSelf<VarDecl>(V<wbr>TPSD);<br>
     }<br>
   }<br>
<br>
@@ -2280,23 +2287,18 @@ VarDecl *VarDecl::getTemplateInstantia<wbr>ti<br>
       VarDecl *VD = getInstantiatedFromStaticDataM<wbr>ember();<br>
       while (auto *NewVD = VD->getInstantiatedFromStaticD<wbr>ataMember())<br>
         VD = NewVD;<br>
-      return VD->getDefinition();<br>
+      return getDefinitionOrSelf(VD);<br>
     }<br>
   }<br>
<br>
   if (VarTemplateDecl *VarTemplate = getDescribedVarTemplate()) {<br>
-<br>
     while (VarTemplate->getInstantiatedF<wbr>romMemberTemplate()) {<br>
       if (VarTemplate->isMemberSpeciali<wbr>zation())<br>
         break;<br>
       VarTemplate = VarTemplate->getInstantiatedFr<wbr>omMemberTemplate();<br>
     }<br>
<br>
-    assert((!VarTemplate->getTempl<wbr>atedDecl() ||<br>
-            !isTemplateInstantiation(getTe<wbr>mplateSpecializationKind())) &&<br>
-           "couldn't find pattern for variable instantiation");<br>
-<br>
-    return VarTemplate->getTemplatedDecl(<wbr>);<br>
+    return getDefinitionOrSelf(VarTemplat<wbr>e->getTemplatedDecl());<br>
   }<br>
   return nullptr;<br>
 }<br>
@@ -3201,7 +3203,7 @@ bool FunctionDecl::isTemplateInstan<wbr>tiati<br>
 FunctionDecl *FunctionDecl::getTemplateInst<wbr>antiationPattern() const {<br>
   // Handle class scope explicit specialization special case.<br>
   if (getTemplateSpecializationKind<wbr>() == TSK_ExplicitSpecialization)<br>
-    return getClassScopeSpecializationPat<wbr>tern();<br>
+    return getDefinitionOrSelf(getClassSc<wbr>opeSpecializationPattern());<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 (isGenericLambdaCallOperatorSp<wbr>ecialization(<br>
           dyn_cast<CXXMethodDecl>(this)<wbr>)) {<br>
-    assert(getPrimaryTemplate() && "A generic lambda specialization must be "<br>
-                                   "generated from a primary call operator "<br>
-                                   "template");<br>
-    assert(getPrimaryTemplate()->g<wbr>etTemplatedDecl()->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()->getTempl<wbr>atedDecl();<br>
+    assert(getPrimaryTemplate() && "not a generic lambda call operator?");<br>
+    return getDefinitionOrSelf(getPrimary<wbr>Template()->getTemplatedDecl()<wbr>);<br>
   }<br>
-<br>
+<br>
   if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) {<br>
     while (Primary->getInstantiatedFromM<wbr>emberTemplate()) {<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->getInstantiatedFromMe<wbr>mberTemplate();<br>
     }<br>
-<br>
-    return Primary->getTemplatedDecl();<br>
+<br>
+    return getDefinitionOrSelf(Primary->g<wbr>etTemplatedDecl());<br>
   }<br>
-<br>
-  return getInstantiatedFromMemberFunct<wbr>ion();<br>
+<br>
+  if (auto *MFD = getInstantiatedFromMemberFunct<wbr>ion())<br>
+    return getDefinitionOrSelf(MFD);<br>
+<br>
+  return nullptr;<br>
 }<br>
<br>
 FunctionTemplateDecl *FunctionDecl::getPrimaryTempl<wbr>ate() const {<br>
@@ -3780,7 +3779,7 @@ EnumDecl *EnumDecl::getTemplateInstanti<wbr>a<br>
       EnumDecl *ED = getInstantiatedFromMemberEnum(<wbr>);<br>
       while (auto *NewED = ED->getInstantiatedFromMemberE<wbr>num())<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-pr<wbr>oject/cfe/trunk/lib/AST/DeclCX<wbr>X.cpp?rev=300650&r1=300649&r2=<wbr>300650&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<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::setTemplateSpec<wbr>ialization<br>
 }<br>
<br>
 const CXXRecordDecl *CXXRecordDecl::getTemplateIns<wbr>tantiationPattern() 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<ClassTemplateSpeciali<wbr>zationDecl>(this)) {<br>
@@ -1374,7 +1381,7 @@ const CXXRecordDecl *CXXRecordDecl::getT<br>
           break;<br>
         CTD = NewCTD;<br>
       }<br>
-      return CTD->getTemplatedDecl()->getDe<wbr>finition();<br>
+      return GetDefinitionOrSelf(CTD->getTe<wbr>mplatedDecl());<br>
     }<br>
     if (auto *CTPSD =<br>
             From.dyn_cast<ClassTemplatePa<wbr>rtialSpecializationDecl *>()) {<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->getInstantiatedFromMemberC<wbr>lass())<br>
         RD = NewRD;<br>
-      return RD->getDefinition();<br>
+      return GetDefinitionOrSelf(RD);<br>
     }<br>
   }<br>
<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLookup.<wbr>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-pr<wbr>oject/cfe/trunk/lib/Sema/SemaL<wbr>ookup.cpp?rev=300650&r1=300649<wbr>&r2=300650&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLookup.<wbr>cpp Tue Apr 18 20:36:43 2017<br>
@@ -1326,12 +1326,6 @@ bool Sema::CppLookupName(LookupResu<wbr>lt &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->isExplicitSpecializati<wbr>on() ? D : MSInfo->getInstantiatedFrom();<br>
-}<br>
-<br>
 Module *Sema::getOwningModule(Decl *Entity) {<br>
   // If it's imported, grab its owning module.<br>
   Module *M = Entity->getImportedOwningModul<wbr>e();<br>
@@ -1413,20 +1407,14 @@ static Module *getDefiningModule(Sema &S<br>
     if (CXXRecordDecl *Pattern = RD->getTemplateInstantiationPa<wbr>ttern())<br>
       Entity = Pattern;<br>
   } else if (EnumDecl *ED = dyn_cast<EnumDecl>(Entity)) {<br>
-    if (MemberSpecializationInfo *MSInfo = ED->getMemberSpecializationInf<wbr>o())<br>
-      Entity = getInstantiatedFrom(ED, MSInfo);<br>
+    if (auto *Pattern = ED->getTemplateInstantiationPa<wbr>ttern())<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->getMemberSpecializationInf<wbr>o())<br>
-      Entity = getInstantiatedFrom(VD, MSInfo);<br>
+    if (VarDecl *Pattern = VD->getTemplateInstantiationPa<wbr>ttern())<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/<wbr>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-pr<wbr>oject/cfe/trunk/test/Modules/<wbr>Inputs/template-default-args/<wbr>a.h?rev=300650&r1=300649&r2=<wbr>300650&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Modules/Inputs/<wbr>template-default-args/a.h (original)<br>
+++ cfe/trunk/test/Modules/Inputs/<wbr>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/templat<wbr>e-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-pr<wbr>oject/cfe/trunk/test/Modules/<wbr>template-default-args.cpp?rev=<wbr>300650&r1=300649&r2=300650&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Modules/templat<wbr>e-default-args.cpp (original)<br>
+++ cfe/trunk/test/Modules/templat<wbr>e-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>
______________________________<wbr>_________________<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/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div></blockquote></div></blockquote></div>
</div></div></blockquote></div></div></div><br></div></div>
</blockquote></div><br></div>