]> granicus.if.org Git - clang/commitdiff
Merging r195283:
authorBill Wendling <isanbard@gmail.com>
Thu, 21 Nov 2013 05:19:27 +0000 (05:19 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 21 Nov 2013 05:19:27 +0000 (05:19 +0000)
------------------------------------------------------------------------
r195283 | hans | 2013-11-20 16:15:56 -0800 (Wed, 20 Nov 2013) | 10 lines

[-cxx-abi microsoft] Emit linkonce_odr definitions for declarations of static data members with inline initializers (PR17689)

This makes Clang emit a linkonce_odr definition for 'val' in the code below,
to be compatible with MSVC-compiled code:

  struct Foo {
    static const int val = 1;
  };

Differential Revision: http://llvm-reviews.chandlerc.com/D2233
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_34@195314 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CodeGenModule.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/ms-integer-static-data-members.cpp [new file with mode: 0644]

index 44bdf66f603bfec09f48a1e74c7e6070c241608c..9e9a2a7aaf9b30ede38d0e74801713f9931c8585 100644 (file)
@@ -373,6 +373,10 @@ public:
   /// Gets the deleted virtual member call name.
   virtual StringRef GetDeletedVirtualCallName() = 0;
 
+  /// \brief Returns true iff static data members that are initialized in the
+  /// class definition should have linkonce linkage.
+  virtual bool isInlineInitializedStaticDataMemberLinkOnce() { return false; }
+
   /**************************** Array cookies ******************************/
 
   /// Returns the extra size required in order to store the array
index f5fdfdb64948ff425a21afa9f1ad80b32b477eb5..4d51fb02bb4d50d657caea05ebaf0d6fb4c2a73a 100644 (file)
@@ -1607,6 +1607,13 @@ CodeGenModule::GetOrCreateLLVMGlobal(StringRef MangledName,
         CXXThreadLocals.push_back(std::make_pair(D, GV));
       setTLSMode(GV, *D);
     }
+
+    // If required by the ABI, treat declarations of static data members with
+    // inline initializers as definitions.
+    if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+        D->isStaticDataMember() && D->hasInit() &&
+        !D->isThisDeclarationADefinition())
+      EmitGlobalVarDefinition(D);
   }
 
   if (AddrSpace != Ty->getAddressSpace())
@@ -1860,6 +1867,14 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
   llvm::GlobalValue::LinkageTypes Linkage = 
     GetLLVMLinkageVarDefinition(D, GV->isConstant());
   GV->setLinkage(Linkage);
+
+  // If required by the ABI, give definitions of static data members with inline
+  // initializers linkonce_odr linkage.
+  if (getCXXABI().isInlineInitializedStaticDataMemberLinkOnce() &&
+      D->isStaticDataMember() && InitExpr &&
+      !InitDecl->isThisDeclarationADefinition())
+    GV->setLinkage(llvm::GlobalVariable::LinkOnceODRLinkage);
+
   if (Linkage == llvm::GlobalVariable::CommonLinkage)
     // common vars aren't constant even if declared const.
     GV->setConstant(false);
index 4a02d4da51a966730acbe2fa4cde1184ef88c628..ee928c5b59006c11b8f87110d7430a547af98cc7 100644 (file)
@@ -50,6 +50,8 @@ public:
   // arbitrary.
   StringRef GetDeletedVirtualCallName() { return "_purecall"; }
 
+  bool isInlineInitializedStaticDataMemberLinkOnce() { return true; }
+
   llvm::Value *adjustToCompleteObject(CodeGenFunction &CGF,
                                       llvm::Value *ptr,
                                       QualType type);
diff --git a/test/CodeGenCXX/ms-integer-static-data-members.cpp b/test/CodeGenCXX/ms-integer-static-data-members.cpp
new file mode 100644 (file)
index 0000000..00beaa6
--- /dev/null
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s
+// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
+// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE
+// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -cxx-abi microsoft -triple=i386-pc-win32 %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
+
+struct S {
+  // For MS ABI, we emit a linkonce_odr definition here, even though it's really just a declaration.
+#ifdef INLINE_INIT
+  static const int x = 5;
+#else
+  static const int x;
+#endif
+};
+
+const int *f() {
+  return &S::x;
+};
+
+#ifdef REAL_DEFINITION
+#ifdef INLINE_INIT
+const int S::x;
+#else
+const int S::x = 5;
+#endif
+#endif
+
+
+// Inline initialization.
+// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, align 4
+
+// Out-of-line initialization.
+// CHECK-OUTOFLINE: @"\01?x@S@@2HB" = constant i32 5, align 4
+
+// No initialization.
+// CHECK: @"\01?x@S@@2HB" = external constant i32