-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[clang] Add support for omitting only global destructors #104899
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
@llvm/pr-subscribers-clang-driver Author: Shoaib Meenai (smeenai) ChangesFor mobile applications, it's common for global destructors to never be Full diff: https://github.com/llvm/llvm-project/pull/104899.diff 9 Files Affected:
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@+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@-8 {{private}}
-// thread_local SecretDestructor sd2; // expected-error@-8 {{private}}
-// void locals() {
-// static SecretDestructor sd3; // expected-error@-8 {{private}}
-// thread_local SecretDestructor sd4; // expected-error@-8 {{private}}
-// }
-#endif
-
[[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}}
[[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}}
|
@llvm/pr-subscribers-clang Author: Shoaib Meenai (smeenai) ChangesFor mobile applications, it's common for global destructors to never be Full diff: https://github.com/llvm/llvm-project/pull/104899.diff 9 Files Affected:
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@+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@-8 {{private}}
-// thread_local SecretDestructor sd2; // expected-error@-8 {{private}}
-// void locals() {
-// static SecretDestructor sd3; // expected-error@-8 {{private}}
-// thread_local SecretDestructor sd4; // expected-error@-8 {{private}}
-// }
-#endif
-
[[clang::always_destroy]] SecretDestructor sd6; // expected-error{{private}}
[[clang::always_destroy]] thread_local SecretDestructor sd7; // expected-error{{private}}
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
(I'm starting a 3-week vacation this Friday and will have limited availability.)
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( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A->render(Args, CmdArgs);
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}
optioninstead to allow omitting only global destructors.