diff options
| -rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 28 | ||||
| -rw-r--r-- | clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp | 13 |
2 files changed, 32 insertions, 9 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index e86f287e0c5..fd66c798654 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -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; } diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index 6b45a8bb2ae..011130d0e77 100644 --- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -136,4 +136,17 @@ namespace look_into_current_instantiation { 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}; } |

