1 // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2 // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o %t.ll
3 // RUN: FileCheck -check-prefix=EVAL -input-file=%t.ll %s
4 // RUN: FileCheck -check-prefix=EVAL-STATIC -input-file=%t.ll %s
5 // RUN: %clang_cc1 -emit-llvm %s -std=c++2a -triple x86_64-unknown-linux-gnu -o - | FileCheck -check-prefix=EVAL-FN %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
8 
9 // there is two version of symbol checks to ensure
10 // that the symbol we are looking for are correct
11 // EVAL-NOT: @__cxx_global_var_init()
12 // EXPR: @__cxx_global_var_init()
13 
14 // EVAL-NOT: @_Z4ret7v()
15 // EXPR: @_Z4ret7v()
ret7()16 consteval int ret7() {
17   return 7;
18 }
19 
20 // EVAL-FN-LABEL: @_Z9test_ret7v(
21 // EVAL-FN-NEXT:  entry:
22 // EVAL-FN-NEXT:    [[I:%.*]] = alloca i32, align 4
23 // EVAL-FN-NEXT:    store i32 7, i32* [[I]], align 4
24 // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* [[I]], align 4
25 // EVAL-FN-NEXT:    ret i32 [[TMP0]]
26 //
test_ret7()27 int test_ret7() {
28   int i = ret7();
29   return i;
30 }
31 
32 int global_i = ret7();
33 
34 constexpr int i_const = 5;
35 
36 // EVAL-NOT: @_Z4retIv()
37 // EXPR: @_Z4retIv()
retI()38 consteval const int &retI() {
39   return i_const;
40 }
41 
42 // EVAL-FN-LABEL: @_Z12test_retRefIv(
43 // EVAL-FN-NEXT:  entry:
44 // EVAL-FN-NEXT:    ret i32* @_ZL7i_const
45 //
test_retRefI()46 const int &test_retRefI() {
47   return retI();
48 }
49 
50 // EVAL-FN-LABEL: @_Z9test_retIv(
51 // EVAL-FN-NEXT:  entry:
52 // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
53 // EVAL-FN-NEXT:    ret i32 [[TMP0]]
54 //
test_retI()55 int test_retI() {
56   return retI();
57 }
58 
59 // EVAL-NOT: @_Z4retIv()
60 // EXPR: @_Z4retIv()
retIPtr()61 consteval const int *retIPtr() {
62   return &i_const;
63 }
64 
65 // EVAL-FN-LABEL: @_Z12test_retIPtrv(
66 // EVAL-FN-NEXT:  entry:
67 // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
68 // EVAL-FN-NEXT:    ret i32 [[TMP0]]
69 //
test_retIPtr()70 int test_retIPtr() {
71   return *retIPtr();
72 }
73 
74 // EVAL-FN-LABEL: @_Z13test_retPIPtrv(
75 // EVAL-FN-NEXT:  entry:
76 // EVAL-FN-NEXT:    ret i32* @_ZL7i_const
77 //
test_retPIPtr()78 const int *test_retPIPtr() {
79   return retIPtr();
80 }
81 
82 // EVAL-NOT: @_Z4retIv()
83 // EXPR: @_Z4retIv()
retIRRef()84 consteval const int &&retIRRef() {
85   return static_cast<const int &&>(i_const);
86 }
87 
88 // EVAL-FN-LABEL: @_Z13test_retIRRefv(
89 // EVAL-FN-NEXT:  entry:
90 // EVAL-FN-NEXT:    ret i32* @_ZL7i_const
91 //
test_retIRRef()92 const int &&test_retIRRef() {
93   return static_cast<const int &&>(retIRRef());
94 }
95 
96 // EVAL-FN-LABEL: @_Z14test_retIRRefIv(
97 // EVAL-FN-NEXT:  entry:
98 // EVAL-FN-NEXT:    [[TMP0:%.*]] = load i32, i32* @_ZL7i_const, align 4
99 // EVAL-FN-NEXT:    ret i32 [[TMP0]]
100 //
test_retIRRefI()101 int test_retIRRefI() {
102   return retIRRef();
103 }
104 
105 struct Agg {
106   int a;
107   long b;
108 };
109 
110 // EVAL-NOT: @_Z6retAggv()
111 // EXPR: @_Z6retAggv()
retAgg()112 consteval Agg retAgg() {
113   return {13, 17};
114 }
115 
116 // EVAL-FN-LABEL: @_Z11test_retAggv(
117 // EVAL-FN-NEXT:  entry:
118 // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
119 // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
120 // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
121 // EVAL-FN-NEXT:    store i32 13, i32* [[TMP0]], align 8
122 // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
123 // EVAL-FN-NEXT:    store i64 17, i64* [[TMP1]], align 8
124 // EVAL-FN-NEXT:    store i64 17, i64* [[B]], align 8
125 // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
126 // EVAL-FN-NEXT:    ret i64 [[TMP2]]
127 //
test_retAgg()128 long test_retAgg() {
129   long b = retAgg().b;
130   return b;
131 }
132 
133 // EVAL-STATIC: @A ={{.*}} global %struct.Agg { i32 13, i64 17 }, align 8
134 Agg A = retAgg();
135 
136 // EVAL-NOT: @_Z9retRefAggv()
137 // EXPR: @_Z9retRefAggv()
retRefAgg()138 consteval const Agg &retRefAgg() {
139   const Agg &tmp = A;
140   return A;
141 }
142 
143 // EVAL-FN-LABEL: @_Z14test_retRefAggv(
144 // EVAL-FN-NEXT:  entry:
145 // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
146 // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
147 // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
148 // EVAL-FN-NEXT:    store i32 13, i32* [[TMP0]], align 8
149 // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
150 // EVAL-FN-NEXT:    store i64 17, i64* [[TMP1]], align 8
151 // EVAL-FN-NEXT:    store i64 17, i64* [[B]], align 8
152 // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
153 // EVAL-FN-NEXT:    ret i64 [[TMP2]]
154 //
test_retRefAgg()155 long test_retRefAgg() {
156   long b = retAgg().b;
157   return b;
158 }
159 
160 // EVAL-NOT: @_Z8is_constv()
161 // EXPR: @_Z8is_constv()
is_const()162 consteval Agg is_const() {
163   return {5, 19 * __builtin_is_constant_evaluated()};
164 }
165 
166 // EVAL-FN-LABEL: @_Z13test_is_constv(
167 // EVAL-FN-NEXT:  entry:
168 // EVAL-FN-NEXT:    [[B:%.*]] = alloca i64, align 8
169 // EVAL-FN-NEXT:    [[REF_TMP:%.*]] = alloca [[STRUCT_AGG:%.*]], align 8
170 // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 0
171 // EVAL-FN-NEXT:    store i32 5, i32* [[TMP0]], align 8
172 // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGG]], %struct.Agg* [[REF_TMP]], i32 0, i32 1
173 // EVAL-FN-NEXT:    store i64 19, i64* [[TMP1]], align 8
174 // EVAL-FN-NEXT:    store i64 19, i64* [[B]], align 8
175 // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i64, i64* [[B]], align 8
176 // EVAL-FN-NEXT:    ret i64 [[TMP2]]
177 //
test_is_const()178 long test_is_const() {
179   long b = is_const().b;
180   return b;
181 }
182 
183 // EVAL-NOT: @_ZN7AggCtorC
184 // EXPR: @_ZN7AggCtorC
185 struct AggCtor {
AggCtorAggCtor186   consteval AggCtor(int a = 3, long b = 5) : a(a * a), b(a * b) {}
187   int a;
188   long b;
189 };
190 
191 // EVAL-FN-LABEL: @_Z12test_AggCtorv(
192 // EVAL-FN-NEXT:  entry:
193 // EVAL-FN-NEXT:    [[I:%.*]] = alloca i32, align 4
194 // EVAL-FN-NEXT:    [[C:%.*]] = alloca [[STRUCT_AGGCTOR:%.*]], align 8
195 // EVAL-FN-NEXT:    store i32 2, i32* [[I]], align 4
196 // EVAL-FN-NEXT:    [[TMP0:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 0
197 // EVAL-FN-NEXT:    store i32 4, i32* [[TMP0]], align 8
198 // EVAL-FN-NEXT:    [[TMP1:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 1
199 // EVAL-FN-NEXT:    store i64 10, i64* [[TMP1]], align 8
200 // EVAL-FN-NEXT:    [[A:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 0
201 // EVAL-FN-NEXT:    [[TMP2:%.*]] = load i32, i32* [[A]], align 8
202 // EVAL-FN-NEXT:    [[CONV:%.*]] = sext i32 [[TMP2]] to i64
203 // EVAL-FN-NEXT:    [[B:%.*]] = getelementptr inbounds [[STRUCT_AGGCTOR]], %struct.AggCtor* [[C]], i32 0, i32 1
204 // EVAL-FN-NEXT:    [[TMP3:%.*]] = load i64, i64* [[B]], align 8
205 // EVAL-FN-NEXT:    [[ADD:%.*]] = add nsw i64 [[CONV]], [[TMP3]]
206 // EVAL-FN-NEXT:    ret i64 [[ADD]]
207 //
test_AggCtor()208 long test_AggCtor() {
209   const int i = 2;
210   AggCtor C(i);
211   return C.a + C.b;
212 }
213 
214 struct UserConv {
operator intUserConv215   consteval operator int() const noexcept { return 42; }
216 };
217 
218 // EVAL-FN-LABEL: @_Z13test_UserConvv(
219 // EVAL-FN-NEXT:  entry:
220 // EVAL-FN-NEXT:    ret i32 42
221 //
test_UserConv()222 int test_UserConv() {
223   return UserConv();
224 }
225 
test_UserConvOverload_helper(int a)226 int test_UserConvOverload_helper(int a) { return a; }
227 
228 // EVAL-FN-LABEL: @_Z21test_UserConvOverloadv(
229 // EVAL-FN-NEXT:  entry:
230 // EVAL-FN-NEXT:    %call = call i32 @_Z28test_UserConvOverload_helperi(i32 42)
231 // EVAL-FN-NEXT:    ret i32 %call
232 //
test_UserConvOverload()233 int test_UserConvOverload() {
234   return test_UserConvOverload_helper(UserConv());
235 }
236 
test_UserConvOverload_helper_ceval(int a)237 consteval int test_UserConvOverload_helper_ceval(int a) { return a; }
238 
239 // EVAL-FN-LABEL: @_Z27test_UserConvOverload_cevalv(
240 // EVAL-FN-NEXT:  entry:
241 // EVAL-FN-NEXT:    ret i32 42
242 //
test_UserConvOverload_ceval()243 int test_UserConvOverload_ceval() {
244   return test_UserConvOverload_helper_ceval(UserConv());
245 }
246