[Sema] Add -fvisibility-global-new-delete= option (#75364)

[Sema] Add `-fvisibility-global-new-delete=` option (#75364)

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`.
This commit is contained in:
bd1976bris 2024-01-22 12:37:11 +00:00 committed by GitHub
parent df4ba00c7b
commit 27ce26b066
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 157 additions and 9 deletions

View File

@ -320,7 +320,7 @@ New Compiler Flags
handlers will be smaller. A throw expression of a type with a
potentially-throwing destructor will lead to an error.
* ``-fopenacc`` was added as a part of the effort to support OpenACC in clang.
* ``-fopenacc`` was added as a part of the effort to support OpenACC in Clang.
* ``-fcx-limited-range`` enables the naive mathematical formulas for complex
division and multiplication with no NaN checking of results. The default is
@ -331,6 +331,16 @@ New Compiler Flags
division. See SMITH, R. L. Algorithm 116: Complex division. Commun. ACM 5, 8
(1962). The default is ``-fno-cx-fortran-rules``.
* ``-fvisibility-global-new-delete=<value>`` gives more freedom to users to
control how and if Clang forces a visibility for the replaceable new and
delete declarations. The option takes 4 values: ``force-hidden``,
``force-protected``, ``force-default`` and ``source``; ``force-default`` is
the default. Option values with prefix ``force-`` assign such declarations
an implicit visibility attribute with the corresponding visibility. 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 (e.g ``--fvisibility=``).
Deprecated Compiler Flags
-------------------------
@ -347,6 +357,9 @@ Modified Compiler Flags
``rtdcall``. This new default CC only works for M68k and will use the new
``m68k_rtdcc`` CC on every functions that are not variadic. The ``-mrtd``
driver/frontend flag has the same effect when targeting M68k.
* ``-fvisibility-global-new-delete-hidden`` is now a deprecated spelling of
``-fvisibility-global-new-delete=force-hidden`` (``-fvisibility-global-new-delete=``
is new in this release).
Removed Compiler Flags
-------------------------

View File

@ -308,7 +308,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")
ENUM_LANGOPT(GlobalAllocationFunctionVisibility, VisibilityForcedKinds, 3, VisibilityForcedKinds::ForceDefault,
"How to apply visibility to 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")

View File

@ -381,6 +381,17 @@ public:
All,
};
enum class VisibilityForcedKinds {
/// Force hidden visibility
ForceHidden,
/// Force protected visibility
ForceProtected,
/// Force default visibility
ForceDefault,
/// Don't alter the visibility
Source,
};
enum class VisibilityFromDLLStorageClassKinds {
/// Keep the IR-gen assigned visibility.
Keep,
@ -673,6 +684,26 @@ public:
DefaultVisiblityExportMapping::All;
}
bool hasGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() !=
VisibilityForcedKinds::Source;
}
bool hasDefaultGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceDefault;
}
bool hasProtectedGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceProtected;
}
bool hasHiddenGlobalAllocationFunctionVisibility() const {
return getGlobalAllocationFunctionVisibility() ==
VisibilityForcedKinds::ForceHidden;
}
/// Remap path prefix according to -fmacro-prefix-path option.
void remapPathPrefix(SmallVectorImpl<char> &Path) const;

View File

@ -3910,9 +3910,16 @@ 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">;
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">,
HelpText<"Give global C++ operator new and delete declarations hidden visibility">;
class MarshallingInfoVisibilityGlobalNewDelete<KeyPathAndMacro kpm, code default>
: MarshallingInfoEnum<kpm, default>,
Values<"force-default,force-protected,force-hidden,source">,
NormalizedValuesScope<"LangOptions::VisibilityForcedKinds">,
NormalizedValues<["ForceDefault", "ForceProtected", "ForceHidden", "Source"]> {}
def fvisibility_global_new_delete_EQ : Joined<["-"], "fvisibility-global-new-delete=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoFlag<LangOpts<"GlobalAllocationFunctionVisibilityHidden">>;
HelpText<"The visibility for global C++ operator new and delete declarations. If 'source' is specified the visibility is not adjusted">,
MarshallingInfoVisibilityGlobalNewDelete<LangOpts<"GlobalAllocationFunctionVisibility">, "ForceDefault">;
def mdefault_visibility_export_mapping_EQ : Joined<["-"], "mdefault-visibility-export-mapping=">,
Values<"none,explicit,all">,
NormalizedValuesScope<"LangOptions::DefaultVisiblityExportMapping">,

View File

@ -6325,7 +6325,28 @@ 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_hidden);
// -fvisibility-global-new-delete-hidden is a deprecated spelling of
// -fvisibility-global-new-delete=force-hidden.
if (const Arg *A =
Args.getLastArg(options::OPT_fvisibility_global_new_delete_hidden)) {
D.Diag(diag::warn_drv_deprecated_arg)
<< A->getAsString(Args)
<< "-fvisibility-global-new-delete=force-hidden";
}
if (const Arg *A =
Args.getLastArg(options::OPT_fvisibility_global_new_delete_EQ,
options::OPT_fvisibility_global_new_delete_hidden)) {
if (A->getOption().matches(options::OPT_fvisibility_global_new_delete_EQ)) {
A->render(Args, CmdArgs);
} else {
assert(A->getOption().matches(
options::OPT_fvisibility_global_new_delete_hidden));
CmdArgs.push_back("-fvisibility-global-new-delete=force-hidden");
}
}
Args.AddLastArg(CmdArgs, options::OPT_ftlsmodel_EQ);
if (Args.hasFlag(options::OPT_fnew_infallible,

View File

@ -359,6 +359,12 @@ void toolchains::PS4PS5Base::addClangTargetOptions(
CC1Args.push_back("-fno-use-init-array");
// Default to -fvisibility-global-new-delete=source for PS5.
if (getTriple().isPS5() &&
!DriverArgs.hasArg(options::OPT_fvisibility_global_new_delete_EQ,
options::OPT_fvisibility_global_new_delete_hidden))
CC1Args.push_back("-fvisibility-global-new-delete=source");
const Arg *A =
DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass,
options::OPT_fno_visibility_from_dllstorageclass);

View File

@ -3216,10 +3216,13 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name,
Alloc->setLocalOwningModule(TheGlobalModuleFragment);
}
Alloc->addAttr(VisibilityAttr::CreateImplicit(
Context, LangOpts.GlobalAllocationFunctionVisibilityHidden
? VisibilityAttr::Hidden
: VisibilityAttr::Default));
if (LangOpts.hasGlobalAllocationFunctionVisibility())
Alloc->addAttr(VisibilityAttr::CreateImplicit(
Context, LangOpts.hasHiddenGlobalAllocationFunctionVisibility()
? VisibilityAttr::Hidden
: LangOpts.hasProtectedGlobalAllocationFunctionVisibility()
? VisibilityAttr::Protected
: VisibilityAttr::Default));
llvm::SmallVector<ParmVarDecl *, 3> ParamDecls;
for (QualType T : Params) {

View File

@ -0,0 +1,14 @@
// 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=default -fvisibility-global-new-delete=force-hidden -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=force-protected -emit-llvm -o - | FileCheck %s -DLINKAGE=protected
// RUN: %clang_cc1 %s -std=c++11 -triple x86_64-unknown-unknown -fvisibility=hidden -fvisibility-global-new-delete=force-default -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=source -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

View File

@ -0,0 +1,52 @@
/// 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 -c -emit-llvm %s 2>&1 | \
// RUN: FileCheck -check-prefix=DEFAULTS %s
// DEFAULTS-NOT: "-fvisibility-global-new-delete="
// DEFAULTS-NOT: "-fvisibility-global-new-delete-hidden"
// DEFINE: %{implicit-check-nots} = --implicit-check-not=-fvisibility-global-new-delete= --implicit-check-not=-fvisibility-global-new-delete-hidden
/// "-fvisibility-global-new-delete=source" added by default for PS5.
// RUN: %clang -### --target=x86_64-sie-ps5 -c -emit-llvm %s 2>&1 | \
// RUN: FileCheck -check-prefix=PS5 %s
// PS5: "-fvisibility-global-new-delete=source"
/// -fvisibility-global-new-delete-hidden added explicitly.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete-hidden %s 2>&1 | FileCheck -check-prefixes=VGNDH,DEPRECATED %s %{implicit-check-nots}
// RUN: %clang -### --target=x86_64-sie-ps5 -c -emit-llvm \
// RUN: -fvisibility-global-new-delete-hidden %s 2>&1 | FileCheck -check-prefixes=VGNDH,DEPRECATED %s %{implicit-check-nots}
// DEPRECATED-DAG: clang: warning: argument '-fvisibility-global-new-delete-hidden' is deprecated, use '-fvisibility-global-new-delete=force-hidden' instead [-Wdeprecated]
// VGNDH-DAG: "-fvisibility-global-new-delete=force-hidden"
/// -fvisibility-global-new-delete=force-hidden added explicitly.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-hidden %s 2>&1 | FileCheck -check-prefixes=VGNDH %s %{implicit-check-nots}
// RUN: %clang -### --target=x86_64-sie-ps5 -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-hidden %s 2>&1 | FileCheck -check-prefixes=VGNDH %s %{implicit-check-nots}
/// -fvisibility-global-new-delete=force-protected added explicitly.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-protected %s 2>&1 | FileCheck -check-prefixes=VGNDP %s %{implicit-check-nots}
// RUN: %clang -### --target=x86_64-sie-ps5 -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-protected %s 2>&1 | FileCheck -check-prefixes=VGNDP %s %{implicit-check-nots}
// VGNDP-DAG: "-fvisibility-global-new-delete=force-protected"
/// -fvisibility-global-new-delete=force-default added explicitly.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-default %s 2>&1 | FileCheck -check-prefixes=VGNDD %s %{implicit-check-nots}
// RUN: %clang -### --target=x86_64-sie-ps5 -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-default %s 2>&1 | FileCheck -check-prefixes=VGNDD %s %{implicit-check-nots}
// VGNDD-DAG: "-fvisibility-global-new-delete=force-default"
/// last specfied used: -fvisibility-global-new-delete-hidden.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete=force-default -fvisibility-global-new-delete=force-protected -fvisibility-global-new-delete-hidden %s 2>&1 | \
// RUN: FileCheck -check-prefixes=VGNDH,DEPRECATED %s %{implicit-check-nots}
/// last specfied used: -fvisibility-global-new-delete=.
// RUN: %clang -### --target=x86_64-unknown-unknown -c -emit-llvm \
// RUN: -fvisibility-global-new-delete-hidden -fvisibility-global-new-delete=force-default -fvisibility-global-new-delete=force-protected %s 2>&1 | \
// RUN: FileCheck -check-prefixes=VGNDP,DEPRECATED %s %{implicit-check-nots}