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