loladiro updated this revision to Diff 76094.
loladiro added a comment.

Rebased patch


Repository:
  rL LLVM

https://reviews.llvm.org/D13419

Files:
  lib/AST/Decl.cpp
  lib/AST/DeclCXX.cpp
  test/CodeGenCXX/visibility.cpp

Index: test/CodeGenCXX/visibility.cpp
===================================================================
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1317,3 +1317,59 @@
   // CHECK-LABEL: define void @_ZN6test693foo1fEv
   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 }
+
+namespace test70 {
+template <typename T>
+class foo {
+public:
+  T x;
+  template <typename S>
+  HIDDEN S AddS(S);
+  template <typename S>
+  class HIDDEN barS {
+  public:
+    static S AddS2(foo<T> x, S);
+  };
+  template <typename S>
+  class HIDDEN barZ {
+  public:
+    template <typename Z>
+    static S AddSZ(foo<T> x, S, Z);
+  };
+};
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+template <typename T>
+template <typename S>
+HIDDEN S foo<T>::AddS(S y) {
+  return ((S)x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+template <typename T>
+template <typename S>
+HIDDEN S foo<T>::barS<S>::AddS2(foo<T> x, S y) {
+  return ((S)x.x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+template <typename T>
+template <typename S>
+template <typename Z>
+HIDDEN S foo<T>::barZ<S>::AddSZ(foo<T> x, S y, Z z) {
+  return ((S)x.x) + y + ((S)z);
+}
+
+extern template struct foo<int>;
+template struct foo<int>;
+
+void f() {
+  auto var = foo<int>{5};
+  auto bar = var.AddS((long long)3);
+  auto bar2 = decltype(var)::barS<long long>::AddS2(var, 3);
+  auto bar3 = decltype(var)::barZ<long long>::AddSZ(var, 3, (char)0);
+}
+}
Index: lib/AST/DeclCXX.cpp
===================================================================
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1346,17 +1346,19 @@
   if (auto *TD = dyn_cast<ClassTemplateSpecializationDecl>(this)) {
     auto From = TD->getInstantiatedFrom();
     if (auto *CTD = From.dyn_cast<ClassTemplateDecl *>()) {
-      while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
-        if (NewCTD->isMemberSpecialization())
+      while (!CTD->isMemberSpecialization()) {
+        auto *NewCTD = CTD->getInstantiatedFromMemberTemplate();
+        if (!NewCTD)
           break;
         CTD = NewCTD;
       }
       return CTD->getTemplatedDecl()->getDefinition();
     }
     if (auto *CTPSD =
             From.dyn_cast<ClassTemplatePartialSpecializationDecl *>()) {
-      while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
-        if (NewCTPSD->isMemberSpecialization())
+      while (!CTPSD->isMemberSpecialization()) {
+        auto *NewCTPSD = CTPSD->getInstantiatedFromMember();
+        if (!NewCTPSD)
           break;
         CTPSD = NewCTPSD;
       }
Index: lib/AST/Decl.cpp
===================================================================
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1052,7 +1052,10 @@
   // If this is a member class of a specialization of a class template
   // and the corresponding decl has explicit visibility, use that.
   if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
-    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+    const CXXRecordDecl *InstantiatedFrom =
+        RD->getTemplateInstantiationPattern();
+    if (!InstantiatedFrom)
+      InstantiatedFrom = RD->getInstantiatedFromMemberClass();
     if (InstantiatedFrom)
       return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1086,16 +1089,13 @@
   }
   // Also handle function template specializations.
   if (const auto *fn = dyn_cast<FunctionDecl>(ND)) {
-    // If the function is a specialization of a template with an
-    // explicit visibility attribute, use that.
-    if (FunctionTemplateSpecializationInfo *templateInfo
-          = fn->getTemplateSpecializationInfo())
-      return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
-                             kind);
+    // If the function is a template specialization or a member of
+    // a specialized class template and the corresponding decl has
+    // explicit visibility, use that.
+    FunctionDecl *InstantiatedFrom = fn->getTemplateInstantiationPattern();
+    if (!InstantiatedFrom)
+      InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
 
-    // If the function is a member of a specialization of a class template
-    // and the corresponding decl has explicit visibility, use that.
-    FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
     if (InstantiatedFrom)
       return getVisibilityOf(InstantiatedFrom, kind);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to