xref: /llvm-project/clang/test/SemaTemplate/trailing-return-short-circuit.cpp (revision babdef27c503c0bbbcc017e9f88affddda90ea4e)
1*babdef27SErich Keane // RUN: %clang_cc1 -std=c++20 -verify %s
2*babdef27SErich Keane 
3*babdef27SErich Keane template <class T>
4*babdef27SErich Keane   requires(sizeof(T) > 2) || T::value // #FOO_REQ
5*babdef27SErich Keane void Foo(T){};                        // #FOO
6*babdef27SErich Keane 
7*babdef27SErich Keane template <class T>
8*babdef27SErich Keane void TrailingReturn(T)       // #TRAILING
9*babdef27SErich Keane   requires(sizeof(T) > 2) || // #TRAILING_REQ
10*babdef27SErich Keane           T::value           // #TRAILING_REQ_VAL
11*babdef27SErich Keane {};
12*babdef27SErich Keane template <bool B>
13*babdef27SErich Keane struct HasValue {
14*babdef27SErich Keane   static constexpr bool value = B;
15*babdef27SErich Keane };
16*babdef27SErich Keane static_assert(sizeof(HasValue<true>) <= 2);
17*babdef27SErich Keane 
18*babdef27SErich Keane template <bool B>
19*babdef27SErich Keane struct HasValueLarge {
20*babdef27SErich Keane   static constexpr bool value = B;
21*babdef27SErich Keane   int I;
22*babdef27SErich Keane };
23*babdef27SErich Keane static_assert(sizeof(HasValueLarge<true>) > 2);
24*babdef27SErich Keane 
usage()25*babdef27SErich Keane void usage() {
26*babdef27SErich Keane   // Passes the 1st check, short-circuit so the 2nd ::value is not evaluated.
27*babdef27SErich Keane   Foo(1.0);
28*babdef27SErich Keane   TrailingReturn(1.0);
29*babdef27SErich Keane 
30*babdef27SErich Keane   // Fails the 1st check, but has a ::value, so the check happens correctly.
31*babdef27SErich Keane   Foo(HasValue<true>{});
32*babdef27SErich Keane   TrailingReturn(HasValue<true>{});
33*babdef27SErich Keane 
34*babdef27SErich Keane   // Passes the 1st check, but would have passed the 2nd one.
35*babdef27SErich Keane   Foo(HasValueLarge<true>{});
36*babdef27SErich Keane   TrailingReturn(HasValueLarge<true>{});
37*babdef27SErich Keane 
38*babdef27SErich Keane   // Fails the 1st check, fails 2nd because there is no ::value.
39*babdef27SErich Keane   Foo(true);
40*babdef27SErich Keane   // expected-error@-1{{no matching function for call to 'Foo'}}
41*babdef27SErich Keane   // expected-note@#FOO{{candidate template ignored: constraints not satisfied [with T = bool]}}
42*babdef27SErich Keane   // expected-note@#FOO_REQ{{because 'sizeof(_Bool) > 2' (1 > 2) evaluated to false}}
43*babdef27SErich Keane   // expected-note@#FOO_REQ{{because substituted constraint expression is ill-formed: type 'bool' cannot be used prior to '::' because it has no members}}
44*babdef27SErich Keane 
45*babdef27SErich Keane   TrailingReturn(true);
46*babdef27SErich Keane   // expected-error@-1{{no matching function for call to 'TrailingReturn'}}
47*babdef27SErich Keane   // expected-note@#TRAILING{{candidate template ignored: constraints not satisfied [with T = bool]}}
48*babdef27SErich Keane   // expected-note@#TRAILING_REQ{{because 'sizeof(_Bool) > 2' (1 > 2) evaluated to false}}
49*babdef27SErich Keane   // expected-note@#TRAILING_REQ_VAL{{because substituted constraint expression is ill-formed: type 'bool' cannot be used prior to '::' because it has no members}}
50*babdef27SErich Keane 
51*babdef27SErich Keane   // Fails the 1st check, fails 2nd because ::value is false.
52*babdef27SErich Keane   Foo(HasValue<false>{});
53*babdef27SErich Keane   // expected-error@-1 {{no matching function for call to 'Foo'}}
54*babdef27SErich Keane   // expected-note@#FOO{{candidate template ignored: constraints not satisfied [with T = HasValue<false>]}}
55*babdef27SErich Keane   // expected-note@#FOO_REQ{{because 'sizeof(HasValue<false>) > 2' (1 > 2) evaluated to false}}
56*babdef27SErich Keane   // expected-note@#FOO_REQ{{and 'HasValue<false>::value' evaluated to false}}
57*babdef27SErich Keane   TrailingReturn(HasValue<false>{});
58*babdef27SErich Keane   // expected-error@-1 {{no matching function for call to 'TrailingReturn'}}
59*babdef27SErich Keane   // expected-note@#TRAILING{{candidate template ignored: constraints not satisfied [with T = HasValue<false>]}}
60*babdef27SErich Keane   // expected-note@#TRAILING_REQ{{because 'sizeof(HasValue<false>) > 2' (1 > 2) evaluated to false}}
61*babdef27SErich Keane   // expected-note@#TRAILING_REQ_VAL{{and 'HasValue<false>::value' evaluated to false}}
62*babdef27SErich Keane }
63