1 // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll
2 // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
3 // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
4 // RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s
6 // RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll
7 // RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s
9 // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
10 // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
11 // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
12 // RUN: FileCheck -check-prefix=EVAL-FN -input-file=%t.ll %s
14 // RUN: %clang_cc1 -emit-llvm %s -Dconsteval="" -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll -fexperimental-new-constant-interpreter
15 // RUN: FileCheck -check-prefix=EXPR -input-file=%t.ll %s
17 // there is two version of symbol checks to ensure
18 // that the symbol we are looking for are correct
19 // EVAL-NOT: @__cxx_global_var_init()
20 // EXPR: @__cxx_global_var_init()
22 // EVAL-NOT: @_Z4ret7v()
24 consteval
int ret7() {
28 // EVAL-FN-LABEL: @_Z9test_ret7v(
29 // EVAL-FN-NEXT: entry:
30 // EVAL-FN-NEXT: [[I:%.*]] = alloca i32, align 4
31 // EVAL-FN-NEXT: store i32 7, ptr [[I]], align 4
32 // EVAL-FN-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
33 // EVAL-FN-NEXT: ret i32 [[TMP0]]
40 int global_i
= ret7();
42 constexpr int i_const
= 5;
44 // EVAL-NOT: @_Z4retIv()
46 consteval
const int &retI() {
50 // EVAL-FN-LABEL: @_Z12test_retRefIv(
51 // EVAL-FN-NEXT: entry:
52 // EVAL-FN-NEXT: ret ptr @_ZL7i_const
54 const int &test_retRefI() {
58 // EVAL-FN-LABEL: @_Z9test_retIv(
59 // EVAL-FN-NEXT: entry:
60 // EVAL-FN-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZL7i_const, align 4
61 // EVAL-FN-NEXT: ret i32 [[TMP0]]
67 // EVAL-NOT: @_Z4retIv()
69 consteval
const int *retIPtr() {
73 // EVAL-FN-LABEL: @_Z12test_retIPtrv(
74 // EVAL-FN-NEXT: entry:
75 // EVAL-FN-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZL7i_const, align 4
76 // EVAL-FN-NEXT: ret i32 [[TMP0]]
82 // EVAL-FN-LABEL: @_Z13test_retPIPtrv(
83 // EVAL-FN-NEXT: entry:
84 // EVAL-FN-NEXT: ret ptr @_ZL7i_const
86 const int *test_retPIPtr() {
90 // EVAL-NOT: @_Z4retIv()
92 consteval
const int &&retIRRef() {
93 return static_cast<const int &&>(i_const
);
96 // EVAL-FN-LABEL: @_Z13test_retIRRefv(
97 // EVAL-FN-NEXT: entry:
98 // EVAL-FN-NEXT: ret ptr @_ZL7i_const
100 const int &&test_retIRRef() {
101 return static_cast<const int &&>(retIRRef());
104 // EVAL-FN-LABEL: @_Z14test_retIRRefIv(
105 // EVAL-FN-NEXT: entry:
106 // EVAL-FN-NEXT: [[TMP0:%.*]] = load i32, ptr @_ZL7i_const, align 4
107 // EVAL-FN-NEXT: ret i32 [[TMP0]]
109 int test_retIRRefI() {
118 // EVAL-NOT: @_Z6retAggv()
119 // EXPR: @_Z6retAggv()
120 consteval Agg
retAgg() {
124 // EVAL-FN-LABEL: @_Z11test_retAggv(
125 // EVAL-FN-NEXT: entry:
126 // EVAL-FN-NEXT: [[B:%.*]] = alloca i64, align 8
127 // EVAL-FN-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
128 // EVAL-FN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 0
129 // EVAL-FN-NEXT: store i32 13, ptr [[TMP0]], align 8
130 // EVAL-FN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 1
131 // EVAL-FN-NEXT: store i64 17, ptr [[TMP1]], align 8
132 // EVAL-FN-NEXT: store i64 17, ptr [[B]], align 8
133 // EVAL-FN-NEXT: [[TMP2:%.*]] = load i64, ptr [[B]], align 8
134 // EVAL-FN-NEXT: ret i64 [[TMP2]]
141 // EVAL-STATIC: @A ={{.*}} global %struct.Agg { i32 13, i64 17 }, align 8
144 // EVAL-NOT: @_Z9retRefAggv()
145 // EXPR: @_Z9retRefAggv()
146 consteval
const Agg
&retRefAgg() {
151 // EVAL-FN-LABEL: @_Z14test_retRefAggv(
152 // EVAL-FN-NEXT: entry:
153 // EVAL-FN-NEXT: [[B:%.*]] = alloca i64, align 8
154 // EVAL-FN-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
155 // EVAL-FN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 0
156 // EVAL-FN-NEXT: store i32 13, ptr [[TMP0]], align 8
157 // EVAL-FN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 1
158 // EVAL-FN-NEXT: store i64 17, ptr [[TMP1]], align 8
159 // EVAL-FN-NEXT: store i64 17, ptr [[B]], align 8
160 // EVAL-FN-NEXT: [[TMP2:%.*]] = load i64, ptr [[B]], align 8
161 // EVAL-FN-NEXT: ret i64 [[TMP2]]
163 long test_retRefAgg() {
168 // EVAL-NOT: @_Z8is_constv()
169 // EXPR: @_Z8is_constv()
170 consteval Agg
is_const() {
171 return {5, 19 * __builtin_is_constant_evaluated()};
174 // EVAL-FN-LABEL: @_Z13test_is_constv(
175 // EVAL-FN-NEXT: entry:
176 // EVAL-FN-NEXT: [[B:%.*]] = alloca i64, align 8
177 // EVAL-FN-NEXT: [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
178 // EVAL-FN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 0
179 // EVAL-FN-NEXT: store i32 5, ptr [[TMP0]], align 8
180 // EVAL-FN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_AGG]], ptr [[REF_TMP]], i32 0, i32 1
181 // EVAL-FN-NEXT: store i64 19, ptr [[TMP1]], align 8
182 // EVAL-FN-NEXT: store i64 19, ptr [[B]], align 8
183 // EVAL-FN-NEXT: [[TMP2:%.*]] = load i64, ptr [[B]], align 8
184 // EVAL-FN-NEXT: ret i64 [[TMP2]]
186 long test_is_const() {
187 long b
= is_const().b
;
191 // EVAL-NOT: @_ZN7AggCtorC
192 // EXPR: @_ZN7AggCtorC
194 consteval
AggCtor(int a
= 3, long b
= 5) : a(a
* a
), b(a
* b
) {}
199 // EVAL-FN-LABEL: @_Z12test_AggCtorv(
200 // EVAL-FN-NEXT: entry:
201 // EVAL-FN-NEXT: [[I:%.*]] = alloca i32, align 4
202 // EVAL-FN-NEXT: [[C:%.*]] = alloca [[STRUCT_AGGCTOR:%.*]], align 8
203 // EVAL-FN-NEXT: store i32 2, ptr [[I]], align 4
204 // EVAL-FN-NEXT: [[TMP0:%.*]] = getelementptr inbounds nuw [[STRUCT_AGGCTOR]], ptr [[C]], i32 0, i32 0
205 // EVAL-FN-NEXT: store i32 4, ptr [[TMP0]], align 8
206 // EVAL-FN-NEXT: [[TMP1:%.*]] = getelementptr inbounds nuw [[STRUCT_AGGCTOR]], ptr [[C]], i32 0, i32 1
207 // EVAL-FN-NEXT: store i64 10, ptr [[TMP1]], align 8
208 // EVAL-FN-NEXT: [[A:%.*]] = getelementptr inbounds nuw [[STRUCT_AGGCTOR]], ptr [[C]], i32 0, i32 0
209 // EVAL-FN-NEXT: [[TMP2:%.*]] = load i32, ptr [[A]], align 8
210 // EVAL-FN-NEXT: [[CONV:%.*]] = sext i32 [[TMP2]] to i64
211 // EVAL-FN-NEXT: [[B:%.*]] = getelementptr inbounds nuw [[STRUCT_AGGCTOR]], ptr [[C]], i32 0, i32 1
212 // EVAL-FN-NEXT: [[TMP3:%.*]] = load i64, ptr [[B]], align 8
213 // EVAL-FN-NEXT: [[ADD:%.*]] = add nsw i64 [[CONV]], [[TMP3]]
214 // EVAL-FN-NEXT: ret i64 [[ADD]]
216 long test_AggCtor() {
223 consteval
operator int() const noexcept
{ return 42; }
226 // EVAL-FN-LABEL: @_Z13test_UserConvv(
227 // EVAL-FN-NEXT: entry:
228 // EVAL-FN-NEXT: ret i32 42
230 int test_UserConv() {
234 // EVAL-FN-LABEL: @_Z28test_UserConvOverload_helperi(
235 // EVAL-FN-NEXT: entry:
236 // EVAL-FN-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
237 // EVAL-FN-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4
238 // EVAL-FN-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4
239 // EVAL-FN-NEXT: ret i32 [[TMP0]]
241 int test_UserConvOverload_helper(int a
) { return a
; }
243 // EVAL-FN-LABEL: @_Z21test_UserConvOverloadv(
244 // EVAL-FN-NEXT: entry:
245 // EVAL-FN-NEXT: [[CALL:%.*]] = call noundef i32 @_Z28test_UserConvOverload_helperi(i32 noundef 42)
246 // EVAL-FN-NEXT: ret i32 [[CALL]]
248 int test_UserConvOverload() {
249 return test_UserConvOverload_helper(UserConv());
252 consteval
int test_UserConvOverload_helper_ceval(int a
) { return a
; }
254 // EVAL-FN-LABEL: @_Z27test_UserConvOverload_cevalv(
255 // EVAL-FN-NEXT: entry:
256 // EVAL-FN-NEXT: ret i32 42
258 int test_UserConvOverload_ceval() {
259 return test_UserConvOverload_helper_ceval(UserConv());
262 consteval
void void_test() {}
263 void void_call() { // EVAL-FN-LABEL: define {{.*}} @_Z9void_call
271 struct S1
{ consteval
S1(int) {} };
272 struct S3
{ constexpr S3(int) {} };
280 // EVAL-FN-LABEL: define {{.*}} void @_ZZN7GH821541fEvEN2S2C2Ev
281 // EVAL-FN-NOT: call void @_ZN7GH821542S1C2Ei
282 // EVAL-FN: call void @_ZN7GH821542S3C2Ei
287 struct C
{ char c
= 1; };
288 struct Empty
{ consteval
Empty() {} };
289 struct Empty2
{ consteval
Empty2() {} };
290 struct Test
: C
, Empty
{
291 [[no_unique_address
]] Empty2 e
;
293 static_assert(sizeof(Test
) == 1);
297 // Make sure we don't overwrite the initialization of c.
299 // EVAL-FN-LABEL: define {{.*}} void @_ZN7GH930404TestC2Ev
301 // EVAL-FN-NEXT: [[THIS_ADDR:%.*]] = alloca ptr, align 8
302 // EVAL-FN-NEXT: store ptr {{.*}}, ptr [[THIS_ADDR]], align 8
303 // EVAL-FN-NEXT: [[THIS:%.*]] = load ptr, ptr [[THIS_ADDR]], align 8
304 // EVAL-FN-NEXT: call void @_ZN7GH930401CC2Ev(ptr noundef nonnull align 1 dereferenceable(1) [[THIS]])
305 // EVAL-FN-NEXT: ret void