On Mac OS X, the presence of an 'availability' attribute for that

platform implies default visibility. To achieve these, refactor our
lookup of explicit visibility so that we search for both an explicit
VisibilityAttr and an appropriate AvailabilityAttr, favoring the
VisibilityAttr if it is present.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128336 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Douglas Gregor 2011-03-26 12:10:19 +00:00
Родитель 81a65f5768
Коммит 4421d2b341
7 изменённых файлов: 113 добавлений и 61 удалений

Просмотреть файл

@ -20,6 +20,7 @@
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/Basic/Linkage.h"
#include "llvm/ADT/Optional.h"
namespace clang {
class CXXTemporary;
@ -273,6 +274,10 @@ public:
/// \brief Determines the linkage and visibility of this entity.
LinkageInfo getLinkageAndVisibility() const;
/// \brief If visibility was explicitly specified for this
/// declaration, return that visibility.
llvm::Optional<Visibility> getExplicitVisibility() const;
/// \brief Clear the linkage cache in response to a change
/// to the declaration.
void ClearLinkageCache();

Просмотреть файл

@ -25,6 +25,7 @@
#include "clang/Basic/Builtins.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
@ -33,53 +34,33 @@ using namespace clang;
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
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>();
static llvm::Optional<Visibility> getVisibilityOf(const Decl *D) {
// If this declaration has an explicit visibility attribute, use it.
if (const VisibilityAttr *A = D->getAttr<VisibilityAttr>()) {
switch (A->getVisibility()) {
case VisibilityAttr::Default:
return DefaultVisibility;
case VisibilityAttr::Hidden:
return HiddenVisibility;
case VisibilityAttr::Protected:
return ProtectedVisibility;
}
// 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) {
switch (A->getVisibility()) {
case VisibilityAttr::Default:
return DefaultVisibility;
case VisibilityAttr::Hidden:
return HiddenVisibility;
case VisibilityAttr::Protected:
return ProtectedVisibility;
}
return DefaultVisibility;
// If we're on Mac OS X, an 'availability' for Mac OS X attribute
// implies visibility(default).
if (D->getASTContext().Target.getTriple().getOS() == llvm::Triple::Darwin) {
for (specific_attr_iterator<AvailabilityAttr>
A = D->specific_attr_begin<AvailabilityAttr>(),
AEnd = D->specific_attr_end<AvailabilityAttr>();
A != AEnd; ++A)
if ((*A)->getPlatform()->getName().equals("macosx"))
return DefaultVisibility;
}
return llvm::Optional<Visibility>();
}
typedef NamedDecl::LinkageInfo LinkageInfo;
@ -286,8 +267,8 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
LinkageInfo LV;
if (F.ConsiderVisibilityAttributes) {
if (const VisibilityAttr *VA = GetExplicitVisibility(D)) {
LV.setVisibility(GetVisibilityFromAttr(VA), true);
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.setVisibility(*Vis, true);
F.ConsiderGlobalVisibility = false;
} else {
// If we're declared in a namespace with a visibility attribute,
@ -296,9 +277,9 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {
!isa<TranslationUnitDecl>(DC);
DC = DC->getParent()) {
if (!isa<NamespaceDecl>(DC)) continue;
if (const VisibilityAttr *VA =
cast<NamespaceDecl>(DC)->getAttr<VisibilityAttr>()) {
LV.setVisibility(GetVisibilityFromAttr(VA), false);
if (llvm::Optional<Visibility> Vis
= cast<NamespaceDecl>(DC)->getExplicitVisibility()) {
LV.setVisibility(*Vis, false);
F.ConsiderGlobalVisibility = false;
break;
}
@ -506,8 +487,8 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {
// If we have an explicit visibility attribute, merge that in.
if (F.ConsiderVisibilityAttributes) {
if (const VisibilityAttr *VA = GetExplicitVisibility(D)) {
LV.mergeVisibility(GetVisibilityFromAttr(VA), true);
if (llvm::Optional<Visibility> Vis = D->getExplicitVisibility()) {
LV.mergeVisibility(*Vis, true);
// Ignore global visibility later, but not this attribute.
F.ConsiderGlobalVisibility = false;
@ -669,6 +650,41 @@ LinkageInfo NamedDecl::getLinkageAndVisibility() const {
return LI;
}
llvm::Optional<Visibility> NamedDecl::getExplicitVisibility() const {
// Use the most recent declaration of a variable.
if (const VarDecl *var = dyn_cast<VarDecl>(this))
return getVisibilityOf(var->getMostRecentDeclaration());
// Use the most recent declaration of a function, and also handle
// function template specializations.
if (const FunctionDecl *fn = dyn_cast<FunctionDecl>(this)) {
if (llvm::Optional<Visibility> V
= getVisibilityOf(fn->getMostRecentDeclaration()))
return V;
// If the function is a specialization of a template with an
// explicit visibility attribute, use that.
if (FunctionTemplateSpecializationInfo *templateInfo
= fn->getTemplateSpecializationInfo())
return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl());
return llvm::Optional<Visibility>();
}
// Otherwise, just check the declaration itself first.
if (llvm::Optional<Visibility> V = getVisibilityOf(this))
return V;
// 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>(this))
return getVisibilityOf(spec->getSpecializedTemplate()->getTemplatedDecl());
return llvm::Optional<Visibility>();
}
static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
// Objective-C: treat all Objective-C declarations as having external
// linkage.
@ -722,8 +738,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
LinkageInfo LV;
if (Flags.ConsiderVisibilityAttributes) {
if (const VisibilityAttr *VA = GetExplicitVisibility(Function))
LV.setVisibility(GetVisibilityFromAttr(VA));
if (llvm::Optional<Visibility> Vis = Function->getExplicitVisibility())
LV.setVisibility(*Vis);
}
if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
@ -745,8 +761,8 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {
if (Var->getStorageClass() == SC_PrivateExtern)
LV.setVisibility(HiddenVisibility);
else if (Flags.ConsiderVisibilityAttributes) {
if (const VisibilityAttr *VA = GetExplicitVisibility(Var))
LV.setVisibility(GetVisibilityFromAttr(VA));
if (llvm::Optional<Visibility> Vis = Var->getExplicitVisibility())
LV.setVisibility(*Vis);
}
if (const VarDecl *Prev = Var->getPreviousDeclaration()) {

Просмотреть файл

@ -2545,7 +2545,7 @@ static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
Fn->getVisibility() != llvm::GlobalVariable::DefaultVisibility)
return;
if (MD->hasAttr<VisibilityAttr>())
if (MD->getExplicitVisibility())
return;
switch (MD->getTemplateSpecializationKind()) {

Просмотреть файл

@ -224,7 +224,7 @@ void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
return;
// Don't override an explicit visibility attribute.
if (RD->hasAttr<VisibilityAttr>())
if (RD->getExplicitVisibility())
return;
switch (RD->getTemplateSpecializationKind()) {

Просмотреть файл

@ -297,7 +297,7 @@ void Sema::AddPushedVisibilityAttribute(Decl *D) {
if (!VisContext)
return;
if (D->hasAttr<VisibilityAttr>())
if (isa<NamedDecl>(D) && cast<NamedDecl>(D)->getExplicitVisibility())
return;
VisStack *Stack = static_cast<VisStack*>(VisContext);

Просмотреть файл

@ -0,0 +1,31 @@
// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin8.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_4 %s
// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin9.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_5 %s
// RUN: %clang_cc1 -fvisibility hidden "-triple" "x86_64-apple-darwin10.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_6 %s
// CHECK-10_4: define hidden void @f2
// CHECK-10_5: define hidden void @f2
// CHECK-10_6: define hidden void @f2
void f2();
void f2() { }
// CHECK-10_4: define void @f3
// CHECK-10_5: define void @f3
// CHECK-10_6: define void @f3
void f3() __attribute__((availability(macosx,introduced=10.5)));
void f3() { }
// CHECK-10_4: declare extern_weak void @f0
// CHECK-10_5: declare void @f0
// CHECK-10_6: declare void @f0
void f0() __attribute__((availability(macosx,introduced=10.5)));
// CHECK-10_4: declare extern_weak void @f1
// CHECK-10_5: declare extern_weak void @f1
// CHECK-10_6: declare void @f1
void f1() __attribute__((availability(macosx,introduced=10.6)));
void test() {
f0();
f1();
f2();
}

Просмотреть файл

@ -1,6 +1,6 @@
// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin8.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_4 %s
// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin9.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_5 %s
// RUN: %clang_cc1 -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin10.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_6 %s
// RUN: %clang_cc1 -fvisibility hidden -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin8.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_4 %s
// RUN: %clang_cc1 -fvisibility hidden -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin9.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_5 %s
// RUN: %clang_cc1 -fvisibility hidden -fobjc-nonfragile-abi "-triple" "x86_64-apple-darwin10.0.0" -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-10_6 %s
// CHECK-10_4: @"OBJC_CLASS_$_WeakClass1" = extern_weak global
// CHECK-10_5: @"OBJC_CLASS_$_WeakClass1" = external global