summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Decl.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-12-18 03:30:47 +0000
committerJohn McCall <rjmccall@apple.com>2010-12-18 03:30:47 +0000
commit659a337c749721bd12484e50b43b1f8f3febb26b (patch)
treea83781d506d2b2fd4c2d3eb44a310de8b9ff31d1 /clang/lib/AST/Decl.cpp
parent1fa7958eaa9836a2598be622ca0229cc46580bb5 (diff)
downloadbcm5719-llvm-659a337c749721bd12484e50b43b1f8f3febb26b.tar.gz
bcm5719-llvm-659a337c749721bd12484e50b43b1f8f3febb26b.zip
Apply attributes to explicit specializations. Specializations which
don't provide their own explicit visibility attributes should get them from the template. Fixes rdar://problem/8778497. llvm-svn: 122136
Diffstat (limited to 'clang/lib/AST/Decl.cpp')
-rw-r--r--clang/lib/AST/Decl.cpp48
1 files changed, 34 insertions, 14 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index f40907cb732..fe3dbebc1f5 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -33,21 +33,41 @@ using namespace clang;
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
-static const VisibilityAttr *GetExplicitVisibility(const Decl *D) {
- // If the decl is redeclarable, make sure we use the explicit
- // visibility attribute from the most recent declaration.
- //
- // Note that this isn't necessary for tags, which can't have their
- // visibility adjusted.
- if (isa<VarDecl>(D)) {
- return cast<VarDecl>(D)->getMostRecentDeclaration()
- ->getAttr<VisibilityAttr>();
- } else if (isa<FunctionDecl>(D)) {
- return cast<FunctionDecl>(D)->getMostRecentDeclaration()
- ->getAttr<VisibilityAttr>();
- } else {
- return D->getAttr<VisibilityAttr>();
+static const VisibilityAttr *GetExplicitVisibility(const Decl *d) {
+ // Use the most recent declaration of a variable.
+ if (const VarDecl *var = dyn_cast<VarDecl>(d))
+ return var->getMostRecentDeclaration()->getAttr<VisibilityAttr>();
+
+ // Use the most recent declaration of a function, and also handle
+ // function template specializations.
+ if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(d)) {
+ if (const VisibilityAttr *attr
+ = fn->getMostRecentDeclaration()->getAttr<VisibilityAttr>())
+ return attr;
+
+ // If the function is a specialization of a template with an
+ // explicit visibility attribute, use that.
+ if (FunctionTemplateSpecializationInfo *templateInfo
+ = fn->getTemplateSpecializationInfo())
+ return templateInfo->getTemplate()->getTemplatedDecl()
+ ->getAttr<VisibilityAttr>();
+
+ return 0;
}
+
+ // Otherwise, just check the declaration itself first.
+ if (const VisibilityAttr *attr = d->getAttr<VisibilityAttr>())
+ return attr;
+
+ // If there wasn't explicit visibility there, and this is a
+ // specialization of a class template, check for visibility
+ // on the pattern.
+ if (const ClassTemplateSpecializationDecl *spec
+ = dyn_cast<ClassTemplateSpecializationDecl>(d))
+ return spec->getSpecializedTemplate()->getTemplatedDecl()
+ ->getAttr<VisibilityAttr>();
+
+ return 0;
}
static Visibility GetVisibilityFromAttr(const VisibilityAttr *A) {
OpenPOWER on IntegriCloud