blob: 78dfc695c15e4607b0f2c2b3d2c8ec3009c660c6 [file] [log] [blame]
Eric Fiselieradd16a82019-04-24 02:23:30 +00001// 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
8using size_t = decltype(sizeof(int));
9
10#define CONSTINIT __attribute__((require_constant_initialization))
11
12extern "C" [[noreturn]] void BOOM();
13extern "C" void OK();
14extern "C" size_t RANDU();
15
16namespace std {
17inline constexpr bool is_constant_evaluated() noexcept {
18 return __builtin_is_constant_evaluated();
19}
20} // namespace std
21
Fangrui Songdbc96b52020-02-03 10:09:39 -080022// CHECK-FN-CG-LABEL: define zeroext i1 @_Z3foov()
Eric Fiselieradd16a82019-04-24 02:23:30 +000023// CHECK-FN-CG: ret i1 false
24bool foo() {
25 return __builtin_is_constant_evaluated();
26}
27
Fangrui Songdbc96b52020-02-03 10:09:39 -080028// CHECK-FN-CG-LABEL: define linkonce_odr i32 @_Z1fv()
Eric Fiselieradd16a82019-04-24 02:23:30 +000029constexpr 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
Fangrui Songdbc96b52020-02-03 10:09:39 -080041// CHECK-STATIC-DAG: @p = global i32 26,
Eric Fiselieradd16a82019-04-24 02:23:30 +000042CONSTINIT int p = f(); // f().m == 13; initialized to 26
Fangrui Songdbc96b52020-02-03 10:09:39 -080043// CHECK-STATIC-DAG: @p2 = global i32 26,
Eric Fiselieradd16a82019-04-24 02:23:30 +000044int 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
52int q = p + f(); // m == 17 for this call; initialized to 56
53
54int y;
55
Fangrui Songdbc96b52020-02-03 10:09:39 -080056// CHECK-STATIC-DAG: @b = global i32 2,
Eric Fiselieradd16a82019-04-24 02:23:30 +000057CONSTINIT 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,
64int c = y + (__builtin_is_constant_evaluated() ? 2 : y); // dynamic initialization to y+y
65
Richard Smith08c8d5b2020-10-19 20:03:18 -070066// This is dynamic initialization that we can convert to static initialization
67// during lowering. When doing so, the dynamic initializer value is preserved.
68// CHECK-STATIC-DAG: @_ZL1a = internal constant i32 1
Eric Fiselieradd16a82019-04-24 02:23:30 +000069const int a = __builtin_is_constant_evaluated() ? y : 1; // dynamic initialization to 1
70const int *a_sink = &a;
71
Fangrui Songdbc96b52020-02-03 10:09:39 -080072// CHECK-ARR-LABEL: define void @_Z13test_arr_exprv
Eric Fiselieradd16a82019-04-24 02:23:30 +000073void 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
Fangrui Songdbc96b52020-02-03 10:09:39 -080085// CHECK-ARR-LABEL: define void @_Z17test_new_arr_exprv
Eric Fiselieradd16a82019-04-24 02:23:30 +000086void test_new_arr_expr() {
Roman Lebedev3dd5a292020-02-26 01:37:17 +030087 // CHECK-ARR: call noalias nonnull i8* @_Znam(i64 17)
Eric Fiselieradd16a82019-04-24 02:23:30 +000088 new char[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? 1 : 17];
89}
90
91// CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali(
92bool 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
Fangrui Songdbc96b52020-02-03 10:09:39 -0800100// CHECK-FOLD-LABEL: define void @_Z21test_ir_constant_foldv()
Eric Fiselieradd16a82019-04-24 02:23:30 +0000101void 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
Fangrui Songdbc96b52020-02-03 10:09:39 -0800114// CHECK-STATIC-DAG: @ir = constant i32* @i_constant,
Eric Fiselieradd16a82019-04-24 02:23:30 +0000115int i_constant;
116int i_not_constant;
117int &ir = __builtin_is_constant_evaluated() ? i_constant : i_not_constant;
118
119// CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev()
120void 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()
128void 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;
Roman Lebedev3dd5a292020-02-26 01:37:17 +0300133}