r176112 - Use the most recent decl in getExplicitVisibility.

Rafael Espindola rafael.espindola at gmail.com
Tue Feb 26 11:33:14 PST 2013


Author: rafael
Date: Tue Feb 26 13:33:14 2013
New Revision: 176112

URL: http://llvm.org/viewvc/llvm-project?rev=176112&view=rev
Log:
Use the most recent decl in getExplicitVisibility.

Now that implicitly hidden template arguments can make an instantiation hidden,
it is important to look at more than just the canonical decl of the argument
in order to see if an attribute is available in a more recent decl.

This has the disadvantage of exposing when getExplicitVisibility is called,
but lets us handle cases like

template <typename T>
struct __attribute__((visibility("default"))) barT {
  static void zed() {}
};
class foo;
class __attribute__((visibility("default"))) foo;
template struct barT<foo>;

Modified:
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/test/CodeGenCXX/visibility.cpp

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=176112&r1=176111&r2=176112&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Tue Feb 26 13:33:14 2013
@@ -970,11 +970,32 @@ void NamedDecl::verifyLinkage() const {
 
 Optional<Visibility>
 NamedDecl::getExplicitVisibility(ExplicitVisibilityKind kind) const {
-  // Use the most recent declaration of a variable.
-  if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
-    if (Optional<Visibility> V = getVisibilityOf(Var, kind))
-      return V;
+  // Check the declaration itself first.
+  if (Optional<Visibility> V = getVisibilityOf(this, kind))
+    return V;
+
+  // If this is a member class of a specialization of a class template
+  // and the corresponding decl has explicit visibility, use that.
+  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
+    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+    if (InstantiatedFrom)
+      return getVisibilityOf(InstantiatedFrom, kind);
+  }
 
+  // If there wasn't explicit visibility there, and this is a
+  // specialization of a class template, check for visibility
+  // on the pattern.
+  if (const ClassTemplateSpecializationDecl *spec
+        = dyn_cast<ClassTemplateSpecializationDecl>(this))
+    return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
+                           kind);
+
+  // Use the most recent declaration.
+  const NamedDecl *MostRecent = cast<NamedDecl>(this->getMostRecentDecl());
+  if (MostRecent != this)
+    return MostRecent->getExplicitVisibility(kind);
+
+  if (const VarDecl *Var = dyn_cast<VarDecl>(this)) {
     if (Var->isStaticDataMember()) {
       VarDecl *InstantiatedFrom = Var->getInstantiatedFromStaticDataMember();
       if (InstantiatedFrom)
@@ -983,12 +1004,8 @@ NamedDecl::getExplicitVisibility(Explici
 
     return None;
   }
-  // Use the most recent declaration of a function, and also handle
-  // function template specializations.
+  // Also handle function template specializations.
   if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
-    if (Optional<Visibility> V = getVisibilityOf(fn, kind))
-      return V;
-
     // If the function is a specialization of a template with an
     // explicit visibility attribute, use that.
     if (FunctionTemplateSpecializationInfo *templateInfo
@@ -1005,30 +1022,10 @@ NamedDecl::getExplicitVisibility(Explici
     return None;
   }
 
-  // Otherwise, just check the declaration itself first.
-  if (Optional<Visibility> V = getVisibilityOf(this, kind))
-    return V;
-
   // The visibility of a template is stored in the templated decl.
   if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(this))
     return getVisibilityOf(TD->getTemplatedDecl(), kind);
 
-  // If there wasn't explicit visibility there, and this is a
-  // specialization of a class template, check for visibility
-  // on the pattern.
-  if (const ClassTemplateSpecializationDecl *spec
-        = dyn_cast<ClassTemplateSpecializationDecl>(this))
-    return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
-                           kind);
-
-  // If this is a member class of a specialization of a class template
-  // and the corresponding decl has explicit visibility, use that.
-  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(this)) {
-    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
-    if (InstantiatedFrom)
-      return getVisibilityOf(InstantiatedFrom, kind);
-  }
-
   return None;
 }
 

Modified: cfe/trunk/test/CodeGenCXX/visibility.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/visibility.cpp?rev=176112&r1=176111&r2=176112&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/visibility.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/visibility.cpp Tue Feb 26 13:33:14 2013
@@ -1227,3 +1227,36 @@ namespace test65 {
 
   template class C<B<A>::InnerT>;
 }
+
+namespace test66 {
+  template <typename T>
+  struct __attribute__((visibility("default"))) barT {
+    static void zed() {}
+  };
+  class foo;
+  class __attribute__((visibility("default"))) foo;
+  template struct barT<foo>;
+  // CHECK: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barTINS_3fooEE3zedEv
+
+  template <int* I>
+  struct __attribute__((visibility("default"))) barI {
+    static void zed() {}
+  };
+  extern int I;
+  extern int I __attribute__((visibility("default")));
+  template struct barI<&I>;
+  // CHECK: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barIIXadL_ZNS_1IEEEE3zedEv
+
+  typedef void (*fType)(void);
+  template<fType F>
+  struct __attribute__((visibility("default"))) barF {
+    static void zed() {}
+  };
+  void F();
+  void F() __attribute__((visibility("default")));;
+  template struct barF<F>;
+  // CHECK: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+  // CHECK-HIDDEN: define weak_odr void @_ZN6test664barFIXadL_ZNS_1FEvEEE3zedEv
+}





More information about the cfe-commits mailing list