Skip to content

Commit 79cbd11

Browse files
[CXX] Templates specialization visibility can be wrong
Summary: 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 Reviewers: rsmith, arphaman, doug.gregor Reviewed By: doug.gregor Subscribers: doug.gregor, cfe-commits Differential Revision: https://reviews.llvm.org/D44670 llvm-svn: 330338
1 parent 1bc6e71 commit 79cbd11

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

clang/lib/AST/Decl.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,9 +1092,18 @@ getExplicitVisibilityAux(const NamedDecl *ND,
10921092
// If there wasn't explicit visibility there, and this is a
10931093
// specialization of a class template, check for visibility
10941094
// on the pattern.
1095-
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND))
1096-
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl(),
1097-
kind);
1095+
if (const auto *spec = dyn_cast<ClassTemplateSpecializationDecl>(ND)) {
1096+
// Walk all the template decl till this point to see if there are
1097+
// explicit visibility attributes.
1098+
const auto *TD = spec->getSpecializedTemplate()->getTemplatedDecl();
1099+
while (TD != nullptr) {
1100+
auto Vis = getVisibilityOf(TD, kind);
1101+
if (Vis != None)
1102+
return Vis;
1103+
TD = TD->getPreviousDecl();
1104+
}
1105+
return None;
1106+
}
10981107

10991108
// Use the most recent declaration.
11001109
if (!IsMostRecent && !isa<NamespaceDecl>(ND)) {
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -triple x86_64-apple-macosx -std=c++11 -fvisibility hidden -emit-llvm -o - %s -O2 -disable-llvm-passes | FileCheck %s
2+
// 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
3+
4+
namespace std {
5+
template <class>
6+
class __attribute__((__type_visibility__("default"))) shared_ptr {
7+
template <class> friend class shared_ptr;
8+
};
9+
}
10+
struct dict;
11+
#ifndef UNDEF_G
12+
std::shared_ptr<dict> g;
13+
#endif
14+
class __attribute__((visibility("default"))) Bar;
15+
template <class = std::shared_ptr<Bar>>
16+
class __attribute__((visibility("default"))) i {
17+
std::shared_ptr<int> foo() const;
18+
};
19+
20+
// CHECK: define void @_ZNK1iISt10shared_ptrI3BarEE3fooEv
21+
template <> std::shared_ptr<int> i<>::foo() const {
22+
return std::shared_ptr<int>();
23+
}

0 commit comments

Comments
 (0)