Author: rsmith Date: Mon Feb 13 19:49:59 2017 New Revision: 295016 URL: http://llvm.org/viewvc/llvm-project?rev=295016&view=rev Log: Canonicalize implicit deduction guide parameter types when forming a deduction guide from a constructor.
The purpose of this change is to avoid triggering instantiation of the class when substituting back into the deduction guide if it uses a typedef member. We will still instantiate the class if the constructor (explicitly or implicitly, directly or indirectly) uses the current instantiation in a way that we can't canonicalize out, but that seems unavoidable. Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=295016&r1=295015&r2=295016&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Feb 13 19:49:59 2017 @@ -1585,12 +1585,7 @@ private: // -- The types of the function parameters are those of the constructor. for (auto *OldParam : TL.getParams()) { - // If we're transforming a non-template constructor, just reuse its - // parameters as the parameters of the deduction guide. Otherwise, we - // need to transform their references to constructor template parameters. - ParmVarDecl *NewParam = Args.getNumLevels() - ? transformFunctionTypeParam(OldParam, Args) - : OldParam; + ParmVarDecl *NewParam = transformFunctionTypeParam(OldParam, Args); if (!NewParam) return QualType(); ParamTypes.push_back(NewParam->getType()); @@ -1636,16 +1631,31 @@ private: transformFunctionTypeParam(ParmVarDecl *OldParam, MultiLevelTemplateArgumentList &Args) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); - TypeSourceInfo *NewDI = SemaRef.SubstType( - OldDI, Args, OldParam->getLocation(), OldParam->getDeclName()); + TypeSourceInfo *NewDI = + Args.getNumLevels() + ? SemaRef.SubstType(OldDI, Args, OldParam->getLocation(), + OldParam->getDeclName()) + : OldDI; if (!NewDI) return nullptr; + // Canonicalize the type. This (for instance) replaces references to + // typedef members of the current instantiations with the definitions of + // those typedefs, avoiding triggering instantiation of the deduced type + // during deduction. + // FIXME: It would be preferable to retain type sugar and source + // information here (and handle this in substitution instead). + NewDI = SemaRef.Context.getTrivialTypeSourceInfo( + SemaRef.Context.getCanonicalType(NewDI->getType()), + OldParam->getLocation()); + // Resolving a wording defect, we also inherit default arguments from the // constructor. ExprResult NewDefArg; if (OldParam->hasDefaultArg()) { - NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args); + NewDefArg = Args.getNumLevels() + ? SemaRef.SubstExpr(OldParam->getDefaultArg(), Args) + : OldParam->getDefaultArg(); if (NewDefArg.isInvalid()) return nullptr; } Modified: cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp?rev=295016&r1=295015&r2=295016&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (original) +++ cfe/trunk/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp Mon Feb 13 19:49:59 2017 @@ -136,4 +136,17 @@ namespace look_into_current_instantiatio B(typename X::type); // expected-note {{couldn't infer template argument 'T'}} }; B b = 0; // expected-error {{no viable}} + + // We should have a substitution failure in the immediate context of + // deduction when using the C(T, U) constructor (probably; core wording + // unclear). + template<typename T> struct C { + using U = typename T::type; + C(T, U); + }; + + struct R { R(int); typedef R type; }; + C(...) -> C<R>; + + C c = {1, 2}; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits