Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -306,6 +306,16 @@ "default visibility for types [-ftype-visibility]") LANGOPT(SetVisibilityForExternDecls, 1, 0, "apply global symbol visibility to external declarations without an explicit visibility") +LANGOPT(VisibilityDLLStorageClass, 1, 0, + "Set the visiblity of globals from their DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(DLLExportVisibility, Visibility, 3, DefaultVisibility, + "Visibility for functions and variables with dllexport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(NoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "Visibility for functions and variables without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclDLLImportVisibility, Visibility, 3, DefaultVisibility, + "Visibility for external declarations with dllimport annotations [-fvisibility-from-dllstorageclass]") +ENUM_LANGOPT(ExternDeclNoDLLStorageClassVisibility, Visibility, 3, HiddenVisibility, + "Visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]") BENIGN_LANGOPT(SemanticInterposition , 1, 0, "semantic interposition") BENIGN_LANGOPT(ExplicitNoSemanticInterposition, 1, 0, "explicitly no semantic interposition") ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1956,6 +1956,15 @@ def fverbose_asm : Flag<["-"], "fverbose-asm">, Group, HelpText<"Generate verbose assembly output">; def dA : Flag<["-"], "dA">, Alias; +defm visibility_from_dllstorageclass : OptInFFlag<"visibility-from-dllstorageclass", "Set the visiblity of symbols in the generated code from their DLL storage class">; +def fvisibility_dllexport_EQ : Joined<["-"], "fvisibility-dllexport=">, Group, + HelpText<"The visibility for dllexport defintions [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group, + HelpText<"The visibility for defintiions without an explicit DLL export class [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_dllimport_EQ : Joined<["-"], "fvisibility-externs-dllimport=">, Group, + HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; +def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group, + HelpText<"The visibility for external declarations without an explicit DLL dllstorageclass [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">; 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, @@ -4280,6 +4289,14 @@ HelpText<"Default type visibility">; def fapply_global_visibility_to_externs : Flag<["-"], "fapply-global-visibility-to-externs">, HelpText<"Apply global symbol visibility to external declarations without an explicit visibility">; +def fvisibility_dllexport : Separate<["-"], "fvisibility-dllexport">, + HelpText<"The visibility for dllexport definitions [-fvisibility-from-dllstorageclass]">; +def fvisibility_nodllstorageclass : Separate<["-"], "fvisibility-nodllstorageclass">, + HelpText<"The visibility for definitions without an explicit DLL storage class [-fvisibility-from-dllstorageclass]">; +def fvisibility_externs_dllimport : Separate<["-"], "fvisibility-externs-dllimport">, + HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">; +def fvisibility_externs_nodllstorageclass : Separate<["-"], "fvisibility-externs-nodllstorageclass">, + HelpText<"The visibility for external declarations without an explicit DLL storage class [-fvisibility-from-dllstorageclass]">; def ftemplate_depth : Separate<["-"], "ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; def foperator_arrow_depth : Separate<["-"], "foperator-arrow-depth">, Index: clang/lib/CodeGen/CodeGenModule.cpp =================================================================== --- clang/lib/CodeGen/CodeGenModule.cpp +++ clang/lib/CodeGen/CodeGenModule.cpp @@ -401,6 +401,30 @@ } } +static void translateDLLStorageClass( + llvm::GlobalValue &GV, + llvm::GlobalValue::VisibilityTypes DLLExportVisibility, + llvm::GlobalValue::VisibilityTypes NoDLLStorageClassVisibility, + llvm::GlobalValue::VisibilityTypes ExternDeclDLLImportVisibility, + llvm::GlobalValue::VisibilityTypes ExternDeclNoDLLStorageClassVisibility) { + if (GV.hasAppendingLinkage() || GV.hasLocalLinkage()) + return; + + if (GV.isDeclarationForLinker()) { + GV.setVisibility(GV.getDLLStorageClass() == + llvm::GlobalValue::DLLImportStorageClass + ? ExternDeclDLLImportVisibility + : ExternDeclNoDLLStorageClassVisibility); + } else { + GV.setVisibility(GV.getDLLStorageClass() == + llvm::GlobalValue::DLLExportStorageClass + ? DLLExportVisibility + : NoDLLStorageClassVisibility); + } + + GV.setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass); +} + void CodeGenModule::Release() { EmitDeferred(); EmitVTablesOpportunistically(); @@ -681,6 +705,37 @@ getTargetCodeGenInfo().emitTargetMetadata(*this, MangledDeclNames); EmitBackendOptionsMetadata(getCodeGenOpts()); + + // Set visibility from DLL export class + // We do this at the end of LLVM IR generation; after any operation + // that might affect the DLL storage class or the visibility, and + // before anything that might act on these. + if (LangOpts.VisibilityDLLStorageClass) { + llvm::GlobalValue::VisibilityTypes DLLExportVisibility = + GetLLVMVisibility(getLangOpts().getDLLExportVisibility()); + llvm::GlobalValue::VisibilityTypes NoDLLStorageClassVisibility = + GetLLVMVisibility(getLangOpts().getNoDLLStorageClassVisibility()); + llvm::GlobalValue::VisibilityTypes ExternDeclDLLImportVisibility = + GetLLVMVisibility(getLangOpts().getExternDeclDLLImportVisibility()); + llvm::GlobalValue::VisibilityTypes ExternDeclNoDLLStorageClassVisibility = + GetLLVMVisibility(getLangOpts().getExternDeclNoDLLStorageClassVisibility()); + + auto &M = getModule(); + for (llvm::Function &F : M.functions()) + translateDLLStorageClass(F, DLLExportVisibility, NoDLLStorageClassVisibility, + ExternDeclDLLImportVisibility, + ExternDeclNoDLLStorageClassVisibility); + + for (llvm::GlobalVariable &GV : M.globals()) + translateDLLStorageClass(GV, DLLExportVisibility, NoDLLStorageClassVisibility, + ExternDeclDLLImportVisibility, + ExternDeclNoDLLStorageClassVisibility); + + for (llvm::GlobalAlias &GA : M.aliases()) + translateDLLStorageClass(GA, DLLExportVisibility, NoDLLStorageClassVisibility, + ExternDeclDLLImportVisibility, + ExternDeclNoDLLStorageClassVisibility); + } } void CodeGenModule::EmitOpenCLMetadata() { Index: clang/lib/Driver/ToolChains/Clang.cpp =================================================================== --- clang/lib/Driver/ToolChains/Clang.cpp +++ clang/lib/Driver/ToolChains/Clang.cpp @@ -5228,6 +5228,38 @@ } } + if (const Arg *A = + Args.getLastArg(options::OPT_fvisibility_from_dllstorageclass, + options::OPT_fno_visibility_from_dllstorageclass)) { + if (A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) { + CmdArgs.push_back("-fvisibility-from-dllstorageclass"); + + if (const Arg *E = + Args.getLastArg(options::OPT_fvisibility_dllexport_EQ)) { + CmdArgs.push_back("-fvisibility-dllexport"); + CmdArgs.push_back(E->getValue()); + } + + if (const Arg *E = + Args.getLastArg(options::OPT_fvisibility_nodllstorageclass_EQ)) { + CmdArgs.push_back("-fvisibility-nodllstorageclass"); + CmdArgs.push_back(E->getValue()); + } + + if (const Arg *E = + Args.getLastArg(options::OPT_fvisibility_externs_dllimport_EQ)) { + CmdArgs.push_back("-fvisibility-externs-dllimport"); + CmdArgs.push_back(E->getValue()); + } + + if (const Arg *E = Args.getLastArg( + options::OPT_fvisibility_externs_nodllstorageclass_EQ)) { + CmdArgs.push_back("-fvisibility-externs-nodllstorageclass"); + CmdArgs.push_back(E->getValue()); + } + } + } + Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden_static_local_var, options::OPT_fno_visibility_inlines_hidden_static_local_var); Index: clang/lib/Driver/ToolChains/PS4CPU.cpp =================================================================== --- clang/lib/Driver/ToolChains/PS4CPU.cpp +++ clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -237,9 +237,8 @@ } void toolchains::PS4CPU::addClangTargetOptions( - const ArgList &DriverArgs, - ArgStringList &CC1Args, - Action::OffloadKind DeviceOffloadingKind) const { + const ArgList &DriverArgs, ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadingKind) const { // PS4 does not use init arrays. if (DriverArgs.hasArg(options::OPT_fuse_init_array)) { Arg *A = DriverArgs.getLastArg(options::OPT_fuse_init_array); @@ -248,4 +247,51 @@ } CC1Args.push_back("-fno-use-init-array"); + + const Arg *A = + DriverArgs.getLastArg(options::OPT_fvisibility_from_dllstorageclass, + options::OPT_fno_visibility_from_dllstorageclass); + if (!A) { + CC1Args.push_back("-fvisibility-from-dllstorageclass"); + + CC1Args.push_back("-fvisibility-dllexport"); + if (const Arg *E = + DriverArgs.getLastArg(options::OPT_fvisibility_dllexport_EQ)) { + CC1Args.push_back(E->getValue()); + } else { + CC1Args.push_back("protected"); + } + + CC1Args.push_back("-fvisibility-externs-nodllstorageclass"); + if (const Arg *E = DriverArgs.getLastArg( + options::OPT_fvisibility_externs_nodllstorageclass_EQ)) { + CC1Args.push_back(E->getValue()); + } else { + CC1Args.push_back("default"); + } + + if (const Arg *E = DriverArgs.getLastArg( + options::OPT_fvisibility_nodllstorageclass_EQ)) { + CC1Args.push_back("-fvisibility-nodllstorageclass"); + CC1Args.push_back(E->getValue()); + } + + if (const Arg *E = DriverArgs.getLastArg( + options::OPT_fvisibility_externs_dllimport_EQ)) { + CC1Args.push_back("-fvisibility-externs-dllimport"); + CC1Args.push_back(E->getValue()); + } + } else if (!A->getOption().matches( + options::OPT_fno_visibility_from_dllstorageclass)) { + if (!DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ)) { + CC1Args.push_back("-fvisibility-dllexport"); + CC1Args.push_back("protected"); + } + + if (!DriverArgs.hasArg( + options::OPT_fvisibility_externs_nodllstorageclass_EQ)) { + CC1Args.push_back("-fvisibility-externs-nodllstorageclass"); + CC1Args.push_back("default"); + } + } } Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -2783,6 +2783,42 @@ if (Args.hasArg(OPT_fapply_global_visibility_to_externs)) Opts.SetVisibilityForExternDecls = 1; + if (Args.hasArg(OPT_fvisibility_from_dllstorageclass)) { + Opts.VisibilityDLLStorageClass = 1; + + // Translate defintions to default visibility by default. + if (Arg *O = Args.getLastArg(OPT_fvisibility_dllexport)) { + Opts.setDLLExportVisibility(parseVisibility(O, Args, Diags)); + } else { + Opts.setDLLExportVisibility(DefaultVisibility); + } + + // Translate defintions without an explict DLL export class to default + // visibility by default. + if (Arg *O = Args.getLastArg(OPT_fvisibility_nodllstorageclass)) { + Opts.setNoDLLStorageClassVisibility(parseVisibility(O, Args, Diags)); + } else { + Opts.setNoDLLStorageClassVisibility(HiddenVisibility); + } + + // Translate dllimport external declarations to default visibility by + // default. + if (Arg *O = Args.getLastArg(OPT_fvisibility_externs_dllimport)) { + Opts.setExternDeclDLLImportVisibility(parseVisibility(O, Args, Diags)); + } else { + Opts.setExternDeclDLLImportVisibility(DefaultVisibility); + } + + // Translate external declarations without an explicit DLL export class + // to hidden visibility by default. + if (Arg *O = Args.getLastArg(OPT_fvisibility_externs_nodllstorageclass)) { + Opts.setExternDeclNoDLLStorageClassVisibility( + parseVisibility(O, Args, Diags)); + } else { + Opts.setExternDeclNoDLLStorageClassVisibility(HiddenVisibility); + } + } + if (Args.hasArg(OPT_ftrapv)) { Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping); // Set the handler, if one is specified. Index: clang/test/CodeGenCXX/visibility-dllstorageclass.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/visibility-dllstorageclass.cpp @@ -0,0 +1,57 @@ +// REQUIRES: x86-registered-target + +// Test that -fvisibility-from-dllstorageclass translates export class into visibility +// and that it overrides the effect of visibility options and annotations. + +// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fvisibility-from-dllstorageclass -fdeclspec -fvisibility hidden -x c++ %s -S -emit-llvm -o - | FileCheck %s --check-prefixes=DEFAULT +// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fvisibility-from-dllstorageclass -fvisibility-dllexport hidden -fvisibility-nodllstorageclass protected -fvisibility-externs-dllimport hidden -fvisibility-externs-nodllstorageclass protected -fdeclspec -x c++ %s -S -emit-llvm -o - | FileCheck %s --check-prefixes=EXPLICIT + +// Function +void f() {} +void __declspec(dllexport) exported_f() {} +// DEFAULT-DAG: define hidden void @_Z1fv() +// DEFAULT-DAG: define dso_local void @_Z10exported_fv() +// EXPLICIT-DAG: define protected void @_Z1fv() +// EXPLICIT-DAG: define hidden void @_Z10exported_fv() + +// Variable +int d = 123; +__declspec(dllexport) int exported_d = 123; +// DEFAULT-DAG: @d = hidden global +// DEFAULT-DAG: @exported_d = dso_local global +// EXPLICIT-DAG: @d = protected global +// EXPLICIT-DAG: @exported_d = hidden global + +// Alias +extern "C" void aliased() {} +void a() __attribute__((alias("aliased"))); +void __declspec(dllexport) a_exported() __attribute__((alias("aliased"))); +// DEFAULT-DAG: @_Z1av = hidden alias +// DEFAULT-DAG: @_Z10a_exportedv = dso_local alias +// EXPLICIT-DAG: @_Z1av = protected alias +// EXPLICIT-DAG: @_Z10a_exportedv = hidden alias + +// Declaration +extern void e(); +extern void __declspec(dllimport) imported_e(); +void use_declarations(){e(); imported_e();} +// DEFAULT-DAG: declare hidden void @_Z1ev() +// DEFAULT-DAG: declare void @_Z10imported_ev() +// EXPLICIT-DAG: declare protected void @_Z1ev() +// EXPLICIT-DAG: declare hidden void @_Z10imported_ev() + +// Show that -fvisibility-from-dllstorageclass overrides the effect of visibility annotations. + +struct __attribute__((type_visibility("protected"))) t { + virtual void foo(); +}; +void t::foo() {} +// DEFAULT-DAG: @_ZTV1t = hidden unnamed_addr constant + +int v __attribute__ ((__visibility__ ("protected"))) = 123; +// DEFAULT-DAG: @v = hidden global + +#pragma GCC visibility push(protected) +int p = 345; +#pragma GCC visibility pop +// DEFAULT-DAG: @p = hidden global Index: clang/test/Driver/ps4-visibility-dllstorageclass.c =================================================================== --- /dev/null +++ clang/test/Driver/ps4-visibility-dllstorageclass.c @@ -0,0 +1,77 @@ +// REQUIRES: x86-registered-target + +// RUN: %clang -### -target x86_64-scei-ps4 %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=SET --implicit-check-not="-fvisibility-nodllstorageclass" --implicit-check-not="-fvisibility-externs-dllimport" + +// RUN: %clang -### -target x86_64-scei-ps4 -fno-visibility-from-dllstorageclass -fvisibility-from-dllstorageclass %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=SET + +// SET-DAG: "-fvisibility-from-dllstorageclass" +// SET-DAG: "-fvisibility-dllexport" "protected" +// SET-DAG: "-fvisibility-externs-nodllstorageclass" "default" + +// RUN: %clang -### -target x86_64-scei-ps4 \ +// RUN: -fvisibility-from-dllstorageclass \ +// RUN: -fvisibility-dllexport=hidden \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: -fvisibility-externs-nodllstorageclass=protected \ +// RUN: -fno-visibility-from-dllstorageclass \ +// RUN: %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=NONE + +// NONE-NOT: "-fvisibility-from-dllstorageclass" +// NONE-NOT: "-fvisibility-dllexport" +// NONE-NOT: "-fvisibility-nodllstorageclass" +// NONE-NOT: "-fvisibility-externs-dllimport" +// NONE-NOT: "-fvisibility-externs-nodllstorageclass" + +// RUN: %clang -### -target x86_64-scei-ps4 \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=DEFAULTS + +// RUN: %clang -### -target x86_64-scei-ps4 \ +// RUN: -fvisibility-from-dllstorageclass \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=DEFAULTS + +// DEFAULTS-DAG: "-fvisibility-from-dllstorageclass" +// DEFAULTS-DAG: "-fvisibility-dllexport" "protected" +// DEFAULTS-DAG: "-fvisibility-nodllstorageclass" "protected" +// DEFAULTS-DAG: "-fvisibility-externs-dllimport" "hidden" +// DEFAULTS-DAG: "-fvisibility-externs-nodllstorageclass" "default" + +// RUN: %clang -### -target x86_64-scei-ps4 \ +// RUN: -fvisibility-dllexport=default \ +// RUN: -fvisibility-dllexport=hidden \ +// RUN: -fvisibility-nodllstorageclass=default \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=default \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: -fvisibility-externs-nodllstorageclass=default \ +// RUN: -fvisibility-externs-nodllstorageclass=protected \ +// RUN: %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=ALL + +// RUN: %clang -### -target x86_64-scei-ps4 \ +// RUN: -fvisibility-from-dllstorageclass \ +// RUN: -fvisibility-dllexport=default \ +// RUN: -fvisibility-dllexport=hidden \ +// RUN: -fvisibility-nodllstorageclass=default \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=default \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: -fvisibility-externs-nodllstorageclass=default \ +// RUN: -fvisibility-externs-nodllstorageclass=protected \ +// RUN: %s -o - 2>&1 | \ +// RUN: FileCheck %s -check-prefix=ALL + +// ALL-DAG: "-fvisibility-from-dllstorageclass" +// ALL-DAG: "-fvisibility-dllexport" "hidden" +// ALL-DAG: "-fvisibility-nodllstorageclass" "protected" +// ALL-DAG: "-fvisibility-externs-dllimport" "hidden" +// ALL-DAG: "-fvisibility-externs-nodllstorageclass" "protected" Index: clang/test/Driver/visibility-dllstorageclass.c =================================================================== --- /dev/null +++ clang/test/Driver/visibility-dllstorageclass.c @@ -0,0 +1,42 @@ +// REQUIRES: x86-registered-target + +// Check behaviour of -fvisibility-from-dllstorageclass options + +// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec -S -### %s 2>&1 | FileCheck %s --check-prefixes=NONE,SHARED + +// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec -fvisibility-from-dllstorageclass -fno-visibility-from-dllstorageclass -S -### %s 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=NONE,SHARED + +// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec -fno-visibility-from-dllstorageclass -fvisibility-from-dllstorageclass -S -### %s 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=SET,SHARED + +// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \ +// RUN: -fvisibility-dllexport=hidden \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: -fvisibility-externs-nodllstorageclass=protected -S -### %s 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=NONE,SHARED + +// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \ +// RUN: -fvisibility-from-dllstorageclass \ +// RUN: -fvisibility-dllexport=default \ +// RUN: -fvisibility-dllexport=hidden \ +// RUN: -fvisibility-nodllstorageclass=default \ +// RUN: -fvisibility-nodllstorageclass=protected \ +// RUN: -fvisibility-externs-dllimport=default \ +// RUN: -fvisibility-externs-dllimport=hidden \ +// RUN: -fvisibility-externs-nodllstorageclass=default \ +// RUN: -fvisibility-externs-nodllstorageclass=protected -S -### %s 2>&1 | \ +// RUN: FileCheck %s --check-prefixes=SET,ALL + +// NONE-NOT: "-fvisibility-from-dllstorageclass" +// SHARED-NOT: "-fvisibility-dllexport" "hidden" +// SHARED-NOT: "-fvisibility-nodllstorageclass" "protected" +// SHARED-NOT: "-fvisibility-externs-dllimport" "hidden" +// SHARED-NOT: "-fvisibility-externs-nodllstorageclass" "protected" + +// SET: "-fvisibility-from-dllstorageclass" +// ALL-DAG: "-fvisibility-dllexport" "hidden" +// ALL-DAG: "-fvisibility-nodllstorageclass" "protected" +// ALL-DAG: "-fvisibility-externs-dllimport" "hidden" +// ALL-DAG: "-fvisibility-externs-nodllstorageclass" "protected"