diff options
-rw-r--r-- | include/clang/AST/Decl.h | 5 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 124 | ||||
-rw-r--r-- | lib/CodeGen/CGVTables.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaAttr.cpp | 2 | ||||
-rw-r--r-- | test/CodeGen/attr-availability.c | 31 | ||||
-rw-r--r-- | test/CodeGenObjC/attr-availability.m | 6 |
7 files changed, 112 insertions, 60 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 339074bde0..4dd3db7fad 100644 --- a/include/clang/AST/Decl.h +++ b/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/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index df72541fbf..dfa53881f1 100644 --- a/lib/AST/Decl.cpp +++ b/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/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp index ca92c5db70..6c1b331be7 100644 --- a/lib/CodeGen/CGVTables.cpp +++ b/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/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 156819c9b6..d180a2253e 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/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/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index 794b0b1f1c..4fad173048 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/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/test/CodeGen/attr-availability.c b/test/CodeGen/attr-availability.c new file mode 100644 index 0000000000..6f9c045a3f --- /dev/null +++ b/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/test/CodeGenObjC/attr-availability.m b/test/CodeGenObjC/attr-availability.m index 4f1fad81b3..d2b2973c78 100644 --- a/test/CodeGenObjC/attr-availability.m +++ b/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 |