]> granicus.if.org Git - clang/commitdiff
Don't factor in visibility for templates and template arguments
authorJohn McCall <rjmccall@apple.com>
Mon, 27 Jun 2011 23:06:04 +0000 (23:06 +0000)
committerJohn McCall <rjmccall@apple.com>
Mon, 27 Jun 2011 23:06:04 +0000 (23:06 +0000)
for explicit specializations with their own explicit visibility.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133958 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/DeclTemplate.h
lib/AST/Decl.cpp
test/CodeGenCXX/visibility.cpp

index dc50d614bf7ce1e98be3c74b511c7c2061dfe3eb..d2b1d3990c66891b584a40032e194ae648785642 100644 (file)
@@ -314,6 +314,10 @@ public:
     return (TemplateSpecializationKind)(Template.getInt() + 1);
   }
 
+  bool isExplicitSpecialization() const {
+    return getTemplateSpecializationKind() == TSK_ExplicitSpecialization;
+  }
+
   /// \brief Set the template specialization kind.
   void setTemplateSpecializationKind(TemplateSpecializationKind TSK) {
     assert(TSK != TSK_Undeclared &&
@@ -1398,6 +1402,10 @@ public:
     return static_cast<TemplateSpecializationKind>(SpecializationKind);
   }
 
+  bool isExplicitSpecialization() const {
+    return getSpecializationKind() == TSK_ExplicitSpecialization;
+  }
+
   void setSpecializationKind(TemplateSpecializationKind TSK) {
     SpecializationKind = TSK;
   }
index 7ca936abc91b20abbd7af6a3ceda5b4958eb84fe..9b507cfc5e2425a6e1c9f1b96167b9f94ddd6536 100644 (file)
@@ -197,6 +197,16 @@ getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
   return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
 }
 
+static bool shouldConsiderTemplateLV(const FunctionDecl *fn,
+                               const FunctionTemplateSpecializationInfo *spec) {
+  return !(spec->isExplicitSpecialization() &&
+           fn->hasAttr<VisibilityAttr>());
+}
+
+static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
+  return !(d->isExplicitSpecialization() && d->hasAttr<VisibilityAttr>());
+}
+
 static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
   assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
          "Not a name having namespace scope");
@@ -397,12 +407,16 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
         Function->getType()->getLinkage() == UniqueExternalLinkage)
       return LinkageInfo::uniqueExternal();
 
-    if (FunctionTemplateSpecializationInfo *SpecInfo
+    // Consider LV from the template and the template arguments unless
+    // this is an explicit specialization with a visibility attribute.
+    if (FunctionTemplateSpecializationInfo *specInfo
                                = Function->getTemplateSpecializationInfo()) {
-      LV.merge(getLVForDecl(SpecInfo->getTemplate(),
-                            F.onlyTemplateVisibility()));
-      const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
-      LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+      if (shouldConsiderTemplateLV(Function, specInfo)) {
+        LV.merge(getLVForDecl(specInfo->getTemplate(),
+                              F.onlyTemplateVisibility()));
+        const TemplateArgumentList &templateArgs = *specInfo->TemplateArguments;
+        LV.merge(getLVForTemplateArgumentList(templateArgs, F));
+      }
     }
 
   //     - a named class (Clause 9), or an unnamed class defined in a
@@ -418,15 +432,17 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
 
     // If this is a class template specialization, consider the
     // linkage of the template and template arguments.
-    if (const ClassTemplateSpecializationDecl *Spec
+    if (const ClassTemplateSpecializationDecl *spec
           = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
-      // From the template.
-      LV.merge(getLVForDecl(Spec->getSpecializedTemplate(),
-                            F.onlyTemplateVisibility()));
-
-      // The arguments at which the template was instantiated.
-      const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
-      LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+      if (shouldConsiderTemplateLV(spec)) {
+        // From the template.
+        LV.merge(getLVForDecl(spec->getSpecializedTemplate(),
+                              F.onlyTemplateVisibility()));
+
+        // The arguments at which the template was instantiated.
+        const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
+        LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));
+      }
     }
 
     // Consider -fvisibility unless the type has C linkage.
@@ -527,14 +543,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
 
     // If this is a method template specialization, use the linkage for
     // the template parameters and arguments.
-    if (FunctionTemplateSpecializationInfo *Spec
+    if (FunctionTemplateSpecializationInfo *spec
            = MD->getTemplateSpecializationInfo()) {
-      LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F));
-      if (F.ConsiderTemplateParameterTypes)
-        LV.merge(getLVForTemplateParameterList(
-                              Spec->getTemplate()->getTemplateParameters()));
+      if (shouldConsiderTemplateLV(MD, spec)) {
+        LV.merge(getLVForTemplateArgumentList(*spec->TemplateArguments, F));
+        if (F.ConsiderTemplateParameterTypes)
+          LV.merge(getLVForTemplateParameterList(
+                              spec->getTemplate()->getTemplateParameters()));
+      }
 
-      TSK = Spec->getTemplateSpecializationKind();
+      TSK = spec->getTemplateSpecializationKind();
     } else if (MemberSpecializationInfo *MSI =
                  MD->getMemberSpecializationInfo()) {
       TSK = MSI->getTemplateSpecializationKind();
@@ -561,14 +579,16 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
     // *do* apply -fvisibility to method declarations.
 
   } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
-    if (const ClassTemplateSpecializationDecl *Spec
+    if (const ClassTemplateSpecializationDecl *spec
         = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
-      // Merge template argument/parameter information for member
-      // class template specializations.
-      LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));
+      if (shouldConsiderTemplateLV(spec)) {
+        // Merge template argument/parameter information for member
+        // class template specializations.
+        LV.merge(getLVForTemplateArgumentList(spec->getTemplateArgs(), F));
       if (F.ConsiderTemplateParameterTypes)
         LV.merge(getLVForTemplateParameterList(
-                    Spec->getSpecializedTemplate()->getTemplateParameters()));
+                    spec->getSpecializedTemplate()->getTemplateParameters()));
+      }
     }
 
   // Static data members.
index 7644e47ff7801af2892ba69ef6cbff191363ab3e..fdccd460454518e95b59b50b498ff6047dc95750 100644 (file)
@@ -422,3 +422,35 @@ namespace test21 {
   // CHECK: define weak_odr void @_ZN6test211AILNS_2EnE0EE3fooEv(
   template void A<en>::foo();
 }
+
+// rdar://problem/9616154
+// Visibility on explicit specializations should take precedence.
+namespace test22 {
+  class A1 {};
+  class A2 {};
+
+  template <class T> struct B {};
+  template <> struct DEFAULT B<A1> {
+    static void foo();
+    static void bar() {}
+  };
+  template <> struct B<A2> {
+    static void foo();
+    static void bar() {}
+  };
+
+  void test() {
+    B<A1>::foo();
+    B<A1>::bar();
+    B<A2>::foo();
+    B<A2>::bar();
+  }
+  // CHECK: declare void @_ZN6test221BINS_2A1EE3fooEv()
+  // CHECK: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+  // CHECK: declare void @_ZN6test221BINS_2A2EE3fooEv()
+  // CHECK: define linkonce_odr void @_ZN6test221BINS_2A2EE3barEv()
+  // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A1EE3fooEv()
+  // CHECK-HIDDEN: define linkonce_odr void @_ZN6test221BINS_2A1EE3barEv()
+  // CHECK-HIDDEN: declare void @_ZN6test221BINS_2A2EE3fooEv()
+  // CHECK-HIDDEN: define linkonce_odr hidden void @_ZN6test221BINS_2A2EE3barEv()
+}