diff options
author | John McCall <rjmccall@apple.com> | 2010-12-18 03:30:47 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-12-18 03:30:47 +0000 |
commit | 7f1b98760d419a09b2261c1ef901f6bc1ff33e19 (patch) | |
tree | d3968efbcb1e3af57942e336b9634200ff838ddd /lib/AST/Decl.cpp | |
parent | 472ccff00cdbcd095c3ba933b9e3f202719f118f (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@122136 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Decl.cpp')
-rw-r--r-- | lib/AST/Decl.cpp | 48 |
1 files changed, 34 insertions, 14 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index f40907cb73..fe3dbebc1f 100644 --- a/lib/AST/Decl.cpp +++ b/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) { |