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

Address review comment re loop structure. Reword comment that had a typo to 
both fix the typo and make the intent of the code more clear.


Repository:
  rL LLVM

http://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
@@ -1314,3 +1314,57 @@
   // 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
@@ -1261,17 +1261,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
@@ -1049,7 +1049,9 @@
   // 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>(ND)) {
-    CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+    const CXXRecordDecl *InstantiatedFrom = RD->getTemplateInstantiationPattern();
+    if (!InstantiatedFrom)
+      InstantiatedFrom = RD->getInstantiatedFromMemberClass();
     if (InstantiatedFrom)
       return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1084,16 +1086,12 @@
   }
   // Also handle function template specializations.
   if (const FunctionDecl *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 member of a specialization of a class template
-    // and the corresponding decl has explicit visibility, use that.
-    FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
+    // 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 (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