diff options
author | Anders Carlsson <andersca@mac.com> | 2010-02-07 02:03:08 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2010-02-07 02:03:08 +0000 |
commit | f6b89a173827457c28ac77b7cf091a24ef484e8a (patch) | |
tree | 7cb0efa647547c0ed2e22476306c10eb2e7833b0 | |
parent | 39de84d671bac60662251e98f20a5a6039795dfc (diff) |
Use the right linkage for static variables inside C++ inline functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95512 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 25 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | test/CodeGenCXX/static-init.cpp | 12 |
3 files changed, 33 insertions, 7 deletions
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index e27c5e4e51..f33c2eb80e 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -76,8 +76,21 @@ void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) { case VarDecl::Auto: case VarDecl::Register: return EmitLocalBlockVarDecl(D); - case VarDecl::Static: - return EmitStaticBlockVarDecl(D); + case VarDecl::Static: { + llvm::GlobalValue::LinkageTypes Linkage = + llvm::GlobalValue::InternalLinkage; + + // If this is a static declaration inside an inline function, it must have + // weak linkage so that the linker will merge multiple definitions of it. + if (getContext().getLangOptions().CPlusPlus) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CurFuncDecl)) { + if (FD->isInlined()) + Linkage = llvm::GlobalValue::WeakAnyLinkage; + } + } + + return EmitStaticBlockVarDecl(D, Linkage); + } case VarDecl::Extern: case VarDecl::PrivateExtern: // Don't emit it now, allow it to be emitted lazily on its first use. @@ -177,12 +190,12 @@ CodeGenFunction::AddInitializerToGlobalBlockVarDecl(const VarDecl &D, return GV; } -void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { +void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D, + llvm::GlobalValue::LinkageTypes Linkage) { llvm::Value *&DMEntry = LocalDeclMap[&D]; assert(DMEntry == 0 && "Decl already exists in localdeclmap!"); - llvm::GlobalVariable *GV = - CreateStaticBlockVarDecl(D, ".", llvm::GlobalValue::InternalLinkage); + llvm::GlobalVariable *GV = CreateStaticBlockVarDecl(D, ".", Linkage); // Store into LocalDeclMap before generating initializer to handle // circular references. @@ -355,7 +368,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { // If this variable is marked 'const', emit the value as a global. if (CGM.getCodeGenOpts().MergeAllConstants && Ty.isConstant(getContext())) { - EmitStaticBlockVarDecl(D); + EmitStaticBlockVarDecl(D, llvm::GlobalValue::InternalLinkage); return; } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 67a123f4f9..64274d16d8 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -845,7 +845,8 @@ public: /// This function can be called with a null (unreachable) insert point. void EmitLocalBlockVarDecl(const VarDecl &D); - void EmitStaticBlockVarDecl(const VarDecl &D); + void EmitStaticBlockVarDecl(const VarDecl &D, + llvm::GlobalValue::LinkageTypes Linkage); /// EmitParmDecl - Emit a ParmVarDecl or an ImplicitParamDecl. void EmitParmDecl(const VarDecl &D, llvm::Value *Arg); diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp index 33d92d6853..a67d137d6a 100644 --- a/test/CodeGenCXX/static-init.cpp +++ b/test/CodeGenCXX/static-init.cpp @@ -1,6 +1,10 @@ // RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK: @_ZZ1hvE1i = internal global i32 0, align 4 + +// CHECK: @_ZZ2h2vE1i = weak global i32 0 +// CHECK: @_ZGVZ2h2vE1i = weak global i64 0 + struct A { A(); ~A(); @@ -22,3 +26,11 @@ int a(); void h() { static const int i = a(); } + +inline void h2() { + static int i = a(); +} + +void h3() { + h2(); +} |