|
4 | 4 | // RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s
|
5 | 5 | // RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s
|
6 | 6 | // RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s
|
| 7 | +// RUN: FileCheck -check-prefix=CHECK-DTOR -input-file=%t.ll %s |
7 | 8 |
|
8 | 9 | using size_t = decltype(sizeof(int));
|
9 | 10 |
|
@@ -131,3 +132,94 @@ void test_ref_to_static_var() {
|
131 | 132 | // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, i32** %r,
|
132 | 133 | int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant;
|
133 | 134 | }
|
| 135 | + |
| 136 | +int not_constexpr; |
| 137 | + |
| 138 | +// __builtin_is_constant_evaluated() should never evaluate to true during |
| 139 | +// destruction if it would not have done so during construction. |
| 140 | +// |
| 141 | +// FIXME: The standard doesn't say that it should ever return true when |
| 142 | +// evaluating a destructor call, even for a constexpr variable. That seems |
| 143 | +// obviously wrong. |
| 144 | +struct DestructorBCE { |
| 145 | + int n; |
| 146 | + constexpr DestructorBCE(int n) : n(n) {} |
| 147 | + constexpr ~DestructorBCE() { |
| 148 | + if (!__builtin_is_constant_evaluated()) |
| 149 | + not_constexpr = 1; |
| 150 | + } |
| 151 | +}; |
| 152 | + |
| 153 | +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_1 |
| 154 | +DestructorBCE global_dtor_bce_1(101); |
| 155 | + |
| 156 | +// CHECK-DTOR: load i32, i32* @not_constexpr |
| 157 | +// CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} @global_dtor_bce_2, i32 |
| 158 | +// CHECK-DTOR: atexit{{.*}} @_ZN13DestructorBCED{{.*}} @global_dtor_bce_2 |
| 159 | +// CHECK-DTOR: } |
| 160 | +DestructorBCE global_dtor_bce_2(not_constexpr); |
| 161 | + |
| 162 | +// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_3 |
| 163 | +constexpr DestructorBCE global_dtor_bce_3(103); |
| 164 | + |
| 165 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_1v( |
| 166 | +void test_dtor_bce_1() { |
| 167 | + // Variable is neither constant initialized (because it has automatic storage |
| 168 | + // duration) nor usable in constant expressions, so BCE should not return |
| 169 | + // true during destruction. It would be OK if we replaced the constructor |
| 170 | + // call with a direct store, but we should emit the destructor call. |
| 171 | + |
| 172 | + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}}, i32 201) |
| 173 | + DestructorBCE local(201); |
| 174 | + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED |
| 175 | + // CHECK-DTOR: } |
| 176 | +} |
| 177 | + |
| 178 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_2v( |
| 179 | +void test_dtor_bce_2() { |
| 180 | + // Non-constant init => BCE is false in destructor. |
| 181 | + |
| 182 | + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} |
| 183 | + DestructorBCE local(not_constexpr); |
| 184 | + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED |
| 185 | + // CHECK-DTOR: } |
| 186 | +} |
| 187 | + |
| 188 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_3v( |
| 189 | +void test_dtor_bce_3() { |
| 190 | + // Should never call dtor for a constexpr variable. |
| 191 | + |
| 192 | + // CHECK-DTOR-NOT: call {{.*}} @_ZN13DestructorBCEC1Ei( |
| 193 | + constexpr DestructorBCE local(203); |
| 194 | + // CHECK-DTOR-NOT: @_ZN13DestructorBCED |
| 195 | + // CHECK-DTOR: } |
| 196 | +} |
| 197 | + |
| 198 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_1v( |
| 199 | +void test_dtor_bce_static_1() { |
| 200 | + // Variable is constant initialized, so BCE returns true during constant |
| 201 | + // destruction. |
| 202 | + |
| 203 | + // CHECK: store i32 301 |
| 204 | + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} |
| 205 | + static DestructorBCE local(301); |
| 206 | + // CHECK-DTOR-NOT: @_ZN13DestructorBCED |
| 207 | + // CHECK-DTOR: } |
| 208 | +} |
| 209 | + |
| 210 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_2v( |
| 211 | +void test_dtor_bce_static_2() { |
| 212 | + // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} |
| 213 | + static DestructorBCE local(not_constexpr); |
| 214 | + // CHECK-DTOR: call {{.*}}atexit{{.*}} @_ZN13DestructorBCED |
| 215 | + // CHECK-DTOR: } |
| 216 | +} |
| 217 | + |
| 218 | +// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_3v( |
| 219 | +void test_dtor_bce_static_3() { |
| 220 | + // CHECK: store i32 303 |
| 221 | + // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}} |
| 222 | + static constexpr DestructorBCE local(303); |
| 223 | + // CHECK-DTOR-NOT: @_ZN13DestructorBCED |
| 224 | + // CHECK-DTOR: } |
| 225 | +} |
0 commit comments