[clang] 415f7ee - [Clang] Add the ability to map DLL storage class to visibility

Ben Dunbobbin via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 2 09:08:33 PST 2020


Author: Ben Dunbobbin
Date: 2020-11-02T17:08:23Z
New Revision: 415f7ee8836944942d8beb70e982e95a312866a7

URL: https://github.com/llvm/llvm-project/commit/415f7ee8836944942d8beb70e982e95a312866a7
DIFF: https://github.com/llvm/llvm-project/commit/415f7ee8836944942d8beb70e982e95a312866a7.diff

LOG: [Clang] Add the ability to map DLL storage class to visibility

For PlayStation we offer source code compatibility with
Microsoft's dllimport/export annotations; however, our file
format is based on ELF.

To support this we translate from DLL storage class to ELF
visibility at the end of codegen in Clang.

Other toolchains have used similar strategies (e.g. see the
documentation for this ARM toolchain:

https://developer.arm.com/documentation/dui0530/i/migrating-from-rvct-v3-1-to-rvct-v4-0/changes-to-symbol-visibility-between-rvct-v3-1-and-rvct-v4-0)

This patch adds the ability to perform this translation. Options
are provided to support customizing the mapping behaviour.

Differential Revision: https://reviews.llvm.org/D89970

Added: 
    clang/test/CodeGenCXX/visibility-dllstorageclass.cpp
    clang/test/Driver/ps4-visibility-dllstorageclass.c
    clang/test/Driver/visibility-dllstorageclass.c

Modified: 
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Driver/Options.td
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/lib/Driver/ToolChains/Clang.cpp
    clang/lib/Driver/ToolChains/PS4CPU.cpp
    clang/lib/Frontend/CompilerInvocation.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def
index d711d66784a4..1d203f8489eb 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -307,6 +307,16 @@ ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility,
              "default visibility for types [-ftype-visibility]")
 LANGOPT(SetVisibilityForExternDecls, 1, 0,
         "apply global symbol visibility to external declarations without an explicit visibility")
+LANGOPT(VisibilityFromDLLStorageClass, 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,

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 057c2606c69d..33cfa72c0888 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -1973,6 +1973,15 @@ def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Gr
 def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>,
   HelpText<"Generate verbose assembly output">;
 def dA : Flag<["-"], "dA">, Alias<fverbose_asm>;
+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<f_Group>, Flags<[CC1Option]>,
+  HelpText<"The visibility for dllexport defintions [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">;
+def fvisibility_nodllstorageclass_EQ : Joined<["-"], "fvisibility-nodllstorageclass=">, Group<f_Group>, Flags<[CC1Option]>,
+  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<f_Group>, Flags<[CC1Option]>,
+  HelpText<"The visibility for dllimport external declarations [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">;
+def fvisibility_externs_nodllstorageclass_EQ : Joined<["-"], "fvisibility-externs-nodllstorageclass=">, Group<f_Group>, Flags<[CC1Option]>,
+  HelpText<"The visibility for external declarations without an explicit DLL dllstorageclass [-fvisibility-from-dllstorageclass]">, Values<"hidden,protected,default">;
 def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
   HelpText<"Set the default symbol visibility for all global declarations">, Values<"hidden,default">;
 def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,

diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 66a3c57b9112..9512b350d9fd 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -401,6 +401,41 @@ void InstrProfStats::reportDiagnostics(DiagnosticsEngine &Diags,
   }
 }
 
