brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.1 KiB · d8cbf2f Raw
226 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s -std=c++2a -o %t.ll2// RUN: FileCheck -check-prefix=CHECK-FN-CG -input-file=%t.ll %s3// RUN: FileCheck -check-prefix=CHECK-STATIC -input-file=%t.ll %s4// RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s5// RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s6// RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s7// RUN: FileCheck -check-prefix=CHECK-DTOR -input-file=%t.ll %s8 9using size_t = decltype(sizeof(int));10 11#define CONSTINIT __attribute__((require_constant_initialization))12 13extern "C" [[noreturn]] void BOOM();14extern "C" void OK();15extern "C" size_t RANDU();16 17namespace std {18inline constexpr bool is_constant_evaluated() noexcept {19  return __builtin_is_constant_evaluated();20}21} // namespace std22 23// CHECK-FN-CG-LABEL: define{{.*}} zeroext i1 @_Z3foov()24// CHECK-FN-CG: ret i1 false25bool foo() {26  return __builtin_is_constant_evaluated();27}28 29// CHECK-FN-CG-LABEL: define linkonce_odr noundef i32 @_Z1fv()30constexpr int f() {31  // CHECK-FN-CG: store i32 13, ptr %n, align 432  // CHECK-FN-CG: store i32 17, ptr %m, align 433  // CHECK-FN-CG:  %0 = load i32, ptr %m, align 434  // CHECK-FN-CG: %add = add nsw i32 %0, 1335  // CHECK-FN-CG: ret i32 %add36  const int n = __builtin_is_constant_evaluated() && std::is_constant_evaluated() ? 13 : 17; // n == 1337  int m = __builtin_is_constant_evaluated() ? 13 : 17;       // m might be 13 or 17 (see below)38  char arr[n] = {};                                          // char[13]39  return m + int(sizeof(arr));40}41 42// CHECK-STATIC-DAG: @p ={{.*}} global i32 26,43CONSTINIT int p = f(); // f().m == 13; initialized to 2644// CHECK-STATIC-DAG: @p2 ={{.*}} global i32 26,45int p2 = f(); // same result without CONSTINIT46 47// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init()48// CHECK-DYN: %0 = load i32, ptr @p, align 449// CHECK-DYN-NEXT: %call = call noundef i32 @_Z1fv()50// CHECK-DYN-NEXT: %add = add nsw i32 %0, %call51// CHECK-DYN-NEXT: store i32 %add, ptr @q, align 452// CHECK-DYN-NEXT: ret void53int q = p + f(); // m == 17 for this call; initialized to 5654 55int y;56 57// CHECK-STATIC-DAG: @b ={{.*}} global i32 2,58CONSTINIT int b = __builtin_is_constant_evaluated() ? 2 : y; // static initialization to 259 60// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.1()61// CHECK-DYN: %0 = load i32, ptr @y, align 462// CHECK-DYN: %1 = load i32, ptr @y, align 463// CHECK-DYN-NEXT: %add = add64// CHECK-DYN-NEXT: store i32 %add, ptr @c,65int c = y + (__builtin_is_constant_evaluated() ? 2 : y); // dynamic initialization to y+y66 67// This is dynamic initialization that we can convert to static initialization68// during lowering. When doing so, the dynamic initializer value is preserved.69// CHECK-STATIC-DAG: @_ZL1a = internal constant i32 170const int a = __builtin_is_constant_evaluated() ? y : 1; // dynamic initialization to 171const int *a_sink = &a;72 73// CHECK-ARR-LABEL: define{{.*}} void @_Z13test_arr_exprv74void test_arr_expr() {75  // CHECK-ARR: %x1 = alloca [101 x i8],76  char x1[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 101 : 1];77 78  // CHECK-ARR: %x2 = alloca [42 x i8],79  char x2[std::is_constant_evaluated() && __builtin_is_constant_evaluated() ? 42 : RANDU()];80 81  // CHECK-ARR: call ptr @llvm.stacksave.p0()82  // CHECK-ARR: %vla = alloca i8, i64 13,83  char x3[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? RANDU() : 13];84}85 86// CHECK-ARR-LABEL: define{{.*}} void @_Z17test_new_arr_exprv87void test_new_arr_expr() {88  // CHECK-ARR: call noalias noundef nonnull ptr @_Znam(i64 noundef 17)89  new char[std::is_constant_evaluated() || __builtin_is_constant_evaluated() ? 1 : 17];90}91 92// CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali(93bool test_constant_initialized_local(int k) {94  // CHECK-FOLD: store i8 1, ptr %n,95  // CHECK-FOLD: store volatile ptr %n, ptr %p,96  const bool n = __builtin_is_constant_evaluated() && std::is_constant_evaluated();97  const bool *volatile p = &n;98  return *p;99}100 101// CHECK-FOLD-LABEL: define{{.*}} void @_Z21test_ir_constant_foldv()102void test_ir_constant_fold() {103  // CHECK-FOLD-NEXT: entry:104  // CHECK-FOLD-NEXT: call void @OK()105  // CHECK-FOLD-NEXT: call void @OK()106  // CHECK-FOLD-NEXT: ret void107  if (std::is_constant_evaluated()) {108    BOOM();109  } else {110    OK();111  }112  std::is_constant_evaluated() ? BOOM() : OK();113}114 115// CHECK-STATIC-DAG: @ir ={{.*}} constant ptr @i_constant,116int i_constant;117int i_not_constant;118int &ir = __builtin_is_constant_evaluated() ? i_constant : i_not_constant;119 120// CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev()121void test_ref_initialization_local_scope() {122  const int i_constant = 42;123  const int i_non_constant = 101;124  // CHECK-FOLD: store ptr %i_non_constant, ptr %r,125  const int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant;126}127 128// CHECK-FOLD-LABEL: @_Z22test_ref_to_static_varv()129void test_ref_to_static_var() {130  static int i_constant = 42;131  static int i_non_constant = 101;132  // CHECK-FOLD: store ptr @_ZZ22test_ref_to_static_varvE10i_constant, ptr %r,133  int &r = __builtin_is_constant_evaluated() ? i_constant : i_non_constant;134}135 136int not_constexpr;137 138// __builtin_is_constant_evaluated() should never evaluate to true during139// destruction if it would not have done so during construction.140//141// FIXME: The standard doesn't say that it should ever return true when142// evaluating a destructor call, even for a constexpr variable. That seems143// obviously wrong.144struct 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_1154DestructorBCE global_dtor_bce_1(101);155 156// CHECK-DTOR: load i32, ptr @not_constexpr157// CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} @global_dtor_bce_2, i32158// CHECK-DTOR: atexit{{.*}} @_ZN13DestructorBCED{{.*}} @global_dtor_bce_2159// CHECK-DTOR: }160DestructorBCE global_dtor_bce_2(not_constexpr);161 162// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_3163constexpr DestructorBCE global_dtor_bce_3(103);164 165// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_1v(166void test_dtor_bce_1() {167  // Variable is neither constant initialized (because it has automatic storage168  // duration) nor usable in constant expressions, so BCE should not return169  // true during destruction. It would be OK if we replaced the constructor170  // call with a direct store, but we should emit the destructor call.171 172  // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}}, i32 noundef 201)173  DestructorBCE local(201);174  // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCED175  // CHECK-DTOR: }176}177 178// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_2v(179void 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 {{.*}} @_ZN13DestructorBCED185  // CHECK-DTOR: }186}187 188// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_3v(189void 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: @_ZN13DestructorBCED195  // CHECK-DTOR: }196}197 198// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_1v(199void test_dtor_bce_static_1() {200  // Variable is constant initialized, so BCE returns true during constant201  // destruction.202 203  // CHECK: store i32 301204  // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}}205  static DestructorBCE local(301);206  // CHECK-DTOR-NOT: @_ZN13DestructorBCED207  // CHECK-DTOR: }208}209 210// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_2v(211void test_dtor_bce_static_2() {212  // CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}}213  static DestructorBCE local(not_constexpr);214  // CHECK-DTOR: call {{.*}}atexit{{.*}} @_ZN13DestructorBCED215  // CHECK-DTOR: }216}217 218// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_3v(219void test_dtor_bce_static_3() {220  // CHECK: store i32 303221  // CHECK-DTOR-NOT: @_ZN13DestructorBCEC1Ei({{.*}}222  static constexpr DestructorBCE local(303);223  // CHECK-DTOR-NOT: @_ZN13DestructorBCED224  // CHECK-DTOR: }225}226