From: David Blaikie Date: Wed, 4 Sep 2013 21:07:37 +0000 (+0000) Subject: Do not emit duplicate global initializers for template static data members inside... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0d520f7d2efb471e568b3449f614ea90b48ad1db;p=clang Do not emit duplicate global initializers for template static data members inside namespaces A quirk of AST representation leads to class template static data member definitions being visited twice during Clang IRGen resulting in duplicate (benign) initializers. Discovered while investigating a possibly-related debug info bug tickled by the duplicate emission of these members & their associated debug info. With thanks to Richard Smith for help investigating, understanding, and helping with the fix. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@189996 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 3b28d9d07f..6c12671843 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -2761,8 +2761,13 @@ void CodeGenModule::EmitObjCIvarInitializations(ObjCImplementationDecl *D) { /// EmitNamespace - Emit all declarations in a namespace. void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) { for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end(); - I != E; ++I) + I != E; ++I) { + if (const VarDecl *VD = dyn_cast(*I)) + if (VD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization && + VD->getTemplateSpecializationKind() != TSK_Undeclared) + continue; EmitTopLevelDecl(*I); + } } // EmitLinkageSpec - Emit all declarations in a linkage spec. diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp index a069e8bd72..f4b72469c7 100644 --- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp +++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++1y -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s // CHECK: ; ModuleID extern "C" int foo(); @@ -12,11 +12,13 @@ template<> int A::a; // CHECK: @_ZN1AIbE1aE = global i32 10 template<> int A::a = 10; -// CHECK: @llvm.global_ctors = appending global [5 x { i32, void ()* }] +// CHECK: @llvm.global_ctors = appending global [7 x { i32, void ()* }] // CHECK: [{ i32, void ()* } { i32 65535, void ()* @[[unordered1:[^ ]*]] }, // CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered2:[^ ]*]] }, // CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered3:[^ ]*]] }, // CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered4:[^ ]*]] }, +// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered5:[^ ]*]] }, +// CHECK: { i32, void ()* } { i32 65535, void ()* @[[unordered6:[^ ]*]] }, // CHECK: { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] template int A::a; // Unordered @@ -37,6 +39,19 @@ template short x; // Unordered template<> int x = foo(); int e = x; // Unordered +namespace ns { +template struct a { + static int i; +}; +template int a::i = foo(); +template struct a; + +struct b { + template static T i; +}; +template T b::i = foo(); +template int b::i; +} // CHECK: define internal void @[[unordered1]] // CHECK: call i32 @foo() // CHECK: store {{.*}} @_ZN1AIsE1aE @@ -49,11 +64,21 @@ int e = x; // Unordered // CHECK: define internal void @[[unordered3]] // CHECK: call i32 @foo() -// CHECK: store {{.*}} @_ZN1AIvE1aE +// CHECK: store {{.*}} @_ZN2ns1aIiE1iE // CHECK: ret // CHECK: define internal void @[[unordered4]] // CHECK: call i32 @foo() +// CHECK: store {{.*}} @_ZN2ns1b1iIiEE +// CHECK: ret + +// CHECK: define internal void @[[unordered5]] +// CHECK: call i32 @foo() +// CHECK: store {{.*}} @_ZN1AIvE1aE +// CHECK: ret + +// CHECK: define internal void @[[unordered6]] +// CHECK: call i32 @foo() // CHECK: store {{.*}} @_Z1xIcE // CHECK: ret