1 // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu
2 
3 using size_t = decltype(sizeof(int));
4 
5 namespace std {
is_constant_evaluated()6 inline constexpr bool is_constant_evaluated() noexcept {
7   return __builtin_is_constant_evaluated();
8 }
9 } // namespace std
10 
11 extern int dummy; // expected-note 1+ {{declared here}}
12 
13 static_assert(__builtin_is_constant_evaluated());
14 static_assert(noexcept(__builtin_is_constant_evaluated()));
15 
16 constexpr bool b = __builtin_is_constant_evaluated();
17 static_assert(b);
18 
19 const int n = __builtin_is_constant_evaluated() ? 4 : dummy;
20 static_assert(n == 4);
21 constexpr int cn = __builtin_is_constant_evaluated() ? 11 : dummy;
22 static_assert(cn == 11);
23 // expected-error@+1 {{'bn' must be initialized by a constant expression}}
24 constexpr int bn = __builtin_is_constant_evaluated() ? dummy : 42; // expected-note {{non-const variable 'dummy' is not allowed}}
25 
26 const int n2 = __builtin_is_constant_evaluated() ? dummy : 42; // expected-note {{declared here}}
27 static_assert(n2 == 42);                                       // expected-error {{static_assert expression is not an integral constant}}
28 // expected-note@-1 {{initializer of 'n2' is not a constant expression}}
29 
30 template <bool V, bool Default = std::is_constant_evaluated()>
31 struct Templ { static_assert(V); static_assert(Default); };
32 Templ<__builtin_is_constant_evaluated()> x; // type X<true>
33 
34 template <class T>
test_if_constexpr()35 void test_if_constexpr() {
36   if constexpr (__builtin_is_constant_evaluated()) {
37     static_assert(__is_same(T, int));
38   } else {
39     using Test = typename T::DOES_NOT_EXIST;
40   }
41 }
42 template void test_if_constexpr<int>();
43 
test_array_decl()44 void test_array_decl() {
45   char x[__builtin_is_constant_evaluated() + std::is_constant_evaluated()];
46   static_assert(sizeof(x) == 2, "");
47 }
48 
test_case_stmt(int x)49 void test_case_stmt(int x) {
50   switch (x) {
51   case 0:                                                                // OK
52   case __builtin_is_constant_evaluated():                                // expected-note {{previous case}}
53   case std::is_constant_evaluated() + __builtin_is_constant_evaluated(): // expected-note {{previous case}}
54   case 1:                                                                // expected-error {{duplicate case value '1'}}
55   case 2:                                                                // expected-error {{duplicate case value '2'}}
56     break;
57   }
58 }
59 
good_array_size()60 constexpr size_t good_array_size() {
61   return std::is_constant_evaluated() ? 42 : static_cast<size_t>(-1);
62 }
63 
bad_array_size()64 constexpr size_t bad_array_size() {
65   return std::is_constant_evaluated() ? static_cast<size_t>(-1) : 13;
66 }
67 
68 template <class T>
require_constexpr(T v)69 constexpr T require_constexpr(T v) {
70   if (!std::is_constant_evaluated())
71     throw "BOOM";
72   return v;
73 }
74 
test_new_expr()75 void test_new_expr() {
76   constexpr size_t TooLarge = -1;
77   auto *x = new int[std::is_constant_evaluated() ? 1 : TooLarge];      // expected-error {{array is too large}}
78   auto *x2 = new int[std::is_constant_evaluated() ? TooLarge : 1];     // OK
79   auto *y = new int[1][std::is_constant_evaluated() ? TooLarge : 1]{}; // expected-error {{array is too large}}
80   auto *y2 = new int[1][require_constexpr(42)];
81 }
82 
test_alignas_operand()83 void test_alignas_operand() {
84   alignas(std::is_constant_evaluated() ? 8 : 2) char dummy;
85   static_assert(__alignof(dummy) == 8);
86 }
87 
test_static_assert_operand()88 void test_static_assert_operand() {
89   static_assert(std::is_constant_evaluated(), "");
90 }
91 
test_enumerator()92 void test_enumerator() {
93   enum MyEnum {
94     ZERO = 0,
95     ONE = std::is_constant_evaluated()
96   };
97   static_assert(ONE == 1, "");
98 }
99 
100 struct TestBitfieldWidth {
101   unsigned Bits : std::is_constant_evaluated();
102 };
103 
104 void test_operand_of_noexcept_fn() noexcept(std::is_constant_evaluated());
105 static_assert(noexcept(test_operand_of_noexcept_fn()), "");
106 
107 
108 namespace test_ref_initialization {
109 int x;
110 int y;
111 int &r = __builtin_is_constant_evaluated() ? x : y;
112 static_assert(&r == &x);
113 
114 } // namespace test_ref_initialization
115 
116 #if defined(__cpp_conditional_explicit)
117 struct TestConditionalExplicit {
TestConditionalExplicitTestConditionalExplicit118   explicit(!__builtin_is_constant_evaluated()) TestConditionalExplicit(int) {}
119 };
120 TestConditionalExplicit e = 42;
121 #endif
122