[RISCV] Add shrinkwrap test cases showing gaps in current impl
[llvm-project.git] / clang / test / CodeGenCXX / cxx2a-consteval.cpp
blobbfeabc946da413d8052b8c4bd8d302e27a3b594f
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
5 //
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()
23 // EXPR: @_Z4ret7v()
24 consteval int ret7() {
25 return 7;
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]]
35 int test_ret7() {
36 int i = ret7();
37 return i;
40 int global_i = ret7();
42 constexpr int i_const = 5;
44 // EVAL-NOT: @_Z4retIv()
45 // EXPR: @_Z4retIv()
46 consteval const int &retI() {
47 return i_const;
50 // EVAL-FN-LABEL: @_Z12test_retRefIv(
51 // EVAL-FN-NEXT: entry:
52 // EVAL-FN-NEXT: ret ptr @_ZL7i_const
54 const int &test_retRefI() {
55 return retI();
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]]
63 int test_retI() {
64 return retI();
67 // EVAL-NOT: @_Z4retIv()
68 // EXPR: @_Z4retIv()
69 consteval const int *retIPtr() {
70 return &i_const;
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]]
78 int test_retIPtr() {
79 return *retIPtr();
82 // EVAL-FN-LABEL: @_Z13test_retPIPtrv(
83 // EVAL-FN-NEXT: entry:
84 // EVAL-FN-NEXT: ret ptr @_ZL7i_const
86 const int *test_retPIPtr() {
87 return retIPtr();
90 // EVAL-NOT: @_Z4retIv()
91 // EXPR: @_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() {
110 return retIRRef();
113 struct Agg {
114 int a;
115 long b;
118 // EVAL-NOT: @_Z6retAggv()
119 // EXPR: @_Z6retAggv()
120 consteval Agg retAgg() {
121 return {13, 17};
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]]
136 long test_retAgg() {
137 long b = retAgg().b;
138 return b;
141 // EVAL-STATIC: @A ={{.*}} global %struct.Agg { i32 13, i64 17 }, align 8
142 Agg A = retAgg();
144 // EVAL-NOT: @_Z9retRefAggv()
145 // EXPR: @_Z9retRefAggv()
146 consteval const Agg &retRefAgg() {
147 const Agg &tmp = A;
148 return A;
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() {
164 long b = retAgg().b;
165 return b;
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;
188 return b;
191 // EVAL-NOT: @_ZN7AggCtorC
192 // EXPR: @_ZN7AggCtorC
193 struct AggCtor {
194 consteval AggCtor(int a = 3, long b = 5) : a(a * a), b(a * b) {}
195 int a;
196 long 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() {
217 const int i = 2;
218 AggCtor C(i);
219 return C.a + C.b;
222 struct UserConv {
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() {
231 return 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
264 // EVAL-FN-NOT: call
265 void_test();
266 // EVAL-FN: {{^}}}
270 namespace GH82154 {
271 struct S1 { consteval S1(int) {} };
272 struct S3 { constexpr S3(int) {} };
274 void f() {
275 struct S2 {
276 S1 s = 0;
277 S3 s2 = 0;
279 S2 s;
280 // EVAL-FN-LABEL: define {{.*}} void @_ZZN7GH821541fEvEN2S2C2Ev
281 // EVAL-FN-NOT: call void @_ZN7GH821542S1C2Ei
282 // EVAL-FN: call void @_ZN7GH821542S3C2Ei
286 namespace GH93040 {
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);
294 void f() {
295 Test test;
297 // Make sure we don't overwrite the initialization of c.
299 // EVAL-FN-LABEL: define {{.*}} void @_ZN7GH930404TestC2Ev
300 // EVAL-FN: entry:
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