| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| // RUN: %clang_cc1 -std=c++2a -verify %s | ||
|
|
||
| constexpr int non_class = 42; | ||
| constexpr int arr_non_class[5] = {1, 2, 3}; | ||
|
|
||
| struct A { | ||
| int member = 1; | ||
| constexpr ~A() { member = member + 1; } | ||
| }; | ||
| constexpr A class_ = {}; | ||
| constexpr A arr_class[5] = {{}, {}}; | ||
|
|
||
| struct Mutable { | ||
| mutable int member = 1; // expected-note {{declared here}} | ||
| constexpr ~Mutable() { member = member + 1; } // expected-note {{read of mutable member}} | ||
| }; | ||
| constexpr Mutable mut_member; // expected-error {{must have constant destruction}} expected-note {{in call}} | ||
|
|
||
| struct MutableStore { | ||
| mutable int member = 1; // expected-note {{declared here}} | ||
| constexpr ~MutableStore() { member = 2; } // expected-note {{assignment to mutable member}} | ||
| }; | ||
| constexpr MutableStore mut_store; // expected-error {{must have constant destruction}} expected-note {{in call}} | ||
|
|
||
| // Note: the constant destruction rules disallow this example even though hcm.n is a const object. | ||
| struct MutableConst { | ||
| struct HasConstMember { | ||
| const int n = 4; | ||
| }; | ||
| mutable HasConstMember hcm; // expected-note {{here}} | ||
| constexpr ~MutableConst() { | ||
| int q = hcm.n; // expected-note {{read of mutable}} | ||
| } | ||
| }; | ||
| constexpr MutableConst mc; // expected-error {{must have constant destruction}} expected-note {{in call}} | ||
|
|
||
| struct Temporary { | ||
| int &&temp; | ||
| constexpr ~Temporary() { | ||
| int n = temp; // expected-note {{outside the expression that created the temporary}} | ||
| } | ||
| }; | ||
| constexpr Temporary t = {3}; // expected-error {{must have constant destruction}} expected-note {{created here}} expected-note {{in call}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,7 @@ | |
|
|
||
| class a { | ||
| public: | ||
| a(); | ||
| ~a(); | ||
| }; | ||
| class logger_base { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,58 @@ | ||
| // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s -std=c++2a | FileCheck %s --implicit-check-not=cxx_global_var_init --implicit-check-not=cxa_atexit | ||
|
|
||
| // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-pch -o %t.pch %s -std=c++2a | ||
| // RUN: %clang_cc1 -triple x86_64-linux-gnu -include-pch %t.pch -x c++ /dev/null -emit-llvm -o - -std=c++2a | FileCheck %s --implicit-check-not=cxx_global_var_init --implicit-check-not=cxa_atexit | ||
|
|
||
| // CHECK: @a = global i32 123, | ||
| int a = (delete new int, 123); | ||
|
|
||
| struct B { | ||
| constexpr B() {} | ||
| constexpr ~B() { n *= 5; } | ||
| int n = 123; | ||
| }; | ||
| // CHECK: @b = global {{.*}} i32 123 | ||
| extern constexpr B b = B(); | ||
|
|
||
| // CHECK: @_ZL1c = internal global {{.*}} i32 123 | ||
| const B c; | ||
| int use_c() { return c.n; } | ||
|
|
||
| struct D { | ||
| int n; | ||
| constexpr ~D() {} | ||
| }; | ||
| D d; | ||
| // CHECK: @d = global {{.*}} zeroinitializer | ||
|
|
||
| D d_arr[3]; | ||
| // CHECK: @d_arr = global {{.*}} zeroinitializer | ||
|
|
||
| thread_local D d_tl; | ||
| // CHECK: @d_tl = thread_local global {{.*}} zeroinitializer | ||
|
|
||
| // CHECK-NOT: @llvm.global_ctors | ||
|
|
||
| // CHECK-LABEL: define {{.*}} @_Z1fv( | ||
| void f() { | ||
| // CHECK-NOT: call | ||
| // CHECK: call {{.*}}memcpy | ||
| // CHECK-NOT: call | ||
| // CHECK: call {{.*}}memset | ||
| // CHECK-NOT: call | ||
| // CHECK: } | ||
| constexpr B b; | ||
| D d = D(); | ||
| } | ||
|
|
||
| // CHECK-LABEL: define {{.*}} @_Z1gv( | ||
| void g() { | ||
| // CHECK-NOT: call | ||
| // CHECK-NOT: cxa_guard | ||
| // CHECK-NOT: _ZGV | ||
| // CHECK: } | ||
| static constexpr B b1; | ||
| static const B b2; | ||
| static D d; | ||
| thread_local D d_tl; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++2a | FileCheck %s | ||
|
|
||
| // RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-pch -o %t.pch %s -std=c++2a | ||
| // RUN: %clang_cc1 -triple x86_64-apple-darwin -include-pch %t.pch -x c++ /dev/null -emit-llvm -o - -std=c++2a | FileCheck %s | ||
|
|
||
| struct B { | ||
| constexpr B() {} | ||
| constexpr ~B() { n *= 5; } | ||
| int n = 123; | ||
| }; | ||
|
|
||
| // We emit a dynamic destructor here because b.n might have been modified | ||
| // before b is destroyed. | ||
| // | ||
| // CHECK: @b = global {{.*}} i32 123 | ||
| B b = B(); | ||
|
|
||
| // CHECK: define {{.*}}cxx_global_var_init | ||
| // CHECK: call {{.*}} @__cxa_atexit({{.*}} @_ZN1BD1Ev {{.*}} @b |