[cfe-commits] r117351 - in /cfe/trunk: include/clang/AST/DeclBase.h lib/AST/Decl.cpp lib/AST/DeclBase.cpp test/CodeGen/visibility.c test/CodeGenCXX/visibility.cpp

John McCall rjmccall at apple.com
Mon Oct 25 21:59:26 PDT 2010


Author: rjmccall
Date: Mon Oct 25 23:59:26 2010
New Revision: 117351

URL: http://llvm.org/viewvc/llvm-project?rev=117351&view=rev
Log:
A couple of tweaks to the visibility rules: 
  - tags with C linkage should ignore visibility=hidden
  - functions and variables with explicit visibility attributes should
    ignore the linkage of their types
Either of these should be sufficient to fix PR8457.

Also, FileCheck-ize a test case.


Modified:
    cfe/trunk/include/clang/AST/DeclBase.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/AST/DeclBase.cpp
    cfe/trunk/test/CodeGen/visibility.c
    cfe/trunk/test/CodeGenCXX/visibility.cpp

Modified: cfe/trunk/include/clang/AST/DeclBase.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=117351&r1=117350&r2=117351&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclBase.h (original)
+++ cfe/trunk/include/clang/AST/DeclBase.h Mon Oct 25 23:59:26 2010
@@ -816,6 +816,10 @@
   /// C++0x scoped enums), and C++ linkage specifications.
   bool isTransparentContext() const;
 
