From ee30102a9ef32cdbf0afe0e4c07a53d265a18f98 Mon Sep 17 00:00:00 2001 From: John McCall Date: Sat, 30 Oct 2010 09:18:49 +0000 Subject: [PATCH] GCC faithfully calculates visibility for variables independently of whether it's a declaration or not, then ignores that information for declarations unless it was explicitly given. It's not totally clear how that should be mapped into a sane system, but make an effort. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117780 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Decl.cpp | 42 +++++++++++++++------------------- test/CodeGenCXX/visibility.cpp | 16 +++++++++++++ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index dbd14e067a..2d29a6a9ca 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -255,21 +255,17 @@ 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 && !ExplicitVisibility && - !Var->isExternC()) { + if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) { LVPair TypeLV = Var->getType()->getLinkageAndVisibility(); if (TypeLV.first != ExternalLinkage) return LVPair(UniqueExternalLinkage, DefaultVisibility); - - // Otherwise, ignore type visibility for declarations. - if (!isDeclaration) + if (!isDeclaration && !ExplicitVisibility) LV.second = minVisibility(LV.second, TypeLV.second); } // Don't consider -fvisibility for pure declarations. - if (isDeclaration) { + if (isDeclaration) ConsiderGlobalVisibility = false; - } if (!Context.getLangOptions().CPlusPlus && (Var->getStorageClass() == SC_Extern || @@ -524,24 +520,24 @@ static LVPair getLVForClassMember(const NamedDecl *D, // Static data members. } else if (const VarDecl *VD = dyn_cast(D)) { - // If we don't have explicit visibility information in the - // hierarchy, apply the LV from its type. See the comment about - // namespace-scope variables for justification for this - // optimization. - if (!HasExplicitVisibility) { - LVPair TypeLV = VD->getType()->getLinkageAndVisibility(); - if (TypeLV.first != ExternalLinkage) - LV.first = minLinkage(LV.first, UniqueExternalLinkage); - LV.second = minVisibility(LV.second, TypeLV.second); + bool IsDefinition = (VD->getDefinition() && + VD->getTemplateSpecializationKind() + != TSK_ExplicitInstantiationDeclaration); + + // GCC just ignores the visibility of a variable declaration + // unless it's explicit. + if (!IsDefinition && !HasExplicitVisibility) { + LV.second = DefaultVisibility; + ConsiderGlobalVisibility = false; } - // Ignore global visibility if it's an extern template or - // just a declaration. - if (ConsiderGlobalVisibility) - ConsiderGlobalVisibility = - (VD->getDefinition() && - VD->getTemplateSpecializationKind() - != TSK_ExplicitInstantiationDeclaration); + // Modify the variable's linkage by its type, but ignore the + // type's visibility unless it's a definition. + LVPair TypeLV = VD->getType()->getLinkageAndVisibility(); + if (TypeLV.first != ExternalLinkage) + LV.first = minLinkage(LV.first, UniqueExternalLinkage); + if (IsDefinition && !HasExplicitVisibility) + LV.second = minVisibility(LV.second, TypeLV.second); } // Suppress -fvisibility if we have explicit visibility on any of diff --git a/test/CodeGenCXX/visibility.cpp b/test/CodeGenCXX/visibility.cpp index a55544573d..2272d1fa5e 100644 --- a/test/CodeGenCXX/visibility.cpp +++ b/test/CodeGenCXX/visibility.cpp @@ -20,6 +20,8 @@ // CHECK-HIDDEN: @_ZN6Test131C1aE = global // CHECK: @_ZN6Test143varE = external global // CHECK-HIDDEN: @_ZN6Test143varE = external global +// CHECK: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] +// CHECK-HIDDEN: @_ZN6Test154TempINS_1AEE5Inner6bufferE = external global [0 x i8] // CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant namespace Test1 { @@ -218,3 +220,17 @@ namespace Test14 { struct A *test() { return var; } } + +// rdar://problem/8613093 +namespace Test15 { + struct A {}; + template struct Temp { + struct Inner { + static char buffer[0]; + }; + }; + + char *test() { + return Temp::Inner::buffer; + } +} -- 2.40.0