r175480 - Add support for -fvisibility-ms-compat.

John McCall rjmccall at apple.com
Mon Feb 18 17:57:35 PST 2013


Author: rjmccall
Date: Mon Feb 18 19:57:35 2013
New Revision: 175480

URL: http://llvm.org/viewvc/llvm-project?rev=175480&view=rev
Log:
Add support for -fvisibility-ms-compat.

We treat this as an alternative to -fvisibility=<?>
which changes the default value visibility to "hidden"
and the default type visibility to "default".

Expose a -cc1 option for changing the default type
visibility, repurposing -fvisibility as the default
value visibility option (also setting type visibility
from it in the absence of a specific option).

rdar://13079314

Added:
    cfe/trunk/test/CodeGenCXX/visibility-ms-compat.cpp
    cfe/trunk/test/Driver/visibility.cpp
Modified:
    cfe/trunk/include/clang/Basic/LangOptions.def
    cfe/trunk/include/clang/Driver/CC1Options.td
    cfe/trunk/include/clang/Driver/Options.td
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Driver/Tools.cpp
    cfe/trunk/lib/Frontend/CompilerInvocation.cpp

Modified: cfe/trunk/include/clang/Basic/LangOptions.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/LangOptions.def?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/LangOptions.def (original)
+++ cfe/trunk/include/clang/Basic/LangOptions.def Mon Feb 18 19:57:35 2013
@@ -147,8 +147,10 @@ BENIGN_LANGOPT(DelayedTemplateParsing ,
 LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime")
 
 ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode")
-ENUM_LANGOPT(VisibilityMode, Visibility, 3, DefaultVisibility, 
-             "symbol visibility")
+ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility, 
+             "value symbol visibility")
+ENUM_LANGOPT(TypeVisibilityMode, Visibility, 3, DefaultVisibility, 
+             "type symbol visibility")
 ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, 
              "stack protector mode")
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Mon Feb 18 19:57:35 2013
@@ -415,7 +415,9 @@ def stack_protector : Separate<["-"], "s
 def stack_protector_buffer_size : Separate<["-"], "stack-protector-buffer-size">,
   HelpText<"Lower bound for a buffer to be considered for stack protection">;
 def fvisibility : Separate<["-"], "fvisibility">,
-  HelpText<"Default symbol visibility">;
+  HelpText<"Default type and symbol visibility">;
+def ftype_visibility : Separate<["-"], "ftype-visibility">,
+  HelpText<"Default type visibility">;
 def ftemplate_depth : Separate<["-"], "ftemplate-depth">,
   HelpText<"Maximum depth of recursive template instantiation">;
 def fconstexpr_depth : Separate<["-"], "fconstexpr-depth">,

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Mon Feb 18 19:57:35 2013
@@ -723,10 +723,14 @@ def fuse_cxa_atexit : Flag<["-"], "fuse-
 def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Use .init_array instead of .ctors">;
 def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>;
-def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>;
+def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>,
+  HelpText<"Set the default symbol visibility for all global declarations">;
 def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>,
   HelpText<"Give inline C++ member functions default visibility by default">,
   Flags<[CC1Option]>;
+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 fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Treat signed integer overflow as two's complement">;
 def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>,

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Feb 18 19:57:35 2013
@@ -80,7 +80,9 @@ typedef NamedDecl::LinkageInfo LinkageIn
 /// Is the given declaration a "type" or a "value" for the purposes of
 /// visibility computation?
 static bool usesTypeVisibility(const NamedDecl *D) {
-  return isa<TypeDecl>(D) || isa<ClassTemplateDecl>(D);
+  return isa<TypeDecl>(D) ||
+         isa<ClassTemplateDecl>(D) ||
+         isa<ObjCInterfaceDecl>(D);
 }
 
 /// Return the explicit visibility of the given declaration.
@@ -440,10 +442,15 @@ static LinkageInfo getLVForNamespaceScop
 
     // Add in global settings if the above didn't give us direct visibility.
     if (!LV.visibilityExplicit()) {
-      // FIXME: type visibility
-      LV.mergeVisibility(Context.getLangOpts().getVisibilityMode(),
-                         /*explicit*/ false);
-
+      // Use global type/value visibility as appropriate.
+      Visibility globalVisibility;
+      if (computation == LVForValue) {
+        globalVisibility = Context.getLangOpts().getValueVisibilityMode();
+      } else {
+        assert(computation == LVForType);
+        globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
+      }
+      LV.mergeVisibility(globalVisibility, /*explicit*/ false);
 
       // If we're paying attention to global visibility, apply
       // -finline-visibility-hidden if this is an inline method.

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Mon Feb 18 19:57:35 2013
@@ -2523,9 +2523,19 @@ void Clang::ConstructJob(Compilation &C,
     CmdArgs.push_back(Args.MakeArgString(Twine(N)));
   }
 
-  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ)) {
-    CmdArgs.push_back("-fvisibility");
-    CmdArgs.push_back(A->getValue());
+  // -fvisibility= and -fvisibility-ms-compat are of a piece.
+  if (const Arg *A = Args.getLastArg(options::OPT_fvisibility_EQ,
+                                     options::OPT_fvisibility_ms_compat)) {
+    if (A->getOption().matches(options::OPT_fvisibility_EQ)) {
+      CmdArgs.push_back("-fvisibility");
+      CmdArgs.push_back(A->getValue());
+    } else {
+      assert(A->getOption().matches(options::OPT_fvisibility_ms_compat));
+      CmdArgs.push_back("-fvisibility");
+      CmdArgs.push_back("hidden");
+      CmdArgs.push_back("-ftype-visibility");
+      CmdArgs.push_back("default");
+    }
   }
 
   Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden);

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=175480&r1=175479&r2=175480&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Mon Feb 18 19:57:35 2013
@@ -1001,6 +1001,24 @@ void CompilerInvocation::setLangDefaults
   Opts.DollarIdents = !Opts.AsmPreprocessor;
 }
 
