<div dir="ltr">Hi Richard,<div><br></div><div>The following test triggers an assertion, even after this patch:</div><div><br></div><div><div>#include <memory></div><div>#include <string></div><div><br></div><div>template <class T></div><div>struct TestAlloc : std::allocator<T> {};</div><div><br></div><div>template <class Char, class Traits = std::char_traits<Char>,</div><div>          class Allocator = std::allocator<Char>></div><div>struct String {</div><div>  using size_type = typename Allocator::size_type;</div><div><br></div><div>  String() = default;</div><div>  String(const String&, size_type, size_type, const Allocator& = Allocator()) {}</div><div>  String(String const&, size_type, const Allocator& = Allocator()) {}</div><div>};</div><div><br></div><div>int main() {</div><div>  using BStr = String<char>;</div><div>  BStr bs;</div><div>  String s(bs, 1ul, 1ul, std::allocator<char>{});</div><div>  static_assert(std::is_same_v<decltype(s), BStr>);</div><div>}</div></div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Feb 13, 2017 at 6:50 PM, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Mon Feb 13 19:49:59 2017<br>
New Revision: 295016<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=295016&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=295016&view=rev</a><br>
Log:<br>
Canonicalize implicit deduction guide parameter types when forming a deduction<br>
guide from a constructor.<br>
<br>
The purpose of this change is to avoid triggering instantiation of the class<br>
when substituting back into the deduction guide if it uses a typedef member.<br>
We will still instantiate the class if the constructor (explicitly or<br>
implicitly, directly or indirectly) uses the current instantiation in a way<br>
that we can't canonicalize out, but that seems unavoidable.<br>
<br>
Modified:<br>
    cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
    cfe/trunk/test/SemaCXX/cxx1z-<wbr>class-template-argument-<wbr>deduction.cpp<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=295016&r1=295015&r2=295016&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp?rev=295016&<wbr>r1=295015&r2=295016&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp Mon Feb 13 19:49:59 2017<br>
@@ -1585,12 +1585,7 @@ private:<br>
<br>
     //    -- The types of the function parameters are those of the constructor.<br>
     for (auto *OldParam : TL.getParams()) {<br>
-      // If we're transforming a non-template constructor, just reuse its<br>
-      // parameters as the parameters of the deduction guide. Otherwise, we<br>
-      // need to transform their references to constructor template parameters.<br>
-      ParmVarDecl *NewParam = Args.getNumLevels()<br>
-                                  ? transformFunctionTypeParam(<wbr>OldParam, Args)<br>
-                                  : OldParam;<br>
+      ParmVarDecl *NewParam = transformFunctionTypeParam(<wbr>OldParam, Args);<br>
       if (!NewParam)<br>
         return QualType();<br>
       ParamTypes.push_back(NewParam-<wbr>>getType());<br>
@@ -1636,16 +1631,31 @@ private:<br>
   transformFunctionTypeParam(<wbr>ParmVarDecl *OldParam,<br>
                              MultiLevelTemplateArgumentList &Args) {<br>
     TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo();<br>
-    TypeSourceInfo *NewDI = SemaRef.SubstType(<br>
-        OldDI, Args, OldParam->getLocation(), OldParam->getDeclName());<br>
+    TypeSourceInfo *NewDI =<br>
+        Args.getNumLevels()<br>
+            ? SemaRef.SubstType(OldDI, Args, OldParam->getLocation(),<br>
+                                OldParam->getDeclName())<br>
+            : OldDI;<br>
     if (!NewDI)<br>
       return nullptr;<br>
<br>
+    // Canonicalize the type. This (for instance) replaces references to<br>
+    // typedef members of the current instantiations with the definitions of<br>
+    // those typedefs, avoiding triggering instantiation of the deduced type<br>
+    // during deduction.<br>
+    // FIXME: It would be preferable to retain type sugar and source<br>
+    // information here (and handle this in substitution instead).<br>
+    NewDI = SemaRef.Context.<wbr>getTrivialTypeSourceInfo(<br>
+        SemaRef.Context.<wbr>getCanonicalType(NewDI-><wbr>getType()),<br>
+        OldParam->getLocation());<br>
+<br>
     // Resolving a wording defect, we also inherit default arguments from the<br>
     // constructor.<br>
     ExprResult NewDefArg;<br>
     if (OldParam->hasDefaultArg()) {<br>
-      NewDefArg = SemaRef.SubstExpr(OldParam-><wbr>getDefaultArg(), Args);<br>
+      NewDefArg = Args.getNumLevels()<br>
+                      ? SemaRef.SubstExpr(OldParam-><wbr>getDefaultArg(), Args)<br>
+                      : OldParam->getDefaultArg();<br>
       if (NewDefArg.isInvalid())<br>
         return nullptr;<br>
     }<br>
<br>
Modified: cfe/trunk/test/SemaCXX/cxx1z-<wbr>class-template-argument-<wbr>deduction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=295016&r1=295015&r2=295016&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/cxx1z-class-template-<wbr>argument-deduction.cpp?rev=<wbr>295016&r1=295015&r2=295016&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/cxx1z-<wbr>class-template-argument-<wbr>deduction.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/cxx1z-<wbr>class-template-argument-<wbr>deduction.cpp Mon Feb 13 19:49:59 2017<br>
@@ -136,4 +136,17 @@ namespace look_into_current_instantiatio<br>
     B(typename X::type); // expected-note {{couldn't infer template argument 'T'}}<br>
   };<br>
   B b = 0; // expected-error {{no viable}}<br>
+<br>
+  // We should have a substitution failure in the immediate context of<br>
+  // deduction when using the C(T, U) constructor (probably; core wording<br>
+  // unclear).<br>
+  template<typename T> struct C {<br>
+    using U = typename T::type;<br>
+    C(T, U);<br>
+  };<br>
+<br>
+  struct R { R(int); typedef R type; };<br>
+  C(...) -> C<R>;<br>
+<br>
+  C c = {1, 2};<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">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><br></div>