diff options
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 40 | ||||
-rw-r--r-- | clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp | 29 |
2 files changed, 54 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index dd116326711..919bc7b63d5 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1659,6 +1659,23 @@ DeclResult Sema::CheckClassTemplate( } namespace { +/// Tree transform to "extract" a transformed type from a class template's +/// constructor to a deduction guide. +class ExtractTypeForDeductionGuide + : public TreeTransform<ExtractTypeForDeductionGuide> { +public: + typedef TreeTransform<ExtractTypeForDeductionGuide> Base; + ExtractTypeForDeductionGuide(Sema &SemaRef) : Base(SemaRef) {} + + TypeSourceInfo *transform(TypeSourceInfo *TSI) { return TransformType(TSI); } + + QualType TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { + return TransformType( + TLB, + TL.getTypedefNameDecl()->getTypeSourceInfo()->getTypeLoc()); + } +}; + /// Transform to convert portions of a constructor declaration into the /// corresponding deduction guide, per C++1z [over.match.class.deduct]p1. struct ConvertConstructorToDeductionGuideTransform { @@ -1880,9 +1897,7 @@ private: MultiLevelTemplateArgumentList &Args) { TypeSourceInfo *OldDI = OldParam->getTypeSourceInfo(); TypeSourceInfo *NewDI; - if (!Args.getNumLevels()) - NewDI = OldDI; - else if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { + if (auto PackTL = OldDI->getTypeLoc().getAs<PackExpansionTypeLoc>()) { // Expand out the one and only element in each inner pack. Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(SemaRef, 0); NewDI = @@ -1898,23 +1913,17 @@ private: 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()); + // Extract 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. + NewDI = ExtractTypeForDeductionGuide(SemaRef).transform(NewDI); // Resolving a wording defect, we also inherit default arguments from the // constructor. ExprResult NewDefArg; if (OldParam->hasDefaultArg()) { - NewDefArg = Args.getNumLevels() - ? SemaRef.SubstExpr(OldParam->getDefaultArg(), Args) - : OldParam->getDefaultArg(); + NewDefArg = SemaRef.SubstExpr(OldParam->getDefaultArg(), Args); if (NewDefArg.isInvalid()) return nullptr; } @@ -1929,6 +1938,7 @@ private: NewDefArg.get()); NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(), OldParam->getFunctionScopeIndex()); + SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam); return NewParam; } diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index f72cb886d81..cbf7c2eee51 100644 --- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -373,6 +373,35 @@ void bar(D<int>& d) { } } +namespace rdar41330135 { +template <int> struct A {}; +template <class T> +struct S { + template <class U> + S(T a, U t, A<sizeof(t)>); +}; +template <class T> struct D { + D(T t, A<sizeof(t)>); +}; +int f() { + S s(0, 0, A<sizeof(int)>()); + D d(0, A<sizeof(int)>()); +} + +namespace test_dupls { +template<unsigned long> struct X {}; +template<typename T> struct A { + A(T t, X<sizeof(t)>); +}; +A a(0, {}); +template<typename U> struct B { + B(U u, X<sizeof(u)>); +}; +B b(0, {}); +} + +} + #else // expected-no-diagnostics |