When ignoring visibility in an instantiation, still consider the linkage.
authorRafael Espindola <rafael.espindola@gmail.com>
Fri, 25 May 2012 14:47:05 +0000 (14:47 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Fri, 25 May 2012 14:47:05 +0000 (14:47 +0000)
Similar fixes for function and member template to follow as I write the
testcases.

llvm-svn: 157470

clang/lib/AST/Decl.cpp
clang/test/CodeGenCXX/visibility.cpp

index 7b7fa42..979971c 100644 (file)
@@ -163,7 +163,8 @@ static bool shouldConsiderTemplateLV(const FunctionDecl *fn,
   return !fn->hasAttr<VisibilityAttr>() || spec->isExplicitSpecialization();
 }
 
-static bool shouldConsiderTemplateLV(const ClassTemplateSpecializationDecl *d) {
+static bool
+shouldConsiderTemplateVis(const ClassTemplateSpecializationDecl *d) {
   return !d->hasAttr<VisibilityAttr>() || d->isExplicitSpecialization();
 }
 
@@ -399,14 +400,19 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
     // linkage of the template and template arguments.
     if (const ClassTemplateSpecializationDecl *spec
           = dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
-      if (shouldConsiderTemplateLV(spec)) {
-        // From the template.
-        LV.merge(getLVForDecl(spec->getSpecializedTemplate(), true));
-
-        // The arguments at which the template was instantiated.
-        const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
-        LV.mergeWithMin(getLVForTemplateArgumentList(TemplateArgs,
-                                                     OnlyTemplate));
+      // From the template.
+      LinkageInfo TempLV = getLVForDecl(spec->getSpecializedTemplate(), true);
+
+      // The arguments at which the template was instantiated.
+      const TemplateArgumentList &TemplateArgs = spec->getTemplateArgs();
+      LinkageInfo ArgsLV = getLVForTemplateArgumentList(TemplateArgs,
+                                                        OnlyTemplate);
+      if (shouldConsiderTemplateVis(spec)) {
+        LV.merge(TempLV);
+        LV.mergeWithMin(ArgsLV);
+      } else {
+        LV.mergeLinkage(TempLV);
+        LV.mergeLinkage(ArgsLV);
       }
     }
 
@@ -540,7 +546,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, bool OnlyTemplate) {
   } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
     if (const ClassTemplateSpecializationDecl *spec
         = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {
-      if (shouldConsiderTemplateLV(spec)) {
+      if (shouldConsiderTemplateVis(spec)) {
         // Merge template argument/parameter information for member
         // class template specializations.
         LV.mergeWithMin(getLVForTemplateArgumentList(spec->getTemplateArgs(),
index 5870308..d889684 100644 (file)
@@ -818,3 +818,17 @@ namespace test43 {
   // CHECK: define hidden void @_ZN6test433barINS_3fooEEEvv
   // CHECK-HIDDEN: define hidden void @_ZN6test433barINS_3fooEEEvv
 }
+
+namespace test44 {
+  template <typename T>
+  struct foo {
+    foo() {}
+  };
+  namespace {
+    struct bar;
+  }
+  template struct DEFAULT foo<bar>;
+  foo<bar> x;
+  // CHECK: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+  // CHECK-HIDDEN: define internal void @_ZN6test443fooINS_12_GLOBAL__N_13barEEC1Ev
+}