}
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 {
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 =
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;
}
NewDefArg.get());
NewParam->setScopeInfo(OldParam->getFunctionScopeDepth(),
OldParam->getFunctionScopeIndex());
+ SemaRef.CurrentInstantiationScope->InstantiatedLocal(OldParam, NewParam);
return NewParam;
}
}
}
+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