diff options
-rw-r--r-- | clang/lib/AST/Decl.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/visibility-pr36810.cpp | 23 |
2 files changed, 35 insertions, 3 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 18ef94ba225..3b4507de61c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1092,9 +1092,18 @@ getExplicitVisibilityAux(const NamedDecl *ND, // If there wasn't explicit visibility there, and this is a // specialization of a class template, check for visibility // on the pattern. - if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) - return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(), - kind); + if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) { + // Walk all the template decl till this point to see if there are + // explicit visibility attributes. + const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl(); + while (TD != nullptr) { + auto Vis = getVisibilityOf(TD, kind); + if (Vis != None) + return Vis; + TD = TD->getPreviousDecl(); + } + return None; + } // Use the most recent declaration. if (!IsMostRecent && !isa<NamespaceDecl>(ND)) { diff --git a/clang/test/CodeGenCXX/visibility-pr36810.cpp b/clang/test/CodeGenCXX/visibility-pr36810.cpp new file mode 100644 index 00000000000..5df1df68513 --- /dev/null +++ b/clang/test/CodeGenCXX/visibility-pr36810.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macosx -std=c++11 -fvisibility hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s +// RUN: %clang_cc1 -triple x86_64-apple-macosx -DUNDEF_G -std=c++11 -fvisibility hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s + +namespace std { +template <class> +class __attribute__((__type_visibility__("default"))) shared_ptr { + template <class> friend class shared_ptr; +}; +} +struct dict; +#ifndef UNDEF_G +std::shared_ptr<dict> g; +#endif +class __attribute__((visibility("default"))) Bar; +template <class = std::shared_ptr<Bar>> +class __attribute__((visibility("default"))) i { + std::shared_ptr<int> foo() const; +}; + +// CHECK: define void @_ZNK1iISt10shared_ptrI3BarEE3fooEv +template <> std::shared_ptr<int> i<>::foo() const { + return std::shared_ptr<int>(); +} |