diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -2307,6 +2307,10 @@ Give inline C++ member functions hidden visibility by default +.. option:: -mignore-xcoff-visibility + +Ignore all the visibility pragmas and attributes in source code for aix xcoff. + .. option:: -fvisibility-ms-compat Give global types 'default' visibility and global functions and variables 'hidden' visibility by default diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -297,6 +297,7 @@ "type's inheritance model would be determined under the Microsoft ABI") ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode") +BENIGN_LANGOPT(IgnoreXCOFFVisibility, 1, 0, "All the visibility pragmas and attributes that are specified in the source are ignored in aix.") ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility, "default visibility for functions and variables [-fvisibility]") ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1936,6 +1936,9 @@ def fverbose_asm : Flag<["-"], "fverbose-asm">, Group, HelpText<"Generate verbose assembly output">; def dA : Flag<["-"], "dA">, Alias; +def mignore_xcoff_visibility : Flag<["-"], "mignore-xcoff-visibility">, Group, + HelpText<"Ignore all the visibility pragmas and attributes in source code">, + Flags<[CC1Option]>; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group, HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group, diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1477,10 +1477,14 @@ } LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) { - return getLVForDecl(D, - LVComputationKind(usesTypeVisibility(D) - ? NamedDecl::VisibilityForType - : NamedDecl::VisibilityForValue)); + NamedDecl::ExplicitVisibilityKind EK = usesTypeVisibility(D) + ? NamedDecl::VisibilityForType + : NamedDecl::VisibilityForValue; + LVComputationKind CK(EK); + + return getLVForDecl(D, D->getASTContext().getLangOpts().IgnoreXCOFFVisibility + ? CK.forLinkageOnly() + : CK); } Module *Decl::getOwningModuleForLinkage(bool IgnoreLinkage) const { diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -5198,6 +5198,13 @@ } } + if (const Arg *A = Args.getLastArg(options::OPT_mignore_xcoff_visibility)) + if (Triple.isOSAIX()) + CmdArgs.push_back("-mignore-xcoff-visibility"); + else + D.Diag(diag::err_drv_unsupported_opt_for_target) + << A->getAsString(Args) << TripleStr; + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_global_new_delete_hidden); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2749,9 +2749,19 @@ // The value-visibility mode defaults to "default". if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) { - Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags)); + // In AIX Os, if there is -mignore_xcoff_visibility and -fvisibility=* at + // sametime, the option "mignore_xcoff_visibility" take effect. + if (T.isOSAIX() && Args.hasArg(OPT_mignore_xcoff_visibility)) + Opts.IgnoreXCOFFVisibility = 1; + else + Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags)); } else { - Opts.setValueVisibilityMode(DefaultVisibility); + // In AIX oS, the -mignore_xcoff_visibility is enable by default if there is + // not -fvisibility=* + if (T.isOSAIX()) + Opts.IgnoreXCOFFVisibility = 1; + else + Opts.setValueVisibilityMode(DefaultVisibility); } // The type-visibility mode defaults to the value-visibility mode. diff --git a/clang/test/Driver/ignore-xcoff-visibility.cpp b/clang/test/Driver/ignore-xcoff-visibility.cpp new file mode 100644 --- /dev/null +++ b/clang/test/Driver/ignore-xcoff-visibility.cpp @@ -0,0 +1,81 @@ +// RUN: %clang -target powerpc-unknown-aix -emit-llvm -o - -S %s |\ +// RUN: FileCheck --check-prefix=IGNOREVISIBILITY %s + +// RUN: %clang -target powerpc-unknown-linux -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY %s + +// RUN: %clang -mignore-xcoff-visibility -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=IGNOREVISIBILITY %s + +// RUN: not %clang -mignore-xcoff-visibility -target powerpc-unknown-linux -emit-llvm -o - -S %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s + +// RUN: %clang -fvisibility=default -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY %s + +// RUN: %clang -fvisibility=default -target powerpc-unknown-linux -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=VISIBILITY %s + +// RUN: %clang -mignore-xcoff-visibility -fvisibility=default -target powerpc-unknown-aix -emit-llvm -o - -S %s | \ +// RUN: FileCheck -check-prefix=IGNOREVISIBILITY %s + +// RUN: not %clang -mignore-xcoff-visibility -fvisibility=default -target powerpc-unknown-linux -emit-llvm -o - -S %s 2>&1 | \ +// RUN: FileCheck -check-prefix=ERROR %s + +__attribute__((visibility("hidden"))) void foo_h(int *p) { + (*p)++; +} + +__attribute__((visibility("protected"))) int b; + +extern __attribute__((visibility("hidden"))) void zoo_extern_h(void); + +void (*foo_p)(void) = zoo_extern_h; + +__attribute__((visibility("protected"))) void bar() { + foo_h(&b); + foo_p(); +} + +class TestClass { +public: + __attribute__((__visibility__("hidden"))) int value() const noexcept { return 0; } +}; + +int main() { + TestClass TC; + return TC.value(); +} + +template +class basic { +public: + __attribute__((__visibility__("protected"))) int getdata() { return 1; } +}; + +template class basic; + +#pragma GCC visibility push(hidden) +int pramb; +void prambar() {} +#pragma GCC visibility pop + +// IGNOREVISIBILITY: @b = global i32 0 +// IGNOREVISIBILITY: @pramb = global i32 0 +// IGNOREVISIBILITY: define void @_Z5foo_hPi(i32* %p) +// IGNOREVISIBILITY: declare void @_Z12zoo_extern_hv() +// IGNOREVISIBILITY: define void @_Z3barv() +// IGNOREVISIBILITY: define linkonce_odr i32 @_ZNK9TestClass5valueEv(%class.TestClass* %this) +// IGNOREVISIBILITY: define weak_odr i32 @_ZN5basicIiE7getdataEv(%class.basic* %this) +// IGNOREVISIBILITY: define void @_Z7prambarv() + +// VISIBILITY: @b = protected global i32 0 +// VISIBILITY: @pramb = hidden global i32 0 +// VISIBILITY: define hidden void @_Z5foo_hPi(i32* %p) +// VISIBILITY: declare hidden void @_Z12zoo_extern_hv() +// VISIBILITY: define protected void @_Z3barv() +// VISIBILITY: define linkonce_odr hidden i32 @_ZNK9TestClass5valueEv(%class.TestClass* %this) +// VISIBILITY: define weak_odr protected i32 @_ZN5basicIiE7getdataEv(%class.basic* %this) +// VISIBILITY: define hidden void @_Z7prambarv() + +// ERROR: unsupported option '-mignore-xcoff-visibility' for target 'powerpc-unknown-linux'