Skip to content
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

Merged
merged 1 commit into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 14 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,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
Expand All @@ -321,6 +321,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
-------------------------
Expand All @@ -337,6 +347,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
-------------------------
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
31 changes: 31 additions & 0 deletions clang/include/clang/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,17 @@ class LangOptions : public LangOptionsBase {
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,
Expand Down Expand Up @@ -673,6 +684,26 @@ class LangOptions : public LangOptionsBase {
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;

Expand Down
11 changes: 9 additions & 2 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">,
Expand Down
23 changes: 22 additions & 1 deletion clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Driver/ToolChains/PS4CPU.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
11 changes: 7 additions & 4 deletions clang/lib/Sema/SemaExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3226,10 +3226,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) {
Expand Down
14 changes: 14 additions & 0 deletions clang/test/CodeGenCXX/visibility-global-new-delete.cpp
Original file line number Diff line number Diff line change
@@ -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
Copy link
Member

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

Copy link
Collaborator Author

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.

52 changes: 52 additions & 0 deletions clang/test/Driver/visibility-global-new-delete.cl
Original file line number Diff line number Diff line change
@@ -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}