steven_wu created this revision. steven_wu added reviewers: rsmith, arphaman.
Under some conditions, LinkageComputer can get the visibility for ClassTemplateSpecializationDecl wrong because it failed to find the Decl that has the explicit visibility. This fixes: llvm.org/bugs/pr36810 rdar://problem/38080953 Repository: rC Clang https://reviews.llvm.org/D44670 Files: lib/AST/Decl.cpp test/CodeGenCXX/visibility-pr36810.cpp Index: test/CodeGenCXX/visibility-pr36810.cpp =================================================================== --- /dev/null +++ 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>(); +} Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -1073,9 +1073,15 @@ // 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)) { + for (const auto *RD : + spec->getSpecializedTemplate()->getTemplatedDecl()->redecls()) { + auto Vis = getVisibilityOf(RD, kind); + if (Vis != None) + return Vis; + } + return None; + } // Use the most recent declaration. if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
Index: test/CodeGenCXX/visibility-pr36810.cpp =================================================================== --- /dev/null +++ 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>(); +} Index: lib/AST/Decl.cpp =================================================================== --- lib/AST/Decl.cpp +++ lib/AST/Decl.cpp @@ -1073,9 +1073,15 @@ // 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)) { + for (const auto *RD : + spec->getSpecializedTemplate()->getTemplatedDecl()->redecls()) { + auto Vis = getVisibilityOf(RD, kind); + if (Vis != None) + return Vis; + } + return None; + } // Use the most recent declaration. if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits