// RUN: %clang_cc1 -no-opaque-pointers -triple x86_64-unknown-unknown -emit-llvm %s -std=c++2a -o %t.ll
// RUN: FileCheck -check-prefix=CHECK-FN-CG -input-file=%t.ll %s
// RUN: FileCheck -check-prefix=CHECK-STATIC -input-file=%t.ll %s
// RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s
// RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s
// RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s
// RUN: FileCheck -check-prefix=CHECK-DTOR -input-file=%t.ll %s
using size_t = decltype;
extern "C" void ;
extern "C" void ;
extern "C" size_t ;
// namespace std
// CHECK-FN-CG-LABEL: define{{.*}} zeroext i1 @_Z3foov()
// CHECK-FN-CG: ret i1 false
bool
// CHECK-FN-CG-LABEL: define linkonce_odr noundef i32 @_Z1fv()
constexpr int
// CHECK-STATIC-DAG: @p ={{.*}} global i32 26,
CONSTINIT int p = ; // f().m == 13; initialized to 26
// CHECK-STATIC-DAG: @p2 ={{.*}} global i32 26,
int p2 = ; // same result without CONSTINIT
// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init()
// CHECK-DYN: %0 = load i32, i32* @p, align 4
// CHECK-DYN-NEXT: %call = call noundef i32 @_Z1fv()
// CHECK-DYN-NEXT: %add = add nsw i32 %0, %call
// CHECK-DYN-NEXT: store i32 %add, i32* @q, align 4
// CHECK-DYN-NEXT: ret void
int q = p + ; // m == 17 for this call; initialized to 56
int y;
// CHECK-STATIC-DAG: @b ={{.*}} global i32 2,
CONSTINIT int b = ? 2 : y; // static initialization to 2
// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.1()
// CHECK-DYN: %0 = load i32, i32* @y, align 4
// CHECK-DYN: %1 = load i32, i32* @y, align 4
// CHECK-DYN-NEXT: %add = add
// CHECK-DYN-NEXT: store i32 %add, i32* @c,
int c = y + ; // dynamic initialization to y+y
// This is dynamic initialization that we can convert to static initialization
// during lowering. When doing so, the dynamic initializer value is preserved.
// CHECK-STATIC-DAG: @_ZL1a = internal constant i32 1
const int a = ? y : 1; // dynamic initialization to 1
const int *a_sink = &a;
// CHECK-ARR-LABEL: define{{.*}} void @_Z13test_arr_exprv
void
// CHECK-ARR-LABEL: define{{.*}} void @_Z17test_new_arr_exprv
void
// CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali(
bool
// CHECK-FOLD-LABEL: define{{.*}} void @_Z21test_ir_constant_foldv()
void
// CHECK-STATIC-DAG: @ir ={{.*}} constant i32* @i_constant,
int i_constant;
int i_not_constant;
int &ir = ? i_constant : i_not_constant;
// CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev()
void
// CHECK-FOLD-LABEL: @_Z22test_ref_to_static_varv()
void
int not_constexpr;
// __builtin_is_constant_evaluated() should never evaluate to true during
// destruction if it would not have done so during construction.
//
// FIXME: The standard doesn't say that it should ever return true when
// evaluating a destructor call, even for a constexpr variable. That seems
// obviously wrong.
;
// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_1
DestructorBCE ;
// CHECK-DTOR: load i32, i32* @not_constexpr
// CHECK-DTOR: call {{.*}} @_ZN13DestructorBCEC1Ei({{.*}} @global_dtor_bce_2, i32
// CHECK-DTOR: atexit{{.*}} @_ZN13DestructorBCED{{.*}} @global_dtor_bce_2
// CHECK-DTOR: }
DestructorBCE ;
// CHECK-DTOR-NOT: @_ZN13DestructorBCED{{.*}}@global_dtor_bce_3
constexpr DestructorBCE ;
// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_1v(
void
// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_2v(
void
// CHECK-DTOR-LABEL: define {{.*}} @_Z15test_dtor_bce_3v(
void
// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_1v(
void
// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_2v(
void
// CHECK-DTOR-LABEL: define {{.*}} @_Z22test_dtor_bce_static_3v(
void