// RUN: %clang_cc1 -triple x86_64-unknown-unknown -std=c++2a -ast-dump %s | FileCheck -strict-whitespace %s template constexpr bool Concept = true; template // depth 0 struct Out { template // depth 1 struct Inner { U t; }; template // depth1 requires Concept Inner(V) -> Inner; }; template struct Out2 { template // depth1 using AInner = Out::Inner; }; Out2::AInner t(1.0); // Verify that the require-clause of alias deduction guide is transformed correctly: // - Occurrence T should be replaced with `int`; // - Occurrence V should be replaced with the Y with depth 1 // - Depth of occurrence Y in the __is_deducible constraint should be 1 // // CHECK: | `-FunctionTemplateDecl {{.*}} // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 Y // CHECK-NEXT: | |-BinaryOperator {{.*}} '' '&&' // CHECK-NEXT: | | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' // CHECK-NEXT: | | | |-TemplateArgument type 'int' // CHECK-NEXT: | | | | `-BuiltinType {{.*}} 'int' // CHECK-NEXT: | | | `-TemplateArgument type 'Y':'type-parameter-1-0' // CHECK-NEXT: | | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 // CHECK-NEXT: | | | `-TemplateTypeParm {{.*}} 'Y' // CHECK-NEXT: | | `-TypeTraitExpr {{.*}} 'bool' __is_deducible // CHECK-NEXT: | | |-DeducedTemplateSpecializationType {{.*}} 'Out2::AInner' dependent // CHECK-NEXT: | | | `-name: 'Out2::AInner' // CHECK-NEXT: | | | `-TypeAliasTemplateDecl {{.+}} AInner{{$}} // CHECK-NEXT: | | `-ElaboratedType {{.*}} 'Inner' sugar dependent // CHECK-NEXT: | | `-TemplateSpecializationType {{.*}} 'Inner' dependent // CHECK-NEXT: | | |-name: 'Inner':'Out::Inner' qualified // CHECK-NEXT: | | | `-ClassTemplateDecl {{.+}} Inner{{$}} // CHECK-NEXT: | | `-TemplateArgument type 'Y' // CHECK-NEXT: | | `-SubstTemplateTypeParmType {{.*}} 'Y' // CHECK-NEXT: | | |-FunctionTemplate {{.*}} '' // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'Y' dependent depth 1 index 0 // CHECK-NEXT: | | `-TemplateTypeParm {{.*}} 'Y' // CHECK-NEXT: | |-CXXDeductionGuideDecl {{.*}} 'auto (Y) -> Inner' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'Y' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} used 'auto (double) -> Inner' implicit_instantiation // CHECK-NEXT: | |-TemplateArgument type 'double' // CHECK-NEXT: | | `-BuiltinType {{.*}} 'double' // CHECK-NEXT: | `-ParmVarDecl {{.*}} 'double' // GH92596 template struct Out3 { template struct Foo { // Deduction guide: // template // Foo(V, T1) -> Foo; template requires Concept // V in require clause of Foo deduction guide: depth 1, index: 2 Foo(V, T1); }; }; template using AFoo3 = Out3::Foo; AFoo3 afoo3{0, 1}; // Verify occurrence V in the require-clause is transformed (depth: 1 => 0, index: 2 => 1) correctly. // CHECK: FunctionTemplateDecl {{.*}} implicit // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T3 // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 V // CHECK-NEXT: |-BinaryOperator {{.*}} '' '&&' // CHECK-NEXT: | |-UnresolvedLookupExpr {{.*}} '' lvalue (no ADL) = 'Concept' // CHECK-NEXT: | | |-TemplateArgument type 'int' // CHECK-NEXT: | | | `-BuiltinType {{.*}} 'int' // CHECK-NEXT: | | `-TemplateArgument type 'V' // CHECK-NEXT: | | `-TemplateTypeParmType {{.*}} 'V' dependent depth 0 index 1 template struct Foo { Foo(T1...); }; template using AFoo = Foo; AFoo a(1, 2); // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (T2...) -> Foo' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T2...' pack // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (int, int) -> Foo' implicit_instantiation template using BFoo = Foo; BFoo b2(1.0, 2.0); // CHECK: |-CXXDeductionGuideDecl {{.*}} implicit 'auto (T, T) -> Foo' // CHECK-NEXT: | | |-ParmVarDecl {{.*}} 'T' // CHECK-NEXT: | | `-ParmVarDecl {{.*}} 'T' // CHECK-NEXT: | `-CXXDeductionGuideDecl {{.*}} implicit used 'auto (double, double) -> Foo' implicit_instantiation namespace GH90209 { // Case 1: type template parameter template struct List1 { List1(int); }; template struct TemplatedClass1 { TemplatedClass1(T1); }; template TemplatedClass1(T1) -> TemplatedClass1>; template using ATemplatedClass1 = TemplatedClass1>; ATemplatedClass1 test1(1); // Verify that we have a correct template parameter list for the deduction guide. // // CHECK: FunctionTemplateDecl {{.*}} // CHECK-NEXT: |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T2 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible // Case 2: template template parameter template struct Foo{}; template typename Ts> struct List2 { List2(int); }; template struct TemplatedClass2 { TemplatedClass2(T1); }; template typename T1> TemplatedClass2(T1) -> TemplatedClass2>; template typename T2> using ATemplatedClass2 = TemplatedClass2>; List2 list(1); ATemplatedClass2 test2(list); // Verify that we have a correct template parameter list for the deduction guide. // // CHECK: FunctionTemplateDecl {{.*}} // CHECK-NEXT: |-TemplateTemplateParmDecl {{.*}} depth 0 index 0 T2 // CHECK-NEXT: | `-TemplateTypeParmDecl {{.*}} typename depth 0 index 0 // CHECK-NEXT: |-TypeTraitExpr {{.*}} 'bool' __is_deducible } // namespace GH90209 namespace GH124715 { template concept invocable = true; template struct Struct { template requires invocable Struct(U, Args...) {} }; template struct Packs {}; template Struct(Lambda lambda, Args... args) -> Struct; template using Alias = Struct>; void foo() { Alias([](int) {}, Packs()); } // CHECK: |-FunctionTemplateDecl {{.*}} implicit // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 0 T // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 1 ... Ts // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} class depth 0 index 2 U // CHECK-NEXT: | |-BinaryOperator {{.*}} 'bool' '&&' // CHECK-NEXT: | | |-ConceptSpecializationExpr {{.*}} 'bool' Concept {{.*}} 'invocable' // CHECK-NEXT: | | | |-ImplicitConceptSpecializationDecl {{.*}} // CHECK-NEXT: | | | | |-TemplateArgument type 'type-parameter-0-2' // CHECK-NEXT: | | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-2' dependent depth 0 index 2 // CHECK-NEXT: | | | | `-TemplateArgument pack '>' // CHECK-NEXT: | | | | `-TemplateArgument type 'Packs' // CHECK-NEXT: | | | | `-TemplateSpecializationType {{.*}} 'Packs' dependent // CHECK-NEXT: | | | | |-name: 'GH124715::Packs' // CHECK-NEXT: | | | | | `-ClassTemplateDecl {{.*}} Packs // CHECK-NEXT: | | | | `-TemplateArgument pack '' // CHECK-NEXT: | | | | `-TemplateArgument type 'type-parameter-0-1...' // CHECK-NEXT: | | | | `-PackExpansionType {{.*}} 'type-parameter-0-1...' dependent // CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack // CHECK-NEXT: | | | |-TemplateArgument {{.*}} type 'U':'type-parameter-0-2' // CHECK-NEXT: | | | | `-TemplateTypeParmType {{.*}} 'U' dependent depth 0 index 2 // CHECK-NEXT: | | | | `-TemplateTypeParm {{.*}} 'U' } // namespace GH124715