+/// Attempt to parse a visibility value out of the given argument.
+static Visibility parseVisibility(Arg *arg, ArgList &args,
+                                  DiagnosticsEngine &diags) {
+  StringRef value = arg->getValue();
+  if (value == "default") {
+    return DefaultVisibility;
+  } else if (value == "hidden") {
+    return HiddenVisibility;
+  } else if (value == "protected") {
+    // FIXME: diagnose if target does not support protected visibility
+    return ProtectedVisibility;
+  }
+
+  diags.Report(diag::err_drv_invalid_value)
+    << arg->getAsString(args) << value;
+  return DefaultVisibility;
+}
+
 static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
                           DiagnosticsEngine &Diags) {
   // FIXME: Cleanup per-file based stuff.
@@ -1132,17 +1150,19 @@ static void ParseLangArgs(LangOptions &O
   if (Args.hasArg(OPT_fdelayed_template_parsing))
     Opts.DelayedTemplateParsing = 1;
 
-  StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
-  if (Vis == "default")
-    Opts.setVisibilityMode(DefaultVisibility);
-  else if (Vis == "hidden")
-    Opts.setVisibilityMode(HiddenVisibility);
-  else if (Vis == "protected")
-    // FIXME: diagnose if target does not support protected visibility
-    Opts.setVisibilityMode(ProtectedVisibility);
-  else
-    Diags.Report(diag::err_drv_invalid_value)
-      << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
+  // The value-visibility mode defaults to "default".
+  if (Arg *visOpt = Args.getLastArg(OPT_fvisibility)) {
+    Opts.setValueVisibilityMode(parseVisibility(visOpt, Args, Diags));
+  } else {
+    Opts.setValueVisibilityMode(DefaultVisibility);
+  }
+
+  // The type-visibility mode defaults to the value-visibility mode.
+  if (Arg *typeVisOpt = Args.getLastArg(OPT_ftype_visibility)) {
+    Opts.setTypeVisibilityMode(parseVisibility(typeVisOpt, Args, Diags));
+  } else {
+    Opts.setTypeVisibilityMode(Opts.getValueVisibilityMode());
+  }
 
   if (Args.hasArg(OPT_fvisibility_inlines_hidden))
     Opts.InlineVisibilityHidden = 1;

Added: cfe/trunk/test/CodeGenCXX/visibility-ms-compat.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility-ms-compat.cpp?rev=175480&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/visibility-ms-compat.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/visibility-ms-compat.cpp Mon Feb 18 19:57:35 2013
@@ -0,0 +1,112 @@
+// RUN: %clang_cc1 %s -std=c++11 -triple=x86_64-apple-darwin10 -fvisibility hidden -ftype-visibility default -emit-llvm -o %t
+// RUN: FileCheck %s < %t
+// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s < %t
+
+// The two visibility options above are how we translate
+// -fvisibility-ms-compat in the driver.
+
+// rdar://13079314
+
+#define HIDDEN __attribute__((visibility("hidden")))
+#define PROTECTED __attribute__((visibility("protected")))
+#define DEFAULT __attribute__((visibility("default")))
+
+namespace std {
+  class type_info;
+};
+
+namespace test0 {
+  struct A {
+    static void foo();
+    static void bar();
+  };
+
+  void A::foo() { bar(); }
+  // CHECK: define hidden void @_ZN5test01A3fooEv()
+  // CHECK: declare void @_ZN5test01A3barEv()
+
+  const std::type_info &ti = typeid(A);
+  // CHECK-GLOBAL: @_ZTSN5test01AE = linkonce_odr constant
+  // CHECK-GLOBAL: @_ZTIN5test01AE = linkonce_odr unnamed_addr constant
+  // CHECK-GLOBAL: @_ZN5test02tiE = hidden constant
+}
+
+namespace test1 {
+  struct HIDDEN A {
+    static void foo();
+    static void bar();
+  };
+
+  void A::foo() { bar(); }
+  // CHECK: define hidden void @_ZN5test11A3fooEv()
+  // CHECK: declare hidden void @_ZN5test11A3barEv()
+
+  const std::type_info &ti = typeid(A);
+  // CHECK-GLOBAL: @_ZTSN5test11AE = linkonce_odr hidden constant
+  // CHECK-GLOBAL: @_ZTIN5test11AE = linkonce_odr hidden unnamed_addr constant
+  // CHECK-GLOBAL: @_ZN5test12tiE = hidden constant
+}
+
+namespace test2 {
+  struct DEFAULT A {
+    static void foo();
+    static void bar();
+  };
+
+  void A::foo() { bar(); }
+  // CHECK: define void @_ZN5test21A3fooEv()
+  // CHECK: declare void @_ZN5test21A3barEv()
+
+  const std::type_info &ti = typeid(A);
+  // CHECK-GLOBAL: @_ZTSN5test21AE = linkonce_odr constant
+  // CHECK-GLOBAL: @_ZTIN5test21AE = linkonce_odr unnamed_addr constant
+  // CHECK-GLOBAL: @_ZN5test22tiE = hidden constant
+}
+
+namespace test3 {
+  struct A { int x; };
+  template <class T> struct B {
+    static void foo() { bar(); }
+    static void bar();
+  };
+
+  template void B<A>::foo();
+  // CHECK: define weak_odr hidden void @_ZN5test31BINS_1AEE3fooEv()
+  // CHECK: declare void @_ZN5test31BINS_1AEE3barEv()
+
+  const std::type_info &ti = typeid(B<A>);
+  // CHECK-GLOBAL: @_ZTSN5test31BINS_1AEEE = linkonce_odr constant
+  // CHECK-GLOBAL: @_ZTIN5test31BINS_1AEEE = linkonce_odr unnamed_addr constant
+}
+
+namespace test4 {
+  struct A { int x; };
+  template <class T> struct DEFAULT B {
+    static void foo() { bar(); }
+    static void bar();
+  };
+
+  template void B<A>::foo();
+  // CHECK: define weak_odr void @_ZN5test41BINS_1AEE3fooEv()
+  // CHECK: declare void @_ZN5test41BINS_1AEE3barEv()
+
+  const std::type_info &ti = typeid(B<A>);
+  // CHECK-GLOBAL: @_ZTSN5test41BINS_1AEEE = linkonce_odr constant
+  // CHECK-GLOBAL: @_ZTIN5test41BINS_1AEEE = linkonce_odr unnamed_addr constant
+}
+
+namespace test5 {
+  struct A { int x; };
+  template <class T> struct HIDDEN B {
+    static void foo() { bar(); }
+    static void bar();
+  };
+
+  template void B<A>::foo();
+  // CHECK: define weak_odr hidden void @_ZN5test51BINS_1AEE3fooEv()
+  // CHECK: declare hidden void @_ZN5test51BINS_1AEE3barEv()
+
+  const std::type_info &ti = typeid(B<A>);
+  // CHECK-GLOBAL: @_ZTSN5test51BINS_1AEEE = linkonce_odr hidden constant
+  // CHECK-GLOBAL: @_ZTIN5test51BINS_1AEEE = linkonce_odr hidden unnamed_addr constant
+}

Added: cfe/trunk/test/Driver/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/visibility.cpp?rev=175480&view=auto
==============================================================================
--- cfe/trunk/test/Driver/visibility.cpp (added)
+++ cfe/trunk/test/Driver/visibility.cpp Mon Feb 18 19:57:35 2013
@@ -0,0 +1,34 @@
+// RUN: %clang -### -S -fvisibility=hidden -fvisibility=default %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-1 %s < %t.log
+// CHECK-NOT: "-ftype-visibility"
+// CHECK-1: "-fvisibility" "default"
+// CHECK-NOT: "-ftype-visibility"
+
+// RUN: %clang -### -S -fvisibility=default -fvisibility=hidden %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-2 %s < %t.log
+// CHECK-NOT: "-ftype-visibility"
+// CHECK-2: "-fvisibility" "hidden"
+// CHECK-NOT: "-ftype-visibility"
+
+// RUN: %clang -### -S -fvisibility-ms-compat -fvisibility=hidden %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-3 %s < %t.log
+// CHECK-NOT: "-ftype-visibility"
+// CHECK-3: "-fvisibility" "hidden"
+// CHECK-NOT: "-ftype-visibility"
+
+// RUN: %clang -### -S -fvisibility-ms-compat -fvisibility=default %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-4 %s < %t.log
+// CHECK-NOT: "-ftype-visibility"
+// CHECK-4: "-fvisibility" "default"
+// CHECK-NOT: "-ftype-visibility"
+
+// RUN: %clang -### -S -fvisibility=hidden -fvisibility-ms-compat %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-5 %s < %t.log
+// CHECK-5: "-fvisibility" "hidden"
+// CHECK-5: "-ftype-visibility" "default"
+
+// RUN: %clang -### -S -fvisibility=default -fvisibility-ms-compat %s 2> %t.log
+// RUN: FileCheck -check-prefix=CHECK-6 %s < %t.log
+// CHECK-6: "-fvisibility" "hidden"
+// CHECK-6: "-ftype-visibility" "default"
+





More information about the cfe-commits mailing list