-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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
[Sema] Add -fvisibility-global-new-delete=
option
#75364
[Sema] Add -fvisibility-global-new-delete=
option
#75364
Conversation
@llvm/pr-subscribers-clang-driver @llvm/pr-subscribers-clang Author: bd1976bris (bd1976bris) ChangesBy default the implicitly declared replaceable global new and delete operators are given a This change adds: The command line help for these options is rendered as:
The motivation is to allow users to specify
Full diff: https://github.com/llvm/llvm-project/pull/75364.diff 7 Files Affected:
diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index c3d5399905a3fd..1471fc11e11663 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -306,7 +306,8 @@ BENIGN_LANGOPT(IgnoreXCOFFVisibility, 1, 0, "All the visibility attributes that
BENIGN_LANGOPT(VisibilityInlinesHiddenStaticLocalVar, 1, 0,
"hidden visibility for static local variables in inline C++ "
"methods when -fvisibility-inlines hidden is enabled")
-LANGOPT(GlobalAllocationFunctionVisibilityHidden , 1, 0, "hidden visibility for global operator new and delete declaration")
+LANGOPT(GlobalAllocationFunctionVisibility, 1, 1, "add a visibility attribute to the implicit global operator new and delete declarations")
+LANGOPT(GlobalAllocationFunctionVisibilityHidden, 1, 0, "hidden visibility for global operator new and delete declarations")
LANGOPT(NewInfallible , 1, 0, "Treats throwing global C++ operator new as always returning valid memory (annotates with __attribute__((returns_nonnull)) and throw()). This is detectable in source.")
BENIGN_LANGOPT(ParseUnknownAnytype, 1, 0, "__unknown_anytype")
BENIGN_LANGOPT(DebuggerSupport , 1, 0, "debugger support")
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index db2190318c931a..a9f43b18df6fbf 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -3863,6 +3863,12 @@ defm visibility_inlines_hidden_static_local_var : BoolFOption<"visibility-inline
def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>,
HelpText<"Give global types 'default' visibility and global functions and "
"variables 'hidden' visibility by default">;
+defm visibility_global_new_delete : BoolFOption<"visibility-global-new-delete",
+ LangOpts<"GlobalAllocationFunctionVisibility">, DefaultTrue,
+ PosFlag<SetTrue, [], [ClangOption], "Add">,
+ NegFlag<SetFalse, [], [ClangOption], "Do not add">,
+ BothFlags<[], [ClangOption, CC1Option],
+ " a visibility attribute to the implicit global C++ operator new and delete declarations">>;
def fvisibility_global_new_delete_hidden : Flag<["-"], "fvisibility-global-new-delete-hidden">, Group<f_Group>,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">,
Visibility<[ClangOption, CC1Option]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index f02f7c841b91f0..979e2a0e83be37 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -6204,7 +6204,19 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var,
options::OPT_fno_visibility_inlines_hidden_static_local_var);
+ Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete,
+ options::OPT_fno_visibility_global_new_delete);
Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden);
+ // Error for incompatible global new and delete directives.
+ const Arg *N = Args.getLastArg(options::OPT_fvisibility_global_new_delete,
+ options::OPT_fno_visibility_global_new_delete);
+ if (N &&
+ N->getOption().matches(options::OPT_fno_visibility_global_new_delete)) {
+ if (Arg *H =
+ Args.getLastArg(options::OPT_fvisibility_global_new_delete_hidden))
+ D.Diag(diag::err_drv_incompatible_options)
+ << N->getSpelling() << H->getSpelling();
+ }
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
if (Args.hasFlag(options::OPT_fnew_infallible,
diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index 5fd82d1da19926..a535d5fb2a7200 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -359,6 +359,12 @@ void toolchains::PS4PS5Base::addClangTargetOptions(
CC1Args.push_back("-fno-use-init-array");
+ // Default to -fno-visibility-global-new-delete for PS5.
+ if (getTriple().isPS5() &&
+ !DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete,
+ options::OPT_fno_visibility_global_new_delete,
+ options::OPT_fvisibility_global_new_delete_hidden))
+ CC1Args.push_back("-fno-visibility-global-new-delete");
const Arg *A =
DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
options::OPT_fno_visibility_from_dllstorageclass);
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 081b568762ae22..29480a1e0c0346 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3222,10 +3222,11 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Alloc->setLocalOwningModule(TheGlobalModuleFragment);
}
- Alloc->addAttr(VisibilityAttr::CreateImplicit(
- Context, LangOpts.GlobalAllocationFunctionVisibilityHidden
- ? VisibilityAttr::Hidden
- : VisibilityAttr::Default));
+ if (LangOpts.GlobalAllocationFunctionVisibility)
+ Alloc->addAttr(VisibilityAttr::CreateImplicit(
+ Context, LangOpts.GlobalAllocationFunctionVisibilityHidden
+ ? VisibilityAttr::Hidden
+ : VisibilityAttr::Default));
llvm::SmallVector<ParmVarDecl *, 3> ParamDecls;
for (QualType T : Params) {
diff --git a/clang/test/CodeGenCXX/visibility-global-new-delete.cpp b/clang/test/CodeGenCXX/visibility-global-new-delete.cpp
new file mode 100644
index 00000000000000..b29a5f01e9a647
--- /dev/null
+++ b/clang/test/CodeGenCXX/visibility-global-new-delete.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-unknown -fvisibility=hidden -emit-llvm -o - | FileCheck %s -DLINKAGE=dso_local
+// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-unknown -fvisibility=hidden -fvisibility-global-new-delete -emit-llvm -o - | FileCheck %s -DLINKAGE=dso_local
+// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-unknown -fvisibility=hidden -fno-visibility-global-new-delete -emit-llvm -o - | FileCheck %s -DLINKAGE=hidden
+// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-unknown -fvisibility=hidden -fvisibility-global-new-delete-hidden -emit-llvm -o - | FileCheck %s -DLINKAGE=hidden
+
+namespace std {
+ typedef __typeof__(sizeof(0)) size_t;
+ struct nothrow_t {};
+}
+
+// Definition which inherits visibility from the implicit compiler generated declaration.
+void operator delete(void*) throw() {}
+// CHECK: define [[LINKAGE]] void @_ZdlPv
diff --git a/clang/test/Driver/visibility-global-new-delete.cl b/clang/test/Driver/visibility-global-new-delete.cl
new file mode 100644
index 00000000000000..08e3a812887452
--- /dev/null
+++ b/clang/test/Driver/visibility-global-new-delete.cl
@@ -0,0 +1,47 @@
+/// Check driver handling for "-fvisibility-global-new-delete-hidden" and "-fvisibility-global-new-delete".
+
+/// These options are not added by default.
+// RUN: %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm %s 2>&1 | \
+// RUN: FileCheck -check-prefix=DEFAULTS %s
+// DEFAULTS-NOT: "-fvisibility-global-new-delete"
+// DEFAULTS-NOT: "-fno-visibility-global-new-delete"
+// DEFAULTS-NOT: "-fvisibility-global-new-delete-hidden"
+
+// DEFINE: %{implicit-check-nots} = --implicit-check-not=-fvisibility-global-new-delete --implicit-check-not=-fno-visibility-global-new-delete
+
+/// "-fno-visibility-global-new-delete" added by default for PS5.
+// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm %s 2>&1 | \
+// RUN: FileCheck -check-prefix=PS5 %s
+// PS5: "-fno-visibility-global-new-delete"
+
+/// -fvisibility-global-new-delete-hidden added explicitly.
+// RUN: %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete-hidden %s 2>&1 | FileCheck -check-prefixes=HIDDEN %s %{implicit-check-nots}
+// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete-hidden %s 2>&1 | FileCheck -check-prefixes=HIDDEN %s %{implicit-check-nots}
+// HIDDEN-DAG: "-fvisibility-global-new-delete-hidden"
+
+/// -fvisibility-global-new-delete added explicitly.
+// RUN: %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete %s 2>&1 | FileCheck -check-prefixes=VGND %s %{implicit-check-nots}
+// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete %s 2>&1 | FileCheck -check-prefixes=VGND %s %{implicit-check-nots}
+// VGND-DAG: "-fvisibility-global-new-delete"
+
+/// -fno-visibility-global-new-delete added explicitly.
+// RUN: %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm \
+// RUN: -fno-visibility-global-new-delete %s 2>&1 | FileCheck -check-prefixes=NO_VGND %s %{implicit-check-nots}
+// RUN: %clang -### -target x86_64-sie-ps5 -x cl -c -emit-llvm \
+// RUN: -fno-visibility-global-new-delete %s 2>&1 | FileCheck -check-prefixes=NO_VGND %s %{implicit-check-nots}
+// NO_VGND-DAG: "-fno-visibility-global-new-delete"
+
+/// No error if both -fvisibility-global-new-delete and -fvisibility-global-new-delete-hidden specified.
+// RUN: %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete-hidden -fvisibility-global-new-delete %s 2>&1 | \
+// RUN: FileCheck -check-prefixes=VGND,HIDDEN %s %{implicit-check-nots}
+
+/// Error if both -fno-visibility-global-new-delete and -fvisibility-global-new-delete-hidden specified.
+// RUN: not %clang -### -target x86_64-unknown-unknown -x cl -c -emit-llvm \
+// RUN: -fvisibility-global-new-delete-hidden -fvisibility-global-new-delete -fno-visibility-global-new-delete %s 2>&1 | \
+// RUN: FileCheck -check-prefixes=INCOMPAT %s
+// INCOMPAT: clang: error: the combination of '-fno-visibility-global-new-delete' and '-fvisibility-global-new-delete-hidden' is incompatible
|
See #74629 for more on visibility support in PlayStation. |
✅ With the latest revision this PR passed the C/C++ code formatter. |
Noting previous discussions w.r.t. -fvisibility-global-new-delete-hidden on https://reviews.llvm.org/D133266. I have added reviewers from that phab review in case they are interested in this. |
From a UI perspective, "add a visibility attribute" doesn't seem all that descriptive. What visibility does it add? Therefore, I suggest I'm unclear what the (If the universe would implode given a visibility other than I hope this makes sense... |
Thanks Paul. It's a nice suggestion for the UI. I didn't go down this route because the name
There's a difference! The |
I don't think it's very clear from |
The meaning that we want to make clear is that this toggles the special behavior of forcing the visibility of these symbols despite all the other mechanisms that usually control visibility for all other symbols. So perhaps |
Thanks for the responses.
Agreed. I'm in favour of your suggestion of
Indeed and the use of the usual pragmas etc is preferable, IMO, as users are already familiar with those - as opposed to the effects of an unusual/niche option. |
I have updated the patch to use |
Actually I kind of prefer all these options to have |
I don't have a strong opinion about the exact spelling. I just recommend that it be as unambiguous as possible, and the use of "forced" in the name seems like a good way to help with that. |
How about instead using Perhaps we can use values of |
@zygoloid - yes, the choice of "default" for the name of one of the visibility values in ELF is annoying :) Thanks for the comments all. I feel that what we might need is a bit of a benevolent dictator here. Does anyone object to Richard's |
To be clear: I didn't mean to suggest that |
-fno-/-fvisibility-global-new-delete
option-fvisibility-global-new-delete=
option
Given that there have been no objections I have modified this to match @zygoloid's suggestion of |
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.
I'm okay with the PS5-specific bits. Other people should have a chance to chime in so I won't mark it approved.
|
||
// Definition which inherits visibility from the implicit compiler generated declaration. | ||
void operator delete(void*) throw() {} | ||
// CHECK: define [[LINKAGE]] void @_ZdlPv |
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.
Add a test for operator new
?
-fvisibility-global-new-delete-hidden
, from https://reviews.llvm.org/D53787, does not have a test. Thanks for adding the test
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.
I don't think there is much value in adding operator new as these declarations are all handled in the same way. I think minimal testing here is better.
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.
Consider adding a note to clang/docs/ReleaseNotes.rst. With a few nits this LGTM.
By default the implicitly declared replaceable global new and delete operators are given a default visibility attribute. Previous work, see: https://reviews.llvm.org/D53787, added `-fvisibility-global-new-delete-hidden` to change this to a hidden visibility attribute. This change adds `-fvisibility-global-new-delete=` which controls whether (or not) to add an implicit visibility attribute to the implicit declarations for these functions, and what visibility that attribute will specify. The option takes 4 values: `force-hidden`, `force-protected`, `force-default` and `source`. Option values `force-hidden`, `force-protected` and `force-default` assign hidden, protected, and default visibilities respectively; the use of the term force in the value names is designed to imply to a user that the semantics of this option differ significantly from `-fvisibility=`. An option value of `source` implies that no implicit attribute is added; without the attribute the replaceable global new and delete operators behave normally (like other functions) with respect to visibility attributes, pragmas and options. The motivation for the `source` value is to facilitate users who intend to replace these functions either for a single linkage unit or a limited set of linkage units. `-fvisibility-global-new-delete=source` can be applied globally to the compilations in a build where the existing `-fvisibility-global-new-delete-hidden` cannot, as it conflicts with a common pattern where these functions are dynamically imported. The existing `-fvisibility-global-new-delete-hidden` is now a deprecated spelling of `-fvisibility-global-new-delete=force-hidden` A release note has been added for these changes. `-fvisibility-global-new-delete=source` will be set by default for PS5. PS5 users that want the normal toolchain behaviour will be able to supply `-fvisibility-global-new-delete=force-default`.
708140b
to
dc60cb2
Compare
-fvisibility-global-new-delete=
option-fvisibility-global-new-delete=
option
I rebased the changes onto the latest main to resolve the merge conflicts - these were just textual not semantic. |
You may like getcord/spr :) |
Thanks for the link to the write up. Very much appreciated. I need to improve my workflow now that everything is via github. I don't particularly like GUI interfaces... you'll notice that I managed to repeat the header line in the commit comment when committing through the GUI: 27ce26b 🥇 |
By default the implicitly declared replaceable global new and delete
operators are given a default visibility attribute. Previous work, see:
https://reviews.llvm.org/D53787, added
-fvisibility-global-new-delete-hidden
to change this to a hiddenvisibility attribute.
This change adds
-fvisibility-global-new-delete=
which controlswhether (or not) to add an implicit visibility attribute to the implicit
declarations for these functions, and what visibility that attribute
will specify. The option takes 4 values:
force-hidden
,force-protected
,force-default
andsource
. Option valuesforce-hidden
,force-protected
andforce-default
assign hidden,protected, and default visibilities respectively; the use of the term
force in the value names is designed to imply to a user that the semantics
of this option differ significantly from
-fvisibility=
. An optionvalue of
source
implies that no implicit attribute is added; withoutthe attribute the replaceable global new and delete operators behave
normally (like other functions) with respect to visibility attributes,
pragmas and options.
The motivation for the
source
value is to facilitate users who intendto replace these functions either for a single linkage unit or a limited
set of linkage units.
-fvisibility-global-new-delete=source
can beapplied globally to the compilations in a build where the existing
-fvisibility-global-new-delete-hidden
cannot, as it conflicts with acommon pattern where these functions are dynamically imported.
The existing
-fvisibility-global-new-delete-hidden
is now a deprecatedspelling of
-fvisibility-global-new-delete=force-hidden
The command line help for these options is rendered as:
A release note has been added for these changes.
-fvisibility-global-new-delete=source
will be set by default for PS5.PS5 users that want the normal toolchain behaviour will be able to
supply
-fvisibility-global-new-delete=force-default
.