From: Daniel Dunbar Date: Tue, 13 Jan 2009 02:25:00 +0000 (+0000) Subject: Bug fix, __private_extern__ globals were always introducing a definition. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49988884c1da4b2200bfe2298a1e41b3f044e8d4;p=clang Bug fix, __private_extern__ globals were always introducing a definition. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62139 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index ff8acde995..39611a08de 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -150,14 +150,14 @@ static void setGlobalVisibility(llvm::GlobalValue *GV, /// AddGlobalCtor - Add a function to the list that will be called before /// main() runs. void CodeGenModule::AddGlobalCtor(llvm::Function * Ctor, int Priority) { - // TODO: Type coercion of void()* types. + // FIXME: Type coercion of void()* types. GlobalCtors.push_back(std::make_pair(Ctor, Priority)); } /// AddGlobalDtor - Add a function to the list that will be called /// when the module is unloaded. void CodeGenModule::AddGlobalDtor(llvm::Function * Dtor, int Priority) { - // TODO: Type coercion of void()* types. + // FIXME: Type coercion of void()* types. GlobalDtors.push_back(std::make_pair(Dtor, Priority)); } @@ -214,7 +214,7 @@ static void SetGlobalValueAttributes(const Decl *D, bool IsInline, llvm::GlobalValue *GV, bool ForDefinition) { - // TODO: Set up linkage and many other things. Note, this is a simple + // FIXME: Set up linkage and many other things. Note, this is a simple // approximation of what we really want. if (!ForDefinition) { // Only a few attributes are set on declarations. @@ -247,6 +247,8 @@ static void SetGlobalValueAttributes(const Decl *D, } } + // FIXME: Figure out the relative priority of the attribute, + // -fvisibility, and private_extern. if (const VisibilityAttr *attr = D->getAttr()) setGlobalVisibility(GV, attr->getVisibility()); // FIXME: else handle -fvisibility @@ -451,7 +453,9 @@ void CodeGenModule::EmitGlobal(const ValueDecl *Global) { } else if (const VarDecl *VD = cast(Global)) { assert(VD->isFileVarDecl() && "Cannot emit local var decl as global."); - isDef = !(VD->getStorageClass() == VarDecl::Extern && VD->getInit() == 0); + isDef = !((VD->getStorageClass() == VarDecl::Extern || + VD->getStorageClass() == VarDecl::PrivateExtern) && + VD->getInit() == 0); isStatic = VD->getStorageClass() == VarDecl::Static; } else { assert(0 && "Invalid argument to EmitGlobal"); @@ -492,11 +496,24 @@ void CodeGenModule::EmitGlobalDefinition(const ValueDecl *D) { // Lookup the entry, lazily creating it if necessary. llvm::GlobalValue *&Entry = GlobalDeclMap[D->getIdentifier()]; - if (!Entry) - Entry = new llvm::GlobalVariable(Ty, false, - llvm::GlobalValue::ExternalLinkage, - 0, D->getNameAsString(), &getModule(), 0, - ASTTy.getAddressSpace()); + if (!Entry) { + llvm::GlobalVariable *GV = + new llvm::GlobalVariable(Ty, false, + llvm::GlobalValue::ExternalLinkage, + 0, D->getNameAsString(), &getModule(), 0, + ASTTy.getAddressSpace()); + Entry = GV; + + // Handle things which are present even on external declarations. + + // FIXME: This code is overly simple and should be merged with + // other global handling. + + GV->setConstant(D->getType().isConstant(Context)); + + if (D->getStorageClass() == VarDecl::PrivateExtern) + setGlobalVisibility(GV, VisibilityAttr::HiddenVisibility); + } // Make sure the result is of the correct type. return llvm::ConstantExpr::getBitCast(Entry, PTy); @@ -626,8 +643,12 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { GV->setLinkage(llvm::GlobalVariable::ExternalLinkage); break; case VarDecl::Extern: + // FIXME: common + break; + case VarDecl::PrivateExtern: - // todo: common + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + // FIXME: common break; } } diff --git a/test/CodeGen/private-extern.c b/test/CodeGen/private-extern.c new file mode 100644 index 0000000000..8cf963da25 --- /dev/null +++ b/test/CodeGen/private-extern.c @@ -0,0 +1,10 @@ +// RUN: clang -emit-llvm -o %t %s && +// RUN: grep '@g0 = external hidden constant i32' %t && +// RUN: grep '@g1 = hidden constant i32 1' %t + +__private_extern__ const int g0; +__private_extern__ const int g1 = 1; + +int f0(void) { + return g0; +}