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() 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 // 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() 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 // 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 // 55 int test_retI() { 56 return retI(); 57 } 58 59 // EVAL-NOT: @_Z4retIv() 60 // EXPR: @_Z4retIv() 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 // 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 // 78 const int *test_retPIPtr() { 79 return retIPtr(); 80 } 81 82 // EVAL-NOT: @_Z4retIv() 83 // EXPR: @_Z4retIv() 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 // 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 // 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() 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 // 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() 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 // 155 long test_retRefAgg() { 156 long b = retAgg().b; 157 return b; 158 } 159 160 // EVAL-NOT: @_Z8is_constv() 161 // EXPR: @_Z8is_constv() 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 // 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 { 186 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 // 208 long test_AggCtor() { 209 const int i = 2; 210 AggCtor C(i); 211 return C.a + C.b; 212 } 213