+static void setVisibilityFromDLLStorageClass(const clang::LangOptions &LO,
+                                             llvm::Module &M) {
+  if (!LO.VisibilityFromDLLStorageClass)
+    return;
+
+  llvm::GlobalValue::VisibilityTypes DLLExportVisibility =
+      CodeGenModule::GetLLVMVisibility(LO.getDLLExportVisibility());
+  llvm::GlobalValue::VisibilityTypes NoDLLStorageClassVisibility =
+      CodeGenModule::GetLLVMVisibility(LO.getNoDLLStorageClassVisibility());
+  llvm::GlobalValue::VisibilityTypes ExternDeclDLLImportVisibility =
+      CodeGenModule::GetLLVMVisibility(LO.getExternDeclDLLImportVisibility());
+  llvm::GlobalValue::VisibilityTypes ExternDeclNoDLLStorageClassVisibility =
+      CodeGenModule::GetLLVMVisibility(
+          LO.getExternDeclNoDLLStorageClassVisibility());
+
+  for (llvm::GlobalValue &GV : M.global_values()) {
+    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();
@@ -688,6 +723,12 @@ void CodeGenModule::Release() {
   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.
+  setVisibilityFromDLLStorageClass(LangOpts, getModule());
 }
 
 void CodeGenModule::EmitOpenCLMetadata() {

diff  --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 53d270917ed3..011e7dfe21c2 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5317,6 +5317,21 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
     }
   }
 
+  if (!RawTriple.isPS4())
+    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");
+        Args.AddLastArg(CmdArgs, options::OPT_fvisibility_dllexport_EQ);
+        Args.AddLastArg(CmdArgs, options::OPT_fvisibility_nodllstorageclass_EQ);
+        Args.AddLastArg(CmdArgs, options::OPT_fvisibility_externs_dllimport_EQ);
+        Args.AddLastArg(CmdArgs,
+                        options::OPT_fvisibility_externs_nodllstorageclass_EQ);
+      }
+    }
+
   if (const Arg *A = Args.getLastArg(options::OPT_mignore_xcoff_visibility)) {
     if (Triple.isOSAIX())
       CmdArgs.push_back("-mignore-xcoff-visibility");

diff  --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp
index fab1b2ac62df..383b0c50d410 100644
--- a/clang/lib/Driver/ToolChains/PS4CPU.cpp
+++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp
@@ -239,9 +239,8 @@ SanitizerMask toolchains::PS4CPU::getSupportedSanitizers() const {
 }
 
 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);
@@ -250,4 +249,36 @@ void toolchains::PS4CPU::addClangTargetOptions(
   }
 
   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 ||
+      A->getOption().matches(options::OPT_fvisibility_from_dllstorageclass)) {
+    CC1Args.push_back("-fvisibility-from-dllstorageclass");
+
+    if (DriverArgs.hasArg(options::OPT_fvisibility_dllexport_EQ))
+      DriverArgs.AddLastArg(CC1Args, options::OPT_fvisibility_dllexport_EQ);
+    else
+      CC1Args.push_back("-fvisibility-dllexport=protected");
+
+    if (DriverArgs.hasArg(options::OPT_fvisibility_nodllstorageclass_EQ))
+      DriverArgs.AddLastArg(CC1Args,
+                            options::OPT_fvisibility_nodllstorageclass_EQ);
+    else
+      CC1Args.push_back("-fvisibility-nodllstorageclass=hidden");
+
+    if (DriverArgs.hasArg(options::OPT_fvisibility_externs_dllimport_EQ))
+      DriverArgs.AddLastArg(CC1Args,
+                            options::OPT_fvisibility_externs_dllimport_EQ);
+    else
+      CC1Args.push_back("-fvisibility-externs-dllimport=default");
+
+    if (DriverArgs.hasArg(
+            options::OPT_fvisibility_externs_nodllstorageclass_EQ))
+      DriverArgs.AddLastArg(
+          CC1Args, options::OPT_fvisibility_externs_nodllstorageclass_EQ);
+    else
+      CC1Args.push_back("-fvisibility-externs-nodllstorageclass=default");
+  }
 }

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 3c0ba31527f7..7b8554c0fe49 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2814,6 +2814,38 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
   if (Args.hasArg(OPT_fapply_global_visibility_to_externs))
     Opts.SetVisibilityForExternDecls = 1;
 
