diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -307,6 +307,14 @@ return Addr; } +/// hasNontrivialDestruction - Determine whether a type's destruction is +/// non-trivial. If so, and the variable uses static initialization, we must +/// register its destructor to run on exit. +static bool hasNontrivialDestruction(QualType T) { + CXXRecordDecl *RD = T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + return RD && !RD->hasTrivialDestructor(); +} + /// AddInitializerToStaticVarDecl - Add the initializer for 'D' to the /// global variable that has already been created for it. If the initializer /// has a different type than GV does, this may free GV and return a different @@ -366,7 +374,7 @@ emitter.finalize(GV); - if (D.needsDestruction(getContext()) && HaveInsertPoint()) { + if (hasNontrivialDestruction(D.getType()) && HaveInsertPoint()) { // We have a constant initializer, but a nontrivial destructor. We still // need to perform a guarded "initialization" in order to register the // destructor. diff --git a/clang/test/CodeGenCXX/const-init-cxx2a.cpp b/clang/test/CodeGenCXX/const-init-cxx2a.cpp --- a/clang/test/CodeGenCXX/const-init-cxx2a.cpp +++ b/clang/test/CodeGenCXX/const-init-cxx2a.cpp @@ -1,58 +1,5 @@ -// 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 +// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++2a | FileCheck %s +// expected-no-diagnostics // 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; -} diff --git a/clang/test/CodeGenObjC/initialize-function-static.m b/clang/test/CodeGenObjC/initialize-function-static.m new file mode 100644 --- /dev/null +++ b/clang/test/CodeGenObjC/initialize-function-static.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos10.15 -emit-llvm -fobjc-arc -o - %s | FileCheck %s + +@interface I +@end + +I *i() { + static I *i = ((void *)0); + return i; +} + +// CHECK-NOT: __cxa_guard_acquire +// CHECK-NOT: __cxa_guard_release