+  /// \brief Determines whether this context is, or is nested within,
+  /// a C++ extern "C" linkage spec.
+  bool isExternCContext() const;
+
   /// \brief Determine whether this declaration context is equivalent
   /// to the declaration context DC.
   bool Equals(const DeclContext *DC) const {

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=117351&r1=117350&r2=117351&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Mon Oct 25 23:59:26 2010
@@ -212,9 +212,13 @@
     //   given variable or function shall be identical...
     // C does not have an equivalent rule.
     //
+    // Ignore this if we've got an explicit attribute;  the user
+    // probably knows what they're doing.
+    //
     // Note that we don't want to make the variable non-external
     // because of this, but unique-external linkage suits us.
-    if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) {
+    if (Context.getLangOptions().CPlusPlus && !Var->isExternC() &&
+        !Var->hasAttr<VisibilityAttr>()) {
       LVPair TypeLV = Var->getType()->getLinkageAndVisibility();
       if (TypeLV.first != ExternalLinkage)
         return LVPair(UniqueExternalLinkage, DefaultVisibility);
@@ -247,7 +251,8 @@
   } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
     // Modify the function's LV by the LV of its type unless this is
     // C or extern "C".  See the comment above about variables.
-    if (Context.getLangOptions().CPlusPlus && !Function->isExternC()) {
+    if (Context.getLangOptions().CPlusPlus && !Function->isExternC() &&
+        !Function->hasAttr<VisibilityAttr>()) {
       LVPair TypeLV = Function->getType()->getLinkageAndVisibility();
       if (TypeLV.first != ExternalLinkage)
         return LVPair(UniqueExternalLinkage, DefaultVisibility);
@@ -321,8 +326,11 @@
         ConsiderDashFVisibility = false;
     }
 
+    // Consider -fvisibility unless the type has C linkage.
     if (ConsiderDashFVisibility)
-      ConsiderDashFVisibility = Tag->isDefinition();
+      ConsiderDashFVisibility =
+        (Context.getLangOptions().CPlusPlus &&
+         !Tag->getDeclContext()->isExternCContext());
 
   //     - an enumerator belonging to an enumeration with external linkage;
   } else if (isa<EnumConstantDecl>(D)) {

Modified: cfe/trunk/lib/AST/DeclBase.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=117351&r1=117350&r2=117351&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclBase.cpp (original)
+++ cfe/trunk/lib/AST/DeclBase.cpp Mon Oct 25 23:59:26 2010
@@ -529,6 +529,17 @@
   return false;
 }
 
+bool DeclContext::isExternCContext() const {
+  const DeclContext *DC = this;
+  while (DC->DeclKind != Decl::TranslationUnit) {
+    if (DC->DeclKind == Decl::LinkageSpec)
+      return cast<LinkageSpecDecl>(DC)->getLanguage()
+        == LinkageSpecDecl::lang_c;
+    DC = DC->getParent();
+  }
+  return false;
+}
+
 bool DeclContext::Encloses(const DeclContext *DC) const {
   if (getPrimaryContext() != this)
     return getPrimaryContext()->Encloses(DC);

Modified: cfe/trunk/test/CodeGen/visibility.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/visibility.c?rev=117351&r1=117350&r2=117351&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/visibility.c (original)
+++ cfe/trunk/test/CodeGen/visibility.c Mon Oct 25 23:59:26 2010
@@ -1,33 +1,34 @@
-// RUN: %clang_cc1 -triple i386-unknown-unknown -fvisibility default -emit-llvm -o %t %s
-// RUN: grep '@g_com = common global i32 0' %t
-// RUN: grep '@g_def = global i32 0' %t
-// RUN: grep '@g_ext = external global i32' %t
-// RUN: grep '@g_deferred = internal global' %t
-// RUN: grep 'declare void @f_ext()' %t
-// RUN: grep 'define internal void @f_deferred()' %t
-// RUN: grep 'define i32 @f_def()' %t
-// RUN: %clang_cc1 -triple i386-unknown-unknown -fvisibility protected -emit-llvm -o %t %s
-// RUN: grep '@g_com = common protected global i32 0' %t
-// RUN: grep '@g_def = protected global i32 0' %t
-// RUN: grep '@g_ext = external global i32' %t
-// RUN: grep '@g_deferred = internal global' %t
-// RUN: grep 'declare void @f_ext()' %t
-// RUN: grep 'define internal void @f_deferred()' %t
-// RUN: grep 'define protected i32 @f_def()' %t
-// RUN: %clang_cc1 -triple i386-unknown-unknown -fvisibility hidden -emit-llvm -o %t %s
-// RUN: grep '@g_com = common hidden global i32 0' %t
-// RUN: grep '@g_def = hidden global i32 0' %t
-// RUN: grep '@g_ext = external global i32' %t
-// RUN: grep '@g_deferred = internal global' %t
-// RUN: grep 'declare void @f_ext()' %t
-// RUN: grep 'define internal void @f_deferred()' %t
-// RUN: grep 'define hidden i32 @f_def()' %t
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -fvisibility default -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-DEFAULT
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -fvisibility protected -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-PROTECTED
+// RUN: %clang_cc1 %s -triple i386-unknown-unknown -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
 
+// CHECK-DEFAULT: @g_def = global i32 0
+// CHECK-DEFAULT: @g_com = common global i32 0
+// CHECK-DEFAULT: @g_ext = external global i32
+// CHECK-DEFAULT: @g_deferred = internal global
+// CHECK-PROTECTED: @g_def = protected global i32 0
+// CHECK-PROTECTED: @g_com = common protected global i32 0
+// CHECK-PROTECTED: @g_ext = external global i32
+// CHECK-PROTECTED: @g_deferred = internal global
+// CHECK-HIDDEN: @g_def = hidden global i32 0
+// CHECK-HIDDEN: @g_com = common hidden global i32 0
+// CHECK-HIDDEN: @g_ext = external global i32
+// CHECK-HIDDEN: @g_deferred = internal global
 int g_com;
 int g_def = 0;
 extern int g_ext;
 static char g_deferred[] = "hello";
 
+// CHECK-DEFAULT: define i32 @f_def()
+// CHECK-DEFAULT: declare void @f_ext()
+// CHECK-DEFAULT: define internal void @f_deferred()
+// CHECK-PROTECTED: define protected i32 @f_def()
+// CHECK-PROTECTED: declare void @f_ext()
+// CHECK-PROTECTED: define internal void @f_deferred()
+// CHECK-HIDDEN: define hidden i32 @f_def()
+// CHECK-HIDDEN: declare void @f_ext()
+// CHECK-HIDDEN: define internal void @f_deferred()
+
 extern void f_ext(void);
 
 static void f_deferred(void) {
@@ -38,3 +39,10 @@
   f_deferred();
   return g_com + g_def + g_ext + g_deferred[0];
 }
+
+// PR8457
+// CHECK-DEFAULT: define void @test1(
+// CHECK-PROTECTED: define void @test1(
+// CHECK-HIDDEN: define void @test1(
+struct Test1 { int field; };
+void  __attribute__((visibility("default"))) test1(struct Test1 *v) { }

Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=117351&r1=117350&r2=117351&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/visibility.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/visibility.cpp Mon Oct 25 23:59:26 2010
@@ -8,6 +8,8 @@
 // CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
 // CHECK: @_ZN5Test71aE = hidden global
 // CHECK: @_ZN5Test71bE = global
+// CHECK: @test9_var = global
+// CHECK-HIDDEN: @test9_var = global
 // CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant 
 
 namespace Test1 {
@@ -115,3 +117,19 @@
     bar();
   }
 }
+
+// PR8457
+namespace Test9 {
+  extern "C" {
+    struct A { int field; };
+    void DEFAULT test9_fun(struct A *a) { }
+    struct A DEFAULT test9_var; // above
+  }
+  // CHECK: define void @test9_fun(
+  // CHECK-HIDDEN: define void @test9_fun(
+
+  void test() {
+    A a = test9_var;
+    test9_fun(&a);
+  }
+}





More information about the cfe-commits mailing list