Skip to content

[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

Merged
merged 2 commits into from
Aug 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
17 changes: 12 additions & 5 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">>;
Expand Down
14 changes: 11 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A->render(Args, CmdArgs);

Args.MakeArgString(Twine("-fc++-static-destructors=") + A->getValue()));

addMachineOutlinerArgs(D, Args, CmdArgs, Triple, /*IsLTO=*/false);

Expand Down
8 changes: 6 additions & 2 deletions clang/test/CodeGenCXX/always_destroy.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
// 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();
};

// 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 {
Expand Down
3 changes: 2 additions & 1 deletion clang/test/CodeGenCXX/attr-no-destroy-d54344.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down
9 changes: 9 additions & 0 deletions clang/test/Driver/cxx-static-destructors.cpp
Original file line number Diff line number Diff line change
@@ -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
30 changes: 10 additions & 20 deletions clang/test/SemaCXX/no_destroy.cpp
Original file line number Diff line number Diff line change
@@ -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}}

Expand Down
Loading