1 // RUN:  %clang_cc1 -std=c++2a -verify %s
2 
3 // Make sure constraint expressions are unevaluated before being substituted
4 // into during satisfaction checking.
5 
6 template<typename T> constexpr bool f = T::value;
7 // expected-error@-1 4{{type}}
8 
9 namespace unevaluated {
10   template<typename T> concept Foo = false && f<int>;
11   bool k = Foo<int>;
12   template<typename T> requires false && f<int> struct S {};
13   // expected-note@-1{{because}}
14   using s = S<int>; // expected-error {{constraints not satisfied}}
foo()15   template<typename T> void foo() requires false && f<int> { };
16   // expected-note@-1{{because}} expected-note@-1{{candidate template ignored}}
17   int a = (foo<int>(), 0); // expected-error{{no matching function}}
bar()18   template<typename T> void bar() requires requires { requires false && f<int>; } { };
19   // expected-note@-1{{because}} expected-note@-1{{candidate template ignored}}
20   int b = (bar<int>(), 0); // expected-error{{no matching function}}
foounevaluated::M21   template<typename T> struct M { static void foo() requires false && f<int> { }; };
22   // expected-note@-1{{because}}
23   int c = (M<int>::foo(), 0);
24   // expected-error@-1{{invalid reference to function 'foo': constraints not satisfied}}
25 }
26 
27 namespace constant_evaluated {
28   template<typename T> requires f<int[0]> struct S {};
29   // expected-note@-1{{in instantiation of}} expected-note@-1{{while substituting}} \
30      expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}} \
31      expected-note@-1{{subexpression not valid}}
32   using s = S<int>;
33   // expected-note@-1 2{{while checking}}
foo()34   template<typename T> void foo() requires f<int[1]> { };
35   // expected-note@-1{{in instantiation}} expected-note@-1{{while substituting}} \
36      expected-note@-1{{candidate template ignored}} expected-note@-1{{subexpression not valid}} \
37      expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}}
38   int a = (foo<int>(), 0);
39   // expected-note@-1 2{{while checking}} expected-error@-1{{no matching function}} \
40      expected-note@-1 2{{in instantiation}}
bar()41   template<typename T> void bar() requires requires { requires f<int[2]>; } { };
42   // expected-note@-1{{in instantiation}} expected-note@-1{{subexpression not valid}} \
43      expected-note@-1{{while substituting}} \
44      expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}} \
45      expected-note@-1 2{{while checking the satisfaction of nested requirement}}
46   int b = (bar<int>(), 0);
fooconstant_evaluated::M47   template<typename T> struct M { static void foo() requires f<int[3]> { }; };
48   // expected-note@-1{{in instantiation}} expected-note@-1{{subexpression not valid}} \
49      expected-note@-1{{while substituting}} \
50      expected-error@-1{{substitution into constraint expression resulted in a non-constant expression}}
51   int c = (M<int>::foo(), 0);
52   // expected-note@-1 2{{while checking}}
53 }
54