[clang] [clang] Add support for omitting only global destructors (PR #104899)
Shoaib Meenai via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 20 11:03:05 PDT 2024
https://github.com/smeenai updated https://github.com/llvm/llvm-project/pull/104899
>From e0a1a4d57d2801f68adc0f4fe26d33d509956490 Mon Sep 17 00:00:00 2001
From: Shoaib Meenai <smeenai at fb.com>
Date: Mon, 19 Aug 2024 18:05:52 -0700
Subject: [PATCH 1/2] [clang] Add support for omitting only global destructors
For mobile applications, it's common for global destructors to never be
called (because the applications have their own lifecycle independent of
the standard C runtime), but threads are created and destroyed as normal
and so thread-local destructors are still called. -fno-static-c++-destructors
omits unnecessary global destructors, which is useful for code size, but
it also omits thread-local destructors, which is unsuitable. Add a
ternary `-fc++-static-destructors={all,none,thread-local}` option
instead to allow omitting only global destructors.
---
clang/include/clang/Basic/LangOptions.def | 4 ++-
clang/include/clang/Basic/LangOptions.h | 10 +++++++
clang/include/clang/Driver/Options.td | 17 +++++++----
clang/lib/AST/Decl.cpp | 14 +++++++--
clang/lib/Driver/ToolChains/Clang.cpp | 5 ++--
clang/test/CodeGenCXX/always_destroy.cpp | 8 +++--
.../CodeGenCXX/attr-no-destroy-d54344.cpp | 3 +-
clang/test/Driver/cxx-static-destructors.cpp | 9 ++++++
clang/test/SemaCXX/no_destroy.cpp | 30 +++++++------------
9 files changed, 66 insertions(+), 34 deletions(-)
create mode 100644 clang/test/Driver/cxx-static-destructors.cpp
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index d454a7ff2f8cf4..a57da8addb69be 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -465,7 +465,9 @@ LANGOPT(FixedPoint, 1, 0, "fixed point types")
LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0,
"unsigned fixed point types having one extra padding bit")
-LANGOPT(RegisterStaticDestructors, 1, 1, "Register C++ static destructors")
+ENUM_LANGOPT(RegisterStaticDestructors, RegisterStaticDestructorsKind, 2,
+ RegisterStaticDestructorsKind::All,
+ "Register C++ static destructors")
LANGOPT(RegCall4, 1, 0, "Set __regcall4 as a default calling convention to respect __regcall ABI v.4")
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 91f1c2f2e6239e..88fbf26e2eb79b 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -441,6 +441,16 @@ class LangOptionsBase {
CX_None
};
+ /// Controls which variables have static destructors registered.
+ enum class RegisterStaticDestructorsKind {
+ /// Register static destructors for all variables.
+ All,
+ /// Register static destructors only for thread-local variables.
+ ThreadLocal,
+ /// Don't register static destructors for any variables.
+ None,
+ };
+
// Define simple language options (with no accessors).
#define LANGOPT(Name, Bits, Default, Description) unsigned Name : Bits;
#define ENUM_LANGOPT(Name, Type, Bits, Default, Description)
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index c66e035a259b3f..0d8cb1d18fb24d 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -2300,11 +2300,18 @@ defm fixed_point : BoolFOption<"fixed-point",
PosFlag<SetTrue, [], [ClangOption, CC1Option], "Enable">,
NegFlag<SetFalse, [], [ClangOption], "Disable">,
BothFlags<[], [ClangOption], " fixed point types">>;
-defm cxx_static_destructors : BoolFOption<"c++-static-destructors",
- LangOpts<"RegisterStaticDestructors">, DefaultTrue,
- NegFlag<SetFalse, [], [ClangOption, CC1Option],
- "Disable C++ static destructor registration">,
- PosFlag<SetTrue>>;
+def cxx_static_destructors_EQ : Joined<["-"], "fc++-static-destructors=">, Group<f_Group>,
+ HelpText<"Controls which variables C++ static destructors are registered for">,
+ Values<"all,thread-local,none">,
+ NormalizedValues<["All", "ThreadLocal", "None"]>,
+ NormalizedValuesScope<"LangOptions::RegisterStaticDestructorsKind">,
+ MarshallingInfoEnum<LangOpts<"RegisterStaticDestructors">, "All">,
+ Visibility<[ClangOption, CC1Option]>;
+def cxx_static_destructors : Flag<["-"], "fc++-static-destructors">, Group<f_Group>,
+ Alias<cxx_static_destructors_EQ>, AliasArgs<["all"]>;
+def no_cxx_static_destructors : Flag<["-"], "fno-c++-static-destructors">, Group<f_Group>,
+ Alias<cxx_static_destructors_EQ>, AliasArgs<["none"]>,
+ HelpText<"Disable C++ static destructor registration">;
def fsymbol_partition_EQ : Joined<["-"], "fsymbol-partition=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoString<CodeGenOpts<"SymbolPartition">>;
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 90caf81757ac96..1a07125815832e 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2799,9 +2799,17 @@ bool VarDecl::isKnownToBeDefined() const {
}
bool VarDecl::isNoDestroy(const ASTContext &Ctx) const {
- return hasGlobalStorage() && (hasAttr<NoDestroyAttr>() ||
- (!Ctx.getLangOpts().RegisterStaticDestructors &&
- !hasAttr<AlwaysDestroyAttr>()));
+ if (!hasGlobalStorage())
+ return false;
+ if (hasAttr<NoDestroyAttr>())
+ return true;
+ if (hasAttr<AlwaysDestroyAttr>())
+ return false;
+
+ using RSDKind = LangOptions::RegisterStaticDestructorsKind;
+ RSDKind K = Ctx.getLangOpts().getRegisterStaticDestructors();
+ return K == RSDKind::None ||
+ (K == RSDKind::ThreadLocal && getTLSKind() == TLS_None);
}
QualType::DestructionKind
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index a5a87db97e96b4..68ac374e036b1f 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7967,8 +7967,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
options::OPT_fno_keep_persistent_storage_variables);
Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers,
options::OPT_fno_complete_member_pointers);
- Args.addOptOutFlag(CmdArgs, options::OPT_fcxx_static_destructors,
- options::OPT_fno_cxx_static_destructors);
+ if (Arg *A = Args.getLastArg(options::OPT_cxx_static_destructors_EQ))
+ CmdArgs.push_back(
+ Args.MakeArgString(Twine("-fc++-static-destructors=") + A->getValue()));
addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false);
diff --git a/clang/test/CodeGenCXX/always_destroy.cpp b/clang/test/CodeGenCXX/always_destroy.cpp
index e84c4cf02c52f5..ca8a8e0cabacb3 100644
--- a/clang/test/CodeGenCXX/always_destroy.cpp
+++ b/clang/test/CodeGenCXX/always_destroy.cpp
@@ -1,4 +1,7 @@
-// RUN: %clang_cc1 %s -fno-c++-static-destructors -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | FileCheck %s
+// RUN: %clang_cc1 %s -fc++-static-destructors=none -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,NO-DTORS %s
+// RUN: %clang_cc1 %s -fc++-static-destructors=thread-local -emit-llvm -triple x86_64-apple-macosx10.13.0 -o - | \
+// RUN: FileCheck --check-prefixes=CHECK,THREAD-LOCAL-DTORS %s
struct NonTrivial {
~NonTrivial();
@@ -6,7 +9,8 @@ struct NonTrivial {
// CHECK-NOT: __cxa_atexit{{.*}}_ZN10NonTrivialD1Ev
NonTrivial nt1;
-// CHECK-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+// NO-DTORS-NOT: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
+// THREAD-LOCAL-DTORS: _tlv_atexit{{.*}}_ZN10NonTrivialD1Ev
thread_local NonTrivial nt2;
struct NonTrivial2 {
diff --git a/clang/test/CodeGenCXX/attr-no-destroy-d54344.cpp b/clang/test/CodeGenCXX/attr-no-destroy-d54344.cpp
index b03791e5135df5..053043adb61c17 100644
--- a/clang/test/CodeGenCXX/attr-no-destroy-d54344.cpp
+++ b/clang/test/CodeGenCXX/attr-no-destroy-d54344.cpp
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR %s -o - | FileCheck %s
// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefix=CHECK-ATTR
-// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR -fno-c++-static-destructors %s -o - | FileCheck %s --check-prefix=CHECK-FLAG
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR -fc++-static-destructors=none %s -o - | FileCheck %s --check-prefix=CHECK-FLAG
+// RUN: %clang_cc1 -std=c++2a -emit-llvm -O0 -triple x86_64-unknown-linux-gnu -DNOATTR -fc++-static-destructors=thread-local %s -o - | FileCheck %s --check-prefix=CHECK-FLAG
// Regression test for D54344. Class with no user-defined destructor
// that has an inherited member that has a non-trivial destructor
diff --git a/clang/test/Driver/cxx-static-destructors.cpp b/clang/test/Driver/cxx-static-destructors.cpp
new file mode 100644
index 00000000000000..71da4d28c25142
--- /dev/null
+++ b/clang/test/Driver/cxx-static-destructors.cpp
@@ -0,0 +1,9 @@
+// RUN: %clang -### -c -fc++-static-destructors=all %s 2>&1 | FileCheck --check-prefix ALL %s
+// RUN: %clang -### -c -fc++-static-destructors %s 2>&1 | FileCheck --check-prefix ALL %s
+// RUN: %clang -### -c -fc++-static-destructors=none %s 2>&1 | FileCheck --check-prefix NONE %s
+// RUN: %clang -### -c -fno-c++-static-destructors %s 2>&1 | FileCheck --check-prefix NONE %s
+// RUN: %clang -### -c -fc++-static-destructors=thread-local %s 2>&1 | FileCheck --check-prefix THREAD-LOCAL %s
+
+// ALL: -fc++-static-destructors=all
+// NONE: -fc++-static-destructors=none
+// THREAD-LOCAL: -fc++-static-destructors=thread-local
diff --git a/clang/test/SemaCXX/no_destroy.cpp b/clang/test/SemaCXX/no_destroy.cpp
index 5872bcf4b439e2..d39bcaeff860a1 100644
--- a/clang/test/SemaCXX/no_destroy.cpp
+++ b/clang/test/SemaCXX/no_destroy.cpp
@@ -1,31 +1,21 @@
-// RUN: %clang_cc1 -DNO_DTORS -DNO_EXCEPTIONS -fno-c++-static-destructors -verify %s
-// RUN: %clang_cc1 -DNO_EXCEPTIONS -verify %s
-// RUN: %clang_cc1 -DNO_DTORS -fexceptions -fno-c++-static-destructors -verify %s
-// RUN: %clang_cc1 -fexceptions -verify %s
+// RUN: %clang_cc1 -fc++-static-destructors=none -verify %s
+// RUN: %clang_cc1 -fc++-static-destructors=thread-local -verify=expected,thread-local-dtors %s
+// RUN: %clang_cc1 -verify=expected,thread-local-dtors,all-dtors %s
+// RUN: %clang_cc1 -fexceptions -fc++-static-destructors=none -verify %s
+// RUN: %clang_cc1 -fexceptions -fc++-static-destructors=thread-local -verify=expected,thread-local-dtors %s
+// RUN: %clang_cc1 -fexceptions -verify=expected,thread-local-dtors,all-dtors %s
struct SecretDestructor {
-#ifndef NO_DTORS
- // expected-note at +2 4 {{private}}
-#endif
private: ~SecretDestructor(); // expected-note + {{private}}
};
-SecretDestructor sd1;
-thread_local SecretDestructor sd2;
+SecretDestructor sd1; // all-dtors-error{{private}}
+thread_local SecretDestructor sd2; // thread-local-dtors-error{{private}}
void locals() {
- static SecretDestructor sd3;
- thread_local SecretDestructor sd4;
+ static SecretDestructor sd3; // all-dtors-error{{private}}
+ thread_local SecretDestructor sd4; // thread-local-dtors-error{{private}}
}
-#ifndef NO_DTORS
-// SecretDestructor sd1; // expected-error at -8 {{private}}
-// thread_local SecretDestructor sd2; // expected-error at -8 {{private}}
-// void locals() {
-// static SecretDestructor sd3; // expected-error at -8 {{private}}
-// thread_local SecretDestructor sd4; // expected-error at -8 {{private}}
-// }
-#endif
-
[[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}}
[[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}}
>From 76d4eb283b3c20e9fe11dcb075e442a87d4492bb Mon Sep 17 00:00:00 2001
From: Shoaib Meenai <smeenai at fb.com>
Date: Tue, 20 Aug 2024 11:02:42 -0700
Subject: [PATCH 2/2] Address comments and add release note
---
clang/docs/ReleaseNotes.rst | 7 +++++++
clang/lib/Driver/ToolChains/Clang.cpp | 3 +--
clang/test/Driver/cxx-static-destructors.cpp | 2 ++
3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 249249971dec7c..4dbf2fde5786da 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -168,6 +168,13 @@ Non-comprehensive list of changes in this release
New Compiler Flags
------------------
+- The ``-fc++-static-destructors={all,thread-local,none}`` flag was
+ added to control which C++ variables have static destructors
+ registered: all (the default) does so for all variables, thread-local
+ only for thread-local variables, and none (which corresponds to the
+ existing ``-fno-c++-static-destructors`` flag) skips all static
+ destructors registration.
+
Deprecated Compiler Flags
-------------------------
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 68ac374e036b1f..9714a0d86b675b 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7968,8 +7968,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptInFlag(CmdArgs, options::OPT_fcomplete_member_pointers,
options::OPT_fno_complete_member_pointers);
if (Arg *A = Args.getLastArg(options::OPT_cxx_static_destructors_EQ))
- CmdArgs.push_back(
- Args.MakeArgString(Twine("-fc++-static-destructors=") + A->getValue()));
+ A->render(Args, CmdArgs);
addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false);
diff --git a/clang/test/Driver/cxx-static-destructors.cpp b/clang/test/Driver/cxx-static-destructors.cpp
index 71da4d28c25142..a12a292a387bda 100644
--- a/clang/test/Driver/cxx-static-destructors.cpp
+++ b/clang/test/Driver/cxx-static-destructors.cpp
@@ -1,7 +1,9 @@
// RUN: %clang -### -c -fc++-static-destructors=all %s 2>&1 | FileCheck --check-prefix ALL %s
// RUN: %clang -### -c -fc++-static-destructors %s 2>&1 | FileCheck --check-prefix ALL %s
+// RUN: %clang -### -c -fno-c++-static-destructors -fc++-static-destructors %s 2>&1 | FileCheck --check-prefix ALL %s
// RUN: %clang -### -c -fc++-static-destructors=none %s 2>&1 | FileCheck --check-prefix NONE %s
// RUN: %clang -### -c -fno-c++-static-destructors %s 2>&1 | FileCheck --check-prefix NONE %s
+// RUN: %clang -### -c -fc++-static-destructors -fno-c++-static-destructors %s 2>&1 | FileCheck --check-prefix NONE %s
// RUN: %clang -### -c -fc++-static-destructors=thread-local %s 2>&1 | FileCheck --check-prefix THREAD-LOCAL %s
// ALL: -fc++-static-destructors=all
More information about the cfe-commits
mailing list