================ @@ -478,3 +478,166 @@ A a{.f1 = {1}}; // CHECK-NEXT: `-DeclRefExpr {{.+}} <col:10> 'int' NonTypeTemplateParm {{.+}} 'N' 'int' } // namespace GH83368 + +namespace GH60777 { + +template <typename... Ts> constexpr bool True() { return true; } + +template <typename T> + requires(sizeof(T) == 4) +struct A { + template <typename... Ts> + requires(sizeof...(Ts) == 0) + A(T val, Ts... tail) + requires(True<Ts...>()) + {} +}; + +A a(42); + +// `requires (sizeof(T) == 4)` goes into the deduction guide together with +// `requires (True<Ts...>())`, while `requires(sizeof...(Ts) == 0)` goes into +// the template parameter list of the synthesized declaration. + +// CHECK-LABEL: Dumping GH60777::<deduction guide for A>: +// CHECK-NEXT: FunctionTemplateDecl 0x{{.+}} <{{.+}}> {{.+}} implicit <deduction guide for A> +// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:20 referenced typename depth 0 index 0 T +// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:25 typename depth 0 index 1 ... Ts +// CHECK-NEXT: |-ParenExpr 0x{{.+}} <{{.+}}> 'bool' +// CHECK-NEXT: | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '==' +// CHECK-NEXT: | |-SizeOfPackExpr 0x{{.+}} <{{.+}}> 'unsigned long' 0x{{.+}} Ts +// CHECK-NEXT: | | `-TemplateArgument type 'Ts...':'type-parameter-0-1...' +// CHECK-NEXT: | | `-PackExpansionType 0x{{.+}} 'Ts...' dependent +// CHECK-NEXT: | | `-TemplateTypeParmType 0x{{.+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack +// CHECK-NEXT: | | `-TemplateTypeParm 0x{{.+}} 'Ts' +// CHECK-NEXT: | `-ImplicitCastExpr 0x{{.+}} <{{.+}}> 'unsigned long' <IntegralCast> +// CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <{{.+}}> 'int' 0 +// CHECK-NEXT: |-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> line:{{.+}} implicit <deduction guide for A> 'auto (T, Ts...) -> A<T>' +// CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <{{.+}}> col:{{.+}} val 'T' +// CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <{{.+}}> col:{{.+}} tail 'Ts...' pack +// CHECK-NEXT: | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '&&' +// CHECK-NEXT: | |-ParenExpr 0x{{.+}} <{{.+}}> 'bool' +// CHECK-NEXT: | | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '==' +// CHECK-NEXT: | | |-UnaryExprOrTypeTraitExpr 0x{{.+}} <{{.+}}> 'unsigned long' sizeof 'T' +// CHECK-NEXT: | | `-ImplicitCastExpr 0x{{.+}} <{{.+}}> 'unsigned long' <IntegralCast> +// CHECK-NEXT: | | `-IntegerLiteral 0x{{.+}} <{{.+}}> 'int' 4 +// CHECK-NEXT: | `-ParenExpr 0x{{.+}} <{{.+}}> '<dependent type>' +// CHECK-NEXT: | `-CallExpr 0x{{.+}} <{{.+}}> '<dependent type>' +// CHECK-NEXT: | `-UnresolvedLookupExpr 0x{{.+}} <col:14, col:24> '<dependent type>' lvalue (ADL) = 'True' 0x{{.+}} +// CHECK-NEXT: | `-TemplateArgument type 'Ts...':'type-parameter-0-1...' +// CHECK-NEXT: | `-PackExpansionType 0x{{.+}} 'Ts...' dependent +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack +// CHECK-NEXT: | `-TemplateTypeParm 0x{{.+}} 'Ts' + +template <typename T> +struct B { + template <typename... Ts> + B(T val, Ts... tail) + requires(True<tail...>()) + {} +}; + +B b(42, 43); +// expected-error@-1 {{no viable constructor}} \ +// expected-note@-6 {{constraints not satisfied}} \ +// expected-note@-5 {{because substituted constraint expression is ill-formed}} \ +// expected-note@-6 {{implicit deduction guide declared as 'template <typename T, typename ...Ts> B(T val, Ts ...tail) -> B<T> requires (True<tail...>())'}} \ +// expected-note@-8 {{function template not viable}} \ +// expected-note@-8 {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}} + +} // namespace GH60777 + +// Examples from @hokein. +namespace GH98592 { + +template <class T> concept True = true; +double arr3[3]; + +template <class T> +struct X { + const int size; + template <class U> + constexpr X(T, U(&)[3]) requires True<T> : size(sizeof(T)) {} +}; + +template <typename T, typename U> +X(T, U (&)[3]) -> X<U>; + +constexpr X x(3, arr3); + +// The synthesized deduction guide is more constrained than the explicit one. +static_assert(x.size == 4); + +// CHECK-LABEL: Dumping GH98592::<deduction guide for X>: +// CHECK-NEXT: FunctionTemplateDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for X> +// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:17 referenced class depth 0 index 0 T +// CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:19 class depth 0 index 1 U +// CHECK-NEXT: |-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for X> 'auto (T, U (&)[3]) -> X<T>' +// CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <col:15> col:16 'T' +// CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'U (&)[3]' +// CHECK-NEXT: | `-ConceptSpecializationExpr 0x{{.+}} <col:36, col:42> 'bool' Concept 0x{{.+}} 'True' +// CHECK-NEXT: | |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28 +// CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-0-0' +// CHECK-NEXT: | | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0' +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: | `-TemplateTypeParm 0x{{.+}} 'T' +// CHECK-NEXT: `-CXXDeductionGuideDecl 0x{{.+}} <col:3, col:63> col:13 implicit used <deduction guide for X> 'auto (int, double (&)[3]) -> GH98592::X<int>' implicit_instantiation +// CHECK-NEXT: |-TemplateArgument type 'int' +// CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'int' +// CHECK-NEXT: |-TemplateArgument type 'double' +// CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'double' +// CHECK-NEXT: |-ParmVarDecl 0x{{.+}} <col:15> col:16 'int' +// CHECK-NEXT: |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'double (&)[3]' +// CHECK-NEXT: `-ConceptSpecializationExpr 0x{{.+}} <col:36, col:42> 'bool' Concept 0x{{.+}} 'True' +// CHECK-NEXT: |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28 +// CHECK-NEXT: | `-TemplateArgument type 'type-parameter-0-0' +// CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0 +// CHECK-NEXT: `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0' +// CHECK-NEXT: `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0 +// CHECK-NEXT: `-TemplateTypeParm 0x{{.+}} 'T' + +template <class T> requires True<T> struct Y { + const int size; + template <class U> + constexpr Y(T, U(&)[3]) : size(sizeof(T)) {} +}; + +template <typename T, typename U> Y(T, U (&)[3]) -> Y<U>; + +constexpr Y y(3, arr3); + +// Likewise, the synthesized deduction guide should be preferred +// according to [over.match.class.deduct]p1. +static_assert(y.size == 4); ---------------- cor3ntin wrote:
I'm trying to figure if the order of operation is observable - I don't think so, so I am confused by the note @erichkeane https://github.com/llvm/llvm-project/pull/111143 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits