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