зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
81a65f5768
Коммит
4421d2b341
|
@ -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();
|
||||
|
|
126
lib/AST/Decl.cpp
126
lib/AST/Decl.cpp
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче