1 // RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -std=c++2a -o %t.ll 2 // RUN: FileCheck -check-prefix=CHECK-FN-CG -input-file=%t.ll %s 3 // RUN: FileCheck -check-prefix=CHECK-STATIC -input-file=%t.ll %s 4 // RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s 5 // RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s 6 // RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s 7 8 using size_t = decltype(sizeof(int)); 9 10 #define CONSTINIT __attribute__((require_constant_initialization)) 11 12 extern "C" [[noreturn]] void BOOM(); 13 extern "C" void OK(); 14 extern "C" size_t RANDU(); 15 16 namespace std { 17 inline constexpr bool is_constant_evaluated() noexcept { 18 return __builtin_is_constant_evaluated(); 19 } 20 } // namespace std 21 22 // CHECK-FN-CG-LABEL: define zeroext i1 @_Z3foov() 23 // CHECK-FN-CG: ret i1 false 24 bool foo() { 25 return __builtin_is_constant_evaluated(); 26 } 27 28 // CHECK-FN-CG-LABEL: define linkonce_odr i32 @_Z1fv() 29 constexpr int f() { 30 // CHECK-FN-CG: store i32 13, i32* %n, align 4 31 // CHECK-FN-CG: store i32 17, i32* %m, align 4 32 // CHECK-FN-CG: %1 = load i32, i32* %m, align 4 33 // CHECK-FN-CG: %add = add nsw i32 %1, 13 34 // CHECK-FN-CG: ret i32 %add 35 const int n = __builtin_is_constant_evaluated() && std::is_constant_evaluated() ? 13 : 17; // n == 13 36 int m = __builtin_is_constant_evaluated() ? 13 : 17; // m might be 13 or 17 (see below) 37 char arr[n] = {}; // char[13] 38 return m + int(sizeof(arr)); 39 } 40 41 // CHECK-STATIC-DAG: @p = global i32 26, 42 CONSTINIT int p = f(); // f().m == 13; initialized to 26 43 // CHECK-STATIC-DAG: @p2 = global i32 26, 44 int p2 = f(); // same result without CONSTINIT 45 46 // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init() 47 // CHECK-DYN: %0 = load i32, i32* @p, align 4 48 // CHECK-DYN-NEXT: %call = call i32 @_Z1fv() 49 // CHECK-DYN-NEXT: %add = add nsw i32 %0, %call 50 // CHECK-DYN-NEXT: store i32 %add, i32* @q, align 4 51 // CHECK-DYN-NEXT: ret void 52 int q = p + f(); // m == 17 for this call; initialized to 56 53 54 int y; 55 56 // CHECK-STATIC-DAG: @b = global i32 2, 57 CONSTINIT int b = __builtin_is_constant_evaluated() ? 2 : y; // static initialization to 2 58 59 // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.1() 60 // CHECK-DYN: %0 = load i32, i32* @y, align 4 61 // CHECK-DYN: %1 = load i32, i32* @y, align 4 62 // CHECK-DYN-NEXT: %add = add 63 // CHECK-DYN-NEXT: store i32 %add, i32* @c, 64 int c = y + (__builtin_is_constant_evaluated() ? 2 : y); // dynamic initialization to y+y 65 66 // CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.2() 67 // CHECK-DYN: store i32 1, i32* @_ZL1a, align 4 68 // CHECK-DYN-NEXT: ret void 69 const int a = __builtin_is_constant_evaluated() ? y : 1; // dynamic initialization to 1 70 const int *a_sink = &a; 71 72 // CHECK-ARR-LABEL: define void @_Z13test_arr_exprv 73 void test_arr_expr() { 74 // CHECK-ARR: %x1 = alloca [101 x i8], 75 char x1[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 101 : 1]; 76 77 // CHECK-ARR: %x2 = alloca [42 x i8], 78 char x2[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 42 : RANDU()]; 79 80 // CHECK-ARR: call i8* @llvm.stacksave() 81 // CHECK-ARR: %vla = alloca i8, i64 13, 82 char x3[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? RANDU() : 13]; 83 } 84 85 // CHECK-ARR-LABEL: define void @_Z17test_new_arr_exprv 86 void test_new_arr_expr() { 87 // CHECK-ARR: call i8* @_Znam(i64 17) 88 new char[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? 1 : 17]; 89 } 90 91 // CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali( 92 bool test_constant_initialized_local(int k) { 93 // CHECK-FOLD: store i8 1, i8* %n, 94 // CHECK-FOLD: store volatile i8* %n, i8** %p, 95 const bool n = __builtin_is_constant_evaluated() && std::is_constant_evaluated(); 96 const bool *volatile p = &n; 97 return *p; 98 } 99 100 // CHECK-FOLD-LABEL: define void @_Z21test_ir_constant_foldv() 101 void test_ir_constant_fold() { 102 // CHECK-FOLD-NEXT: entry: 103 // CHECK-FOLD-NEXT: call void @OK() 104 // CHECK-FOLD-NEXT: call void @OK() 105 // CHECK-FOLD-NEXT: ret void 106 if (std::is_constant_evaluated()) { 107 BOOM(); 108 } else { 109 OK(); 110 } 111 std::is_constant_evaluated() ? BOOM() : OK(); 112 } 113 114 // CHECK-STATIC-DAG: @ir = constant i32* @i_constant, 115 int i_constant; 116 int i_not_constant; 117 int &ir = __builtin_is_constant_evaluated() ? i_constant : i_not_constant; 118 119 // CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev() 120 void test_ref_initialization_local_scope() { 121 const int i_constant = 42; 122 const int i_non_constant = 101; 123 // CHECK-FOLD: store i32* %i_non_constant, i32** %r, 124 const int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; 125 } 126 127 // CHECK-FOLD-LABEL: @_Z22test_ref_to_static_varv() 128 void test_ref_to_static_var() { 129 static int i_constant = 42; 130 static int i_non_constant = 101; 131 // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r, 132 int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant; 133 }