+  if (Args.hasArg(OPT_fvisibility_from_dllstorageclass)) {
+    Opts.VisibilityFromDLLStorageClass = 1;
+
+    // Translate dllexport defintions to default visibility, by default.
+    if (Arg *O = Args.getLastArg(OPT_fvisibility_dllexport_EQ))
+      Opts.setDLLExportVisibility(parseVisibility(O, Args, Diags));
+    else
+      Opts.setDLLExportVisibility(DefaultVisibility);
+
+    // Translate defintions without an explict DLL storage class to hidden
+    // visibility, by default.
+    if (Arg *O = Args.getLastArg(OPT_fvisibility_nodllstorageclass_EQ))
+      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_EQ))
+      Opts.setExternDeclDLLImportVisibility(parseVisibility(O, Args, Diags));
+    else
+      Opts.setExternDeclDLLImportVisibility(DefaultVisibility);
+
+    // Translate external declarations without an explicit DLL storage class
+    // to hidden visibility, by default.
+    if (Arg *O = Args.getLastArg(OPT_fvisibility_externs_nodllstorageclass_EQ))
+      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.

diff  --git a/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp
new file mode 100644
index 000000000000..f090ccb3b099
--- /dev/null
+++ b/clang/test/CodeGenCXX/visibility-dllstorageclass.cpp
@@ -0,0 +1,70 @@
+// REQUIRES: x86-registered-target
+
+// Test that -fvisibility-from-dllstorageclass maps DLL storage class to visibility
+// and that it overrides the effect of visibility options and annotations.
+
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -fvisibility hidden \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -x c++ %s -S -emit-llvm -o - | \
+// RUN:   FileCheck %s --check-prefixes=DEFAULT
+
+// RUN: %clang_cc1 -triple x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -fvisibility hidden \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -fvisibility-dllexport=hidden \
+// RUN:     -fvisibility-nodllstorageclass=protected \
+// RUN:     -fvisibility-externs-dllimport=hidden \
+// RUN:     -fvisibility-externs-nodllstorageclass=protected \
+// RUN:     -x c++  %s -S -emit-llvm -o - | \
+// RUN:   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

diff  --git a/clang/test/Driver/ps4-visibility-dllstorageclass.c b/clang/test/Driver/ps4-visibility-dllstorageclass.c
new file mode 100644
index 000000000000..412024d4e5a9
--- /dev/null
+++ b/clang/test/Driver/ps4-visibility-dllstorageclass.c
@@ -0,0 +1,128 @@
+// Check behaviour of -fvisibility-from-dllstorageclass options for PS4
+
+// RUN: %clang -### -target x86_64-scei-ps4 %s -Werror -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefixes=DEFAULTS,DEFAULTS1 \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// RUN: %clang -### -target x86_64-scei-ps4 \
+// RUN:     -fno-visibility-from-dllstorageclass \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -Werror \
+// RUN:     %s -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefixes=DEFAULTS,DEFAULTS2 \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// DEFAULTS:      "-fvisibility-from-dllstorageclass"
+// DEFAULTS-SAME: "-fvisibility-dllexport=protected"
+// DEFAULTS-SAME: "-fvisibility-nodllstorageclass=hidden"
+// DEFAULTS-SAME: "-fvisibility-externs-dllimport=default"
+// DEFAULTS-SAME: "-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=UNUSED \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass \
+// RUN:     --implicit-check-not=warning:
+
+// UNUSED:      clang: warning: argument unused during compilation: '-fvisibility-dllexport=hidden'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-nodllstorageclass=protected'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-externs-dllimport=hidden'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-externs-nodllstorageclass=protected'
+
+// RUN: %clang -### -target x86_64-scei-ps4 \
+// RUN:     -fvisibility-nodllstorageclass=protected \
+// RUN:     -fvisibility-externs-dllimport=hidden \
+// RUN:     -Werror \
+// RUN:     %s -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=SOME \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// SOME1:      "-fvisibility-from-dllstorageclass"
+// SOME1-SAME: "-fvisibility-dllexport=protected"
+// SOME1-SAME: "-fvisibility-nodllstorageclass=protected"
+// SOME1-SAME: "-fvisibility-externs-dllimport=hidden"
+// SOME1-SAME: "-fvisibility-externs-nodllstorageclass=default"
+
+// RUN: %clang -### -target x86_64-scei-ps4 \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -fvisibility-nodllstorageclass=protected \
+// RUN:     -fvisibility-externs-dllimport=hidden \
+// RUN:     -Werror \
+// RUN:     %s -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=SOME \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// SOME:      "-fvisibility-from-dllstorageclass"
+// SOME-SAME: "-fvisibility-dllexport=protected"
+// SOME-SAME: "-fvisibility-nodllstorageclass=protected"
+// SOME-SAME: "-fvisibility-externs-dllimport=hidden"
+// SOME-SAME: "-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:     -Werror \
+// RUN:     %s -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=ALL \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// 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:     -Werror \
+// RUN:     %s -o - 2>&1 | \
+// RUN:   FileCheck %s -check-prefix=ALL \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// ALL:      "-fvisibility-from-dllstorageclass"
+// ALL-SAME: "-fvisibility-dllexport=hidden"
+// ALL-SAME: "-fvisibility-nodllstorageclass=protected"
+// ALL-SAME: "-fvisibility-externs-dllimport=hidden"
+// ALL-SAME: "-fvisibility-externs-nodllstorageclass=protected"

