[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
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 18ef94b..3b4507d 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1092,9 +1092,18 @@
// 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)) {