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 | 659a337c749721bd12484e50b43b1f8f3febb26b (patch) | |
| tree | a83781d506d2b2fd4c2d3eb44a310de8b9ff31d1 /clang/lib/AST/Decl.cpp | |
| parent | 1fa7958eaa9836a2598be622ca0229cc46580bb5 (diff) | |
| download | bcm5719-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.cpp | 48 |
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) { |

