@@ -479,6 +479,169 @@ A a{.f1 = {1}};
479479
480480} // namespace GH83368
481481
482+ namespace GH60777 {
483+
484+ template <typename ... Ts> constexpr bool True () { return true ; }
485+
486+ template <typename T>
487+ requires (sizeof (T) > 1 )
488+ struct A {
489+ template <typename ... Ts>
490+ requires (sizeof ...(Ts) == 0 )
491+ A (T val, Ts... tail)
492+ requires (True<Ts...>())
493+ {}
494+ };
495+
496+ A a (42 );
497+
498+ // `requires (sizeof(T) > 1)` goes into the deduction guide together with
499+ // `requires (True<Ts...>())`, while `requires(sizeof...(Ts) == 0)` goes into
500+ // the template parameter list of the synthesized declaration.
501+
502+ // CHECK-LABEL: Dumping GH60777::<deduction guide for A>:
503+ // CHECK-NEXT: FunctionTemplateDecl 0x{{.+}} <{{.+}}> {{.+}} implicit <deduction guide for A>
504+ // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:20 referenced typename depth 0 index 0 T
505+ // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:25 typename depth 0 index 1 ... Ts
506+ // CHECK-NEXT: |-ParenExpr 0x{{.+}} <{{.+}}> 'bool'
507+ // CHECK-NEXT: | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '=='
508+ // CHECK-NEXT: | |-SizeOfPackExpr {{.+}} Ts
509+ // CHECK-NEXT: | | `-TemplateArgument type 'Ts...':'type-parameter-0-1...'
510+ // CHECK-NEXT: | | `-PackExpansionType 0x{{.+}} 'Ts...' dependent
511+ // CHECK-NEXT: | | `-TemplateTypeParmType 0x{{.+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
512+ // CHECK-NEXT: | | `-TemplateTypeParm 0x{{.+}} 'Ts'
513+ // CHECK-NEXT: | `-ImplicitCastExpr {{.+}} <IntegralCast>
514+ // CHECK-NEXT: | `-IntegerLiteral 0x{{.+}} <{{.+}}> 'int' 0
515+ // CHECK-NEXT: |-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> line:{{.+}} implicit <deduction guide for A> 'auto (T, Ts...) -> A<T>'
516+ // CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <{{.+}}> col:{{.+}} val 'T'
517+ // CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <{{.+}}> col:{{.+}} tail 'Ts...' pack
518+ // CHECK-NEXT: | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '&&'
519+ // CHECK-NEXT: | |-ParenExpr 0x{{.+}} <{{.+}}> 'bool'
520+ // CHECK-NEXT: | | `-BinaryOperator 0x{{.+}} <{{.+}}> 'bool' '>'
521+ // CHECK-NEXT: | | |-UnaryExprOrTypeTraitExpr {{.+}} sizeof 'T'
522+ // CHECK-NEXT: | | `-ImplicitCastExpr {{.+}} <IntegralCast>
523+ // CHECK-NEXT: | | `-IntegerLiteral 0x{{.+}} <{{.+}}> 'int' 1
524+ // CHECK-NEXT: | `-ParenExpr 0x{{.+}} <{{.+}}> '<dependent type>'
525+ // CHECK-NEXT: | `-CallExpr 0x{{.+}} <{{.+}}> '<dependent type>'
526+ // CHECK-NEXT: | `-UnresolvedLookupExpr 0x{{.+}} <col:14, col:24> '<dependent type>' {{.+}}
527+ // CHECK-NEXT: | `-TemplateArgument type 'Ts...':'type-parameter-0-1...'
528+ // CHECK-NEXT: | `-PackExpansionType 0x{{.+}} 'Ts...' dependent
529+ // CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
530+ // CHECK-NEXT: | `-TemplateTypeParm 0x{{.+}} 'Ts'
531+
532+ template <typename T>
533+ struct B {
534+ template <typename ... Ts>
535+ B (T val, Ts... tail)
536+ requires (True<tail...>())
537+ {}
538+ };
539+
540+ B b (42 , 43 );
541+ // expected-error@-1 {{no viable constructor}} \
542+ // expected-note@-6 {{constraints not satisfied}} \
543+ // expected-note@-5 {{because substituted constraint expression is ill-formed}} \
544+ // expected-note@-6 {{implicit deduction guide declared as 'template <typename T, typename ...Ts> B(T val, Ts ...tail) -> B<T> requires (True<tail...>())'}} \
545+ // expected-note@-8 {{function template not viable}} \
546+ // expected-note@-8 {{implicit deduction guide declared as 'template <typename T> B(B<T>) -> B<T>'}}
547+
548+ } // namespace GH60777
549+
550+ // Examples from @hokein.
551+ namespace GH98592 {
552+
553+ template <class T > concept True = true ;
554+ double arr3[3 ];
555+
556+ template <class T >
557+ struct X {
558+ const int size;
559+ template <class U >
560+ constexpr X (T, U(&)[3]) requires True<T> : size(sizeof (T)) {}
561+ };
562+
563+ template <typename T, typename U>
564+ X (T, U (&)[3 ]) -> X<U>;
565+
566+ constexpr X x (3 , arr3);
567+
568+ // The synthesized deduction guide is more constrained than the explicit one.
569+ static_assert (x.size == 4 );
570+
571+ // CHECK-LABEL: Dumping GH98592::<deduction guide for X>:
572+ // CHECK-NEXT: FunctionTemplateDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for X>
573+ // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:17 referenced class depth 0 index 0 T
574+ // CHECK-NEXT: |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:19 class depth 0 index 1 U
575+ // CHECK-NEXT: |-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for X> 'auto (T, U (&)[3]) -> X<T>'
576+ // CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <col:15> col:16 'T'
577+ // CHECK-NEXT: | |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'U (&)[3]'
578+ // CHECK-NEXT: | `-ConceptSpecializationExpr 0x{{.+}} <col:36, col:42> 'bool' Concept 0x{{.+}} 'True'
579+ // CHECK-NEXT: | |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28
580+ // CHECK-NEXT: | | `-TemplateArgument type 'type-parameter-0-0'
581+ // CHECK-NEXT: | | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0
582+ // CHECK-NEXT: | `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0'
583+ // CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0
584+ // CHECK-NEXT: | `-TemplateTypeParm 0x{{.+}} 'T'
585+ // 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
586+ // CHECK-NEXT: |-TemplateArgument type 'int'
587+ // CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'int'
588+ // CHECK-NEXT: |-TemplateArgument type 'double'
589+ // CHECK-NEXT: | `-BuiltinType 0x{{.+}} 'double'
590+ // CHECK-NEXT: |-ParmVarDecl 0x{{.+}} <col:15> col:16 'int'
591+ // CHECK-NEXT: |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'double (&)[3]'
592+ // CHECK-NEXT: `-ConceptSpecializationExpr 0x{{.+}} <col:36, col:42> 'bool' Concept 0x{{.+}} 'True'
593+ // CHECK-NEXT: |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28
594+ // CHECK-NEXT: | `-TemplateArgument type 'type-parameter-0-0'
595+ // CHECK-NEXT: | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0
596+ // CHECK-NEXT: `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0'
597+ // CHECK-NEXT: `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0
598+ // CHECK-NEXT: `-TemplateTypeParm 0x{{.+}} 'T'
599+
600+ template <class T > requires True<T> struct Y {
601+ const int size;
602+ template <class U >
603+ constexpr Y (T, U(&)[3]) : size(sizeof (T)) {}
604+ };
605+
606+ template <typename T, typename U> Y (T, U (&)[3]) -> Y<U>;
607+
608+ constexpr Y y (3 , arr3);
609+
610+ // Likewise, the synthesized deduction guide should be preferred
611+ // according to [over.match.class.deduct]p1.
612+ static_assert (y.size == 4 );
613+
614+ // Dumping GH98592::<deduction guide for Y>:
615+ // FunctionTemplateDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for Y>
616+ // |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:17 referenced class depth 0 index 0 T
617+ // |-TemplateTypeParmDecl 0x{{.+}} <{{.+}}> col:19 class depth 0 index 1 U
618+ // |-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> col:13 implicit <deduction guide for Y> 'auto (T, U (&)[3]) -> Y<T>'
619+ // | |-ParmVarDecl 0x{{.+}} <col:15> col:16 'T'
620+ // | |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'U (&)[3]'
621+ // | `-ConceptSpecializationExpr 0x{{.+}} <{{.+}}> 'bool' Concept 0x{{.+}} 'True'
622+ // | |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28
623+ // | | `-TemplateArgument type 'type-parameter-0-0'
624+ // | | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0
625+ // | `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0'
626+ // | `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0
627+ // | `-TemplateTypeParm 0x{{.+}} 'T'
628+ // `-CXXDeductionGuideDecl 0x{{.+}} <{{.+}}> col:13 implicit used <deduction guide for Y> 'auto (int, double (&)[3]) -> GH98592::Y<int>' implicit_instantiation
629+ // |-TemplateArgument type 'int'
630+ // | `-BuiltinType 0x{{.+}} 'int'
631+ // |-TemplateArgument type 'double'
632+ // | `-BuiltinType 0x{{.+}} 'double'
633+ // |-ParmVarDecl 0x{{.+}} <col:15> col:16 'int'
634+ // |-ParmVarDecl 0x{{.+}} <col:18, col:24> col:21 'double (&)[3]'
635+ // `-ConceptSpecializationExpr 0x{{.+}} <{{.+}}> 'bool' Concept 0x{{.+}} 'True'
636+ // |-ImplicitConceptSpecializationDecl 0x{{.+}} <{{.+}}> col:28
637+ // | `-TemplateArgument type 'type-parameter-0-0'
638+ // | `-TemplateTypeParmType 0x{{.+}} 'type-parameter-0-0' dependent depth 0 index 0
639+ // `-TemplateArgument <{{.+}}> type 'T':'type-parameter-0-0'
640+ // `-TemplateTypeParmType 0x{{.+}} 'T' dependent depth 0 index 0
641+ // `-TemplateTypeParm 0x{{.+}} 'T'
642+
643+ } // namespce GH98592
644+
482645namespace GH122134 {
483646
484647template <class , class >
0 commit comments