From: Daniel Dunbar Date: Tue, 14 Apr 2009 06:00:08 +0000 (+0000) Subject: Clean up handling of visibility. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=04d4078425614bf9fd58d606335c1f5f74ee7fa4;p=clang Clean up handling of visibility. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69027 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 5db1d2989b..1198c6f20f 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -91,8 +91,11 @@ public: unsigned InstantiationDepth; // Maximum template instantiation depth. enum GCMode { NonGC, GCOnly, HybridGC }; - enum VisibilityMode {NonVisibility, DefaultVisibility, ProtectedVisibility, - HiddenVisibility, InternalVisibility }; + enum VisibilityMode { + Default, + Protected, + Hidden + }; LangOptions() { Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0; @@ -105,7 +108,7 @@ public: LaxVectorConversions = 1; HeinousExtensions = 0; - SymbolVisibility = 0; + SymbolVisibility = (unsigned) Default; // FIXME: The default should be 1. ThreadsafeStatics = 0; @@ -135,7 +138,9 @@ public: const char *getMainFileName() const { return MainFileName; } void setMainFileName(const char *Name) { MainFileName = Name; } - VisibilityMode getVisibilityMode() const { return (VisibilityMode) SymbolVisibility; } + VisibilityMode getVisibilityMode() const { + return (VisibilityMode) SymbolVisibility; + } void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; } /// Emit - Emit this LangOptions object to bitcode. diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index c69f5937d0..153c8681a0 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -440,8 +440,6 @@ protected: llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI, bool ForStrongLayout); - bool IsClassHidden(const ObjCInterfaceDecl *ID); - void BuildAggrIvarLayout(const ObjCInterfaceDecl *OI, const llvm::StructLayout *Layout, const RecordDecl *RD, @@ -1441,23 +1439,6 @@ enum ClassFlags { eClassFlags_ABI2_HasCXXStructors = 0x00004 // }; -bool CGObjCCommonMac::IsClassHidden(const ObjCInterfaceDecl *ID) { - if (const VisibilityAttr *attr = ID->getAttr()) { - switch (attr->getVisibility()) { - default: - assert(0 && "Unknown visibility"); - return false; - case VisibilityAttr::DefaultVisibility: - case VisibilityAttr::ProtectedVisibility: // FIXME: What do we do here? - return false; - case VisibilityAttr::HiddenVisibility: - return true; - } - } else - return (CGM.getLangOptions().getVisibilityMode() == - LangOptions::HiddenVisibility); -} - /* struct _objc_class { Class isa; @@ -1494,7 +1475,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { unsigned Size = CGM.getTargetData().getTypePaddedSize(InterfaceTy); // FIXME: Set CXX-structors flag. - if (IsClassHidden(ID->getClassInterface())) + if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) Flags |= eClassFlags_Hidden; std::vector InstanceMethods, ClassMethods; @@ -1571,7 +1552,7 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, unsigned Flags = eClassFlags_Meta; unsigned Size = CGM.getTargetData().getTypePaddedSize(ObjCTypes.ClassTy); - if (IsClassHidden(ID->getClassInterface())) + if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden) Flags |= eClassFlags_Hidden; std::vector Values(12); @@ -4226,7 +4207,8 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { llvm::GlobalVariable *SuperClassGV, *IsAGV; - bool classIsHidden = IsClassHidden(ID->getClassInterface()); + bool classIsHidden = + CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden; if (classIsHidden) flags |= OBJC2_CLS_HIDDEN; if (!ID->getClassInterface()->getSuperClass()) { @@ -4547,13 +4529,10 @@ llvm::Constant * CGObjCNonFragileABIMac::EmitIvarOffsetVar( CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.LongTy)); // @private and @package have hidden visibility. bool globalVisibility = (Ivar->getAccessControl() == ObjCIvarDecl::Public || - Ivar->getAccessControl() == ObjCIvarDecl::Protected); - if (!globalVisibility) + Ivar->getAccessControl() == ObjCIvarDecl::Protected); + if (!globalVisibility || CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden) IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - else if (IsClassHidden(ID)) - IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - else if (CGM.getLangOptions().getVisibilityMode() == - LangOptions::DefaultVisibility) + else IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); IvarOffsetGV->setSection("__DATA, __objc_const"); UsedGlobals.push_back(IvarOffsetGV); @@ -5633,8 +5612,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, &CGM.getModule()); } - if (CGM.getLangOptions().getVisibilityMode() == - LangOptions::HiddenVisibility) + if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden) Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); Entry->setAlignment(8); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 7dacc3bfce..855791a5d3 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -95,54 +95,45 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type, getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg; } -/// setGlobalVisibility - Set the visibility for the given LLVM -/// GlobalValue according to the given clang AST visibility value. -static void setGlobalVisibility(llvm::GlobalValue *GV, - VisibilityAttr::VisibilityTypes Vis) { - // Internal definitions should always have default visibility. - if (GV->hasLocalLinkage()) { - GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - return; +LangOptions::VisibilityMode +CodeGenModule::getDeclVisibilityMode(const Decl *D) const { + if (const VarDecl *VD = dyn_cast(D)) + if (VD->getStorageClass() == VarDecl::PrivateExtern) + return LangOptions::Hidden; + + if (const VisibilityAttr *attr = D->getAttr()) { + switch (attr->getVisibility()) { + default: assert(0 && "Unknown visibility!"); + case VisibilityAttr::DefaultVisibility: + return LangOptions::Default; + case VisibilityAttr::HiddenVisibility: + return LangOptions::Hidden; + case VisibilityAttr::ProtectedVisibility: + return LangOptions::Protected; + } } - switch (Vis) { - default: assert(0 && "Unknown visibility!"); - case VisibilityAttr::DefaultVisibility: - GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - break; - case VisibilityAttr::HiddenVisibility: - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - break; - case VisibilityAttr::ProtectedVisibility: - GV->setVisibility(llvm::GlobalValue::ProtectedVisibility); - break; - } + return getLangOptions().getVisibilityMode(); } -static void setGlobalOptionVisibility(llvm::GlobalValue *GV, - LangOptions::VisibilityMode Vis) { - // Internal definitions should always have default visibility. +void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV, + const Decl *D) const { + // Internal definitions always have default visibility. if (GV->hasLocalLinkage()) { GV->setVisibility(llvm::GlobalValue::DefaultVisibility); return; } - switch (Vis) { + switch (getDeclVisibilityMode(D)) { default: assert(0 && "Unknown visibility!"); - case LangOptions::NonVisibility: - break; - case LangOptions::DefaultVisibility: - GV->setVisibility(llvm::GlobalValue::DefaultVisibility); - break; - case LangOptions::HiddenVisibility: - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - break; - case LangOptions::ProtectedVisibility: - GV->setVisibility(llvm::GlobalValue::ProtectedVisibility); - break; + case LangOptions::Default: + return GV->setVisibility(llvm::GlobalValue::DefaultVisibility); + case LangOptions::Hidden: + return GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + case LangOptions::Protected: + return GV->setVisibility(llvm::GlobalValue::ProtectedVisibility); } } - /// \brief Retrieves the mangled name for the given declaration. /// @@ -270,25 +261,18 @@ void CodeGenModule::SetGlobalValueAttributes(const Decl *D, GV->setLinkage(llvm::Function::WeakAnyLinkage); } - // FIXME: Figure out the relative priority of the attribute, - // -fvisibility, and private_extern. if (ForDefinition) { - if (const VisibilityAttr *attr = D->getAttr()) - setGlobalVisibility(GV, attr->getVisibility()); - else - setGlobalOptionVisibility(GV, getLangOptions().getVisibilityMode()); - } + setGlobalVisibility(GV, D); - if (const SectionAttr *SA = D->getAttr()) - GV->setSection(SA->getName()); - - // Only add to llvm.used when we see a definition, otherwise we - // might add multiple times or risk the value being replaced by a - // subsequent RAUW. - if (ForDefinition) { + // Only add to llvm.used when we see a definition, otherwise we + // might add multiple times or risk the value being replaced by a + // subsequent RAUW. if (D->hasAttr()) AddUsedGlobal(GV); } + + if (const SectionAttr *SA = D->getAttr()) + GV->setSection(SA->getName()); } void CodeGenModule::SetFunctionAttributes(const Decl *D, @@ -645,7 +629,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, // FIXME: Merge with other attribute handling code. if (D->getStorageClass() == VarDecl::PrivateExtern) - setGlobalVisibility(GV, VisibilityAttr::HiddenVisibility); + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); if (D->hasAttr() || D->hasAttr()) GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); @@ -746,10 +730,6 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // "extern int x[];") and then a definition of a different type (e.g. // "int x[10];"). This also happens when an initializer has a different type // from the type of the global (this happens with unions). - // - // FIXME: This also ends up happening if there's a definition followed by - // a tentative definition! (Although Sema rejects that construct - // at the moment.) if (GV == 0 || GV->getType()->getElementType() != InitType || GV->getType()->getAddressSpace() != ASTTy.getAddressSpace()) { @@ -789,42 +769,20 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setLinkage(llvm::Function::DLLExportLinkage); else if (D->hasAttr() || D->hasAttr()) GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); - else { - // FIXME: This isn't right. This should handle common linkage and other - // stuff. - switch (D->getStorageClass()) { - case VarDecl::Static: assert(0 && "This case handled above"); - case VarDecl::Auto: - case VarDecl::Register: - assert(0 && "Can't have auto or register globals"); - case VarDecl::None: - if (!D->getInit() && !CompileOpts.NoCommon) - GV->setLinkage(llvm::GlobalVariable::CommonLinkage); - else - GV->setLinkage(llvm::GlobalVariable::ExternalLinkage); - break; - case VarDecl::Extern: - // FIXME: common - break; - - case VarDecl::PrivateExtern: - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - // FIXME: common - break; - } - } - - if (const VisibilityAttr *attr = D->getAttr()) - setGlobalVisibility(GV, attr->getVisibility()); + else if (!CompileOpts.NoCommon && + (!D->hasExternalStorage() && !D->getInit())) + GV->setLinkage(llvm::GlobalVariable::CommonLinkage); else - setGlobalOptionVisibility(GV, getLangOptions().getVisibilityMode()); + GV->setLinkage(llvm::GlobalVariable::ExternalLinkage); - if (const SectionAttr *SA = D->getAttr()) - GV->setSection(SA->getName()); + setGlobalVisibility(GV, D); if (D->hasAttr()) AddUsedGlobal(GV); + if (const SectionAttr *SA = D->getAttr()) + GV->setSection(SA->getName()); + // Emit global variable debug information. if (CGDebugInfo *DI = getDebugInfo()) { DI->setLocation(D->getLocation()); diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index a1e2efc439..b2e6e228e0 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -14,6 +14,7 @@ #ifndef CLANG_CODEGEN_CODEGENMODULE_H #define CLANG_CODEGEN_CODEGENMODULE_H +#include "clang/Basic/LangOptions.h" #include "clang/AST/Attr.h" #include "CGBlocks.h" #include "CGCall.h" @@ -167,6 +168,13 @@ public: Diagnostic &getDiags() const { return Diags; } const llvm::TargetData &getTargetData() const { return TheTargetData; } + /// getDeclVisibilityMode - Compute the visibility of the decl \arg D. + LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const; + + /// setGlobalVisibility - Set the visibility for the given LLVM + /// GlobalValue. + void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const; + /// GetAddrOfGlobalVar - Return the llvm::Constant for the address of the /// given global variable. If Ty is non-null and if the global doesn't exist, /// then it will be greated with the specified type instead of whatever the diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 31515a9c12..91b87f2b05 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -812,36 +812,23 @@ void InitializeGCMode(LangOptions &Options) { Options.setGCMode(LangOptions::HybridGC); } -static llvm::cl::opt +static llvm::cl::opt SymbolVisibility("fvisibility", - llvm::cl::desc("Set the default visibility to the specific option")); - -void InitializeSymbolVisibility(LangOptions &Options) { - if (SymbolVisibility.empty()) - return; - std::string Visibility = SymbolVisibility; - const char *vkind = Visibility.c_str(); - if (!strcmp(vkind, "default")) - Options.setVisibilityMode(LangOptions::DefaultVisibility); - else if (!strcmp(vkind, "protected")) - Options.setVisibilityMode(LangOptions::ProtectedVisibility); - else if (!strcmp(vkind, "hidden")) - Options.setVisibilityMode(LangOptions::HiddenVisibility); - else if (!strcmp(vkind, "internal")) - Options.setVisibilityMode(LangOptions::InternalVisibility); - else - fprintf(stderr, - "-fvisibility only valid for default|protected|hidden|internal\n"); -} + llvm::cl::desc("Set the default symbol visibility:"), + llvm::cl::init(LangOptions::Default), + llvm::cl::values(clEnumValN(LangOptions::Default, "default", + "Use default symbol visibility"), + clEnumValN(LangOptions::Hidden, "hidden", + "Use hidden symbol visibility"), + clEnumValN(LangOptions::Protected,"protected", + "Use protected symbol visibility"), + clEnumValEnd)); static llvm::cl::opt OverflowChecking("ftrapv", llvm::cl::desc("Trap on integer overflow"), llvm::cl::init(false)); -void InitializeOverflowChecking(LangOptions &Options) { - Options.OverflowChecking = OverflowChecking; -} //===----------------------------------------------------------------------===// // Target Triple Processing. //===----------------------------------------------------------------------===// @@ -2299,8 +2286,8 @@ int main(int argc, char **argv) { LangKind LK = GetLanguage(InFile); InitializeLangOptions(LangInfo, LK); InitializeGCMode(LangInfo); - InitializeSymbolVisibility(LangInfo); - InitializeOverflowChecking(LangInfo); + LangInfo.setVisibilityMode(SymbolVisibility); + LangInfo.OverflowChecking = OverflowChecking; InitializeLanguageStandard(LangInfo, LK, Target.get()); // Process the -I options and set them in the HeaderInfo.