diff options
author | John McCall <rjmccall@apple.com> | 2010-10-28 04:18:25 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-10-28 04:18:25 +0000 |
commit | b7139c43ae6627b44f4ba1304a914894f5bb0439 (patch) | |
tree | 038fa61fe861e07b1ddc77d7fe896b2c7be93d65 | |
parent | eaae1adb9492401df049fd9047fd1ad74cf7c7dd (diff) | |
download | bcm5719-llvm-b7139c43ae6627b44f4ba1304a914894f5bb0439.tar.gz bcm5719-llvm-b7139c43ae6627b44f4ba1304a914894f5bb0439.zip |
When computing visibility, use the latest declaration's explicit visibility
attribute.
Part of rdar://problem/8595231
llvm-svn: 117526
-rw-r--r-- | clang/lib/AST/Decl.cpp | 34 | ||||
-rw-r--r-- | clang/test/CodeGen/visibility.c | 7 |
2 files changed, 33 insertions, 8 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index cb03ff50e25..2069054b3a7 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -33,6 +33,23 @@ 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 Visibility GetVisibilityFromAttr(const VisibilityAttr *A) { switch (A->getVisibility()) { case VisibilityAttr::Default: @@ -180,6 +197,8 @@ static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) { if (D->isInAnonymousNamespace()) return LVPair(UniqueExternalLinkage, DefaultVisibility); + const VisibilityAttr *ExplicitVisibility = GetExplicitVisibility(D); + // Set up the defaults. // C99 6.2.2p5: @@ -218,7 +237,7 @@ static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) { // Note that we don't want to make the variable non-external // because of this, but unique-external linkage suits us. if (Context.getLangOptions().CPlusPlus && !Var->isExternC() && - !Var->hasAttr<VisibilityAttr>()) { + !ExplicitVisibility) { LVPair TypeLV = Var->getType()->getLinkageAndVisibility(); if (TypeLV.first != ExternalLinkage) return LVPair(UniqueExternalLinkage, DefaultVisibility); @@ -252,7 +271,7 @@ static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) { // Modify the function's LV by the LV of its type unless this is // C or extern "C". See the comment above about variables. if (Context.getLangOptions().CPlusPlus && !Function->isExternC() && - !Function->hasAttr<VisibilityAttr>()) { + !ExplicitVisibility) { LVPair TypeLV = Function->getType()->getLinkageAndVisibility(); if (TypeLV.first != ExternalLinkage) return LVPair(UniqueExternalLinkage, DefaultVisibility); @@ -376,9 +395,8 @@ static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) { Visibility StandardV; // If we have an explicit visibility attribute, merge that in. - const VisibilityAttr *VA = D->getAttr<VisibilityAttr>(); - if (VA) - StandardV = GetVisibilityFromAttr(VA); + if (ExplicitVisibility) + StandardV = GetVisibilityFromAttr(ExplicitVisibility); else if (ConsiderDashFVisibility) StandardV = Context.getLangOptions().getVisibilityMode(); else @@ -416,7 +434,7 @@ static LVPair getLVForClassMember(const NamedDecl *D) { LVPair LV = ClassLV; // If we have an explicit visibility attribute, merge that in. - const VisibilityAttr *VA = D->getAttr<VisibilityAttr>(); + const VisibilityAttr *VA = GetExplicitVisibility(D); if (VA) LV.second = minVisibility(LV.second, GetVisibilityFromAttr(VA)); // If it's a value declaration and we don't have an explicit visibility @@ -510,7 +528,7 @@ LVPair NamedDecl::getLinkageAndVisibility() const { return LVPair(UniqueExternalLinkage, DefaultVisibility); LVPair LV(ExternalLinkage, DefaultVisibility); - if (const VisibilityAttr *VA = Function->getAttr<VisibilityAttr>()) + if (const VisibilityAttr *VA = GetExplicitVisibility(Function)) LV.second = GetVisibilityFromAttr(VA); if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) { @@ -531,7 +549,7 @@ LVPair NamedDecl::getLinkageAndVisibility() const { LVPair LV(ExternalLinkage, DefaultVisibility); if (Var->getStorageClass() == SC_PrivateExtern) LV.second = HiddenVisibility; - else if (const VisibilityAttr *VA = Var->getAttr<VisibilityAttr>()) + else if (const VisibilityAttr *VA = GetExplicitVisibility(Var)) LV.second = GetVisibilityFromAttr(VA); if (const VarDecl *Prev = Var->getPreviousDeclaration()) { diff --git a/clang/test/CodeGen/visibility.c b/clang/test/CodeGen/visibility.c index 501071b832b..42b116f7aa4 100644 --- a/clang/test/CodeGen/visibility.c +++ b/clang/test/CodeGen/visibility.c @@ -46,3 +46,10 @@ int f_def(void) { // CHECK-HIDDEN: define void @test1( struct Test1 { int field; }; void __attribute__((visibility("default"))) test1(struct Test1 *v) { } + +// rdar://problem/8595231 +// CHECK-DEFAULT: define void @test2() +// CHECK-PROTECTED: define void @test2() +// CHECK-HIDDEN: define void @test2() +void test2(void); +void __attribute__((visibility("default"))) test2(void) {} |