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