diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-03-26 12:10:19 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-03-26 12:10:19 +0000 |
commit | 1baf38f5a6edfbaa402f1dbda9dfa30fe02d5163 (patch) | |
tree | 7d76db523a10e3129396b86ecaf8198bca494d01 | |
parent | 34d00052cbfd6747026f77128950de4462803d65 (diff) | |
download | bcm5719-llvm-1baf38f5a6edfbaa402f1dbda9dfa30fe02d5163.tar.gz bcm5719-llvm-1baf38f5a6edfbaa402f1dbda9dfa30fe02d5163.zip |
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.
llvm-svn: 128336
-rw-r--r-- | clang/include/clang/AST/Decl.h | 5 | ||||
-rw-r--r-- | clang/lib/AST/Decl.cpp | 124 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 2 | ||||
-rw-r--r-- | clang/test/CodeGen/attr-availability.c | 31 | ||||
-rw-r--r-- | clang/test/CodeGenObjC/attr-availability.m | 6 |
7 files changed, 112 insertions, 60 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 339074bde02..4dd3db7fad9 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -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(); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index df72541fbf9..dfa53881f1a 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/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>(); - - // 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>(); +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; + } - return 0; + return DefaultVisibility; } - // 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; + // 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 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()) { diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index ca92c5db703..6c1b331be78 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -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()) { diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 156819c9b6f..d180a2253ef 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -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()) { diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 794b0b1f1cf..4fad1730487 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -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); diff --git a/clang/test/CodeGen/attr-availability.c b/clang/test/CodeGen/attr-availability.c new file mode 100644 index 00000000000..6f9c045a3f1 --- /dev/null +++ b/clang/test/CodeGen/attr-availability.c @@ -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(); +} diff --git a/clang/test/CodeGenObjC/attr-availability.m b/clang/test/CodeGenObjC/attr-availability.m index 4f1fad81b30..d2b2973c78d 100644 --- a/clang/test/CodeGenObjC/attr-availability.m +++ b/clang/test/CodeGenObjC/attr-availability.m @@ -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 |