diff  --git a/clang/test/Driver/visibility-dllstorageclass.c b/clang/test/Driver/visibility-dllstorageclass.c
new file mode 100644
index 000000000000..1ad2e5452f23
--- /dev/null
+++ b/clang/test/Driver/visibility-dllstorageclass.c
@@ -0,0 +1,87 @@
+// Check behaviour of -fvisibility-from-dllstorageclass options
+
+// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -Werror -S -### %s 2>&1 | \
+// RUN:   FileCheck %s \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -fno-visibility-from-dllstorageclass \
+// RUN:     -Werror -S -### %s 2>&1 | \
+// RUN:   FileCheck %s \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -fno-visibility-from-dllstorageclass \
+// RUN:     -fvisibility-from-dllstorageclass \
+// RUN:     -Werror -S -### %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefix=SET \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass
+
+// 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 \
+// RUN:     -S -### %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefixes=UNUSED \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass \
+// RUN:     --implicit-check-not=error: \
+// RUN:     --implicit-check-not=warning:
+
+// RUN: %clang -target x86_64-unknown-windows-itanium -fdeclspec \
+// RUN:     -fno-visibility-from-dllstorageclass \
+// RUN:     -fvisibility-dllexport=hidden \
+// RUN:     -fvisibility-nodllstorageclass=protected \
+// RUN:     -fvisibility-externs-dllimport=hidden \
+// RUN:     -fvisibility-externs-nodllstorageclass=protected \
+// RUN:     -S -### %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefixes=UNUSED \
+// RUN:     --implicit-check-not=-fvisibility-from-dllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-dllexport \
+// RUN:     --implicit-check-not=-fvisibility-nodllstorageclass \
+// RUN:     --implicit-check-not=-fvisibility-externs-dllimport \
+// RUN:     --implicit-check-not=-fvisibility-externs-nodllstorageclass \
+// RUN:     --implicit-check-not=error: \
+// RUN:     --implicit-check-not=warning:
+
+// UNUSED:      clang: warning: argument unused during compilation: '-fvisibility-dllexport=hidden'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-nodllstorageclass=protected'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-externs-dllimport=hidden'
+// UNUSED-NEXT: clang: warning: argument unused during compilation: '-fvisibility-externs-nodllstorageclass=protected'
+
+// 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 \
+// RUN:     -Werror -S -### %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefixes=SET,ALL
+
+// SET:      "-fvisibility-from-dllstorageclass"
+// ALL-SAME: "-fvisibility-dllexport=hidden"
+// ALL-SAME: "-fvisibility-nodllstorageclass=protected"
+// ALL-SAME: "-fvisibility-externs-dllimport=hidden"
+// ALL-SAME: "-fvisibility-externs-nodllstorageclass=protected"


        


More information about the cfe-commits mailing list