]> granicus.if.org Git - clang/commitdiff
[MSVC] Handle out-of-line definition of static data member correctly (fix for http...
authorAlexey Bataev <a.bataev@hotmail.com>
Wed, 20 May 2015 11:57:02 +0000 (11:57 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Wed, 20 May 2015 11:57:02 +0000 (11:57 +0000)
There are 3 cases of defining static const member:

initialized inside the class, not defined outside the class.
initialized inside the class, defined outside the class.
not initialized inside the class, defined outside the class.
Revision r213304 was supposed to fix the linkage problem of case (1), but mistakenly it made case (2) behave the same.
As a result, out-of-line definition of static data member is not handled correctly.
Proposed patch distinguishes between cases (1) and (2) and allows to properly emit static const members under –fms-compatibility option.

This fixes http://llvm.org/PR21164.
Differential Revision: http://reviews.llvm.org/D9850

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

lib/AST/ASTContext.cpp
test/CodeGenCXX/dllexport-members.cpp
test/CodeGenCXX/ms-integer-static-data-members.cpp

index 770a2cf4df5e4a8dd3e28f589e7c9d07f6bed366..4a831d90e64587ca59e4705426fcf232af418c67 100644 (file)
@@ -4931,7 +4931,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
 bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
   return getLangOpts().MSVCCompat && VD->isStaticDataMember() &&
          VD->getType()->isIntegralOrEnumerationType() &&
-         !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
+         VD->isFirstDecl() && !VD->isOutOfLine() && VD->hasInit();
 }
 
 static inline 
index 5b2af1e04bd753ca9f71b2b4458cf56595abbd2c..4038d0ba467dd524799deabbd51d1edf815a962f 100644 (file)
@@ -110,9 +110,10 @@ public:
 
   // MSC-DAG: @"\01?StaticField@ExportMembers@@2HA"               = dllexport global i32 1, align 4
   // MSC-DAG: @"\01?StaticConstField@ExportMembers@@2HB"          = dllexport constant i32 1, align 4
-  // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-  // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-  // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB"            = weak_odr dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldEqualInit@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldBraceInit@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldRefNotDef@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?ConstexprField@ExportMembers@@2HB"            = dllexport constant i32 1, comdat, align 4
   // GNU-DAG: @_ZN13ExportMembers11StaticFieldE                   = dllexport global i32 1, align 4
   // GNU-DAG: @_ZN13ExportMembers16StaticConstFieldE              = dllexport constant i32 1, align 4
   // GNU-DAG: @_ZN13ExportMembers25StaticConstFieldEqualInitE     = dllexport constant i32 1, align 4
@@ -122,6 +123,7 @@ public:
   __declspec(dllexport) static  const  int  StaticConstField;
   __declspec(dllexport) static  const  int  StaticConstFieldEqualInit = 1;
   __declspec(dllexport) static  const  int  StaticConstFieldBraceInit{1};
+  __declspec(dllexport) static  const  int  StaticConstFieldRefNotDef = 1;
   __declspec(dllexport) constexpr static int ConstexprField = 1;
 };
 
@@ -144,6 +146,7 @@ inline void ExportMembers::staticInlineDef() {}
 const  int  ExportMembers::StaticConstField = 1;
 const  int  ExportMembers::StaticConstFieldEqualInit;
 const  int  ExportMembers::StaticConstFieldBraceInit;
+int foo() { return ExportMembers::StaticConstFieldRefNotDef; }
 constexpr int ExportMembers::ConstexprField;
 
 
@@ -233,9 +236,10 @@ public:
 
   // MSC-DAG: @"\01?StaticField@Nested@ExportMembers@@2HA"               = dllexport global i32 1, align 4
   // MSC-DAG: @"\01?StaticConstField@Nested@ExportMembers@@2HB"          = dllexport constant i32 1, align 4
-  // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-  // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
-  // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB"            = weak_odr dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldEqualInit@Nested@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldBraceInit@Nested@ExportMembers@@2HB" = dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?StaticConstFieldRefNotDef@Nested@ExportMembers@@2HB" = weak_odr dllexport constant i32 1, comdat, align 4
+  // MSC-DAG: @"\01?ConstexprField@Nested@ExportMembers@@2HB"            = dllexport constant i32 1, comdat, align 4
   // GNU-DAG: @_ZN13ExportMembers6Nested11StaticFieldE                   = dllexport global i32 1, align 4
   // GNU-DAG: @_ZN13ExportMembers6Nested16StaticConstFieldE              = dllexport constant i32 1, align 4
   // GNU-DAG: @_ZN13ExportMembers6Nested25StaticConstFieldEqualInitE     = dllexport constant i32 1, align 4
@@ -245,6 +249,7 @@ public:
   __declspec(dllexport) static  const  int  StaticConstField;
   __declspec(dllexport) static  const  int  StaticConstFieldEqualInit = 1;
   __declspec(dllexport) static  const  int  StaticConstFieldBraceInit{1};
+  __declspec(dllexport) static  const  int  StaticConstFieldRefNotDef = 1;
   __declspec(dllexport) constexpr static int ConstexprField = 1;
 };
 
@@ -267,6 +272,7 @@ inline void ExportMembers::Nested::staticInlineDef() {}
 const  int  ExportMembers::Nested::StaticConstField = 1;
 const  int  ExportMembers::Nested::StaticConstFieldEqualInit;
 const  int  ExportMembers::Nested::StaticConstFieldBraceInit;
+int fooNested() { return ExportMembers::Nested::StaticConstFieldRefNotDef; }
 constexpr int ExportMembers::Nested::ConstexprField;
 
 
index 4965f7319187a855e47b673109f7c53f8e48bddd..5e5b81d4a59111f3ba82252eeb1d66e5f31c830f 100644 (file)
@@ -1,35 +1,52 @@
 // RUN: %clang_cc1 -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s
-// RUN: %clang_cc1 -DINLINE_INIT -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-INLINE
-// RUN: %clang_cc1 -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %s -o - | FileCheck %s --check-prefix=CHECK-OUTOFLINE
-// RUN: %clang_cc1 -DINLINE_INIT -DREAL_DEFINITION -emit-llvm -triple=i386-pc-win32 -fms-compatibility %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
+  static const int NoInit_Ref;
+  static const int Inline_NotDef_NotRef = 5;
+  static const int Inline_NotDef_Ref = 5;
+  static const int Inline_Def_NotRef = 5;
+  static const int Inline_Def_Ref = 5;
+  static const int OutOfLine_Def_NotRef;
+  static const int OutOfLine_Def_Ref;
 };
 
-const int *f() {
-  return &S::x;
+const int *foo1() {
+  return &S::NoInit_Ref;
 };
 
-#ifdef REAL_DEFINITION
-#ifdef INLINE_INIT
-const int S::x;
-#else
-const int S::x = 5;
-#endif
-#endif
+const int *foo2() {
+  return &S::Inline_NotDef_Ref;
+};
+
+const int *foo3() {
+  return &S::Inline_Def_Ref;
+};
 
+const int *foo4() {
+    return &S::OutOfLine_Def_Ref;
+};
 
-// Inline initialization.
-// CHECK-INLINE: @"\01?x@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4
+const int S::Inline_Def_NotRef;
+const int S::Inline_Def_Ref;
+const int S::OutOfLine_Def_NotRef = 5;
+const int S::OutOfLine_Def_Ref = 5;
 
-// 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
+// CHECK-DAG: @"\01?NoInit_Ref@S@@2HB" = external constant i32
+
+// Inline initialization, no real definiton, not referenced.
+// CHECK-NOT: @"\01?Inline_NotDef_NotRef@S@@2HB" = {{.*}} constant i32 5
+
+// Inline initialization, no real definiton, referenced.
+// CHECK-DAG: @"\01?Inline_NotDef_Ref@S@@2HB" = linkonce_odr constant i32 5, comdat, align 4
+
+// Inline initialization, real definiton, not referenced.
+// CHECK-DAG: @"\01?Inline_Def_NotRef@S@@2HB" = constant i32 5, align 4
+
+// Inline initialization, real definiton, referenced.
+// CHECK-DAG: @"\01?Inline_Def_Ref@S@@2HB" = constant i32 5, comdat, align 4
+
+// Out-of-line initialization.
+// CHECK-DAG: @"\01?OutOfLine_Def_NotRef@S@@2HB" = constant i32 5, align 4
+// CHECK-DAG: @"\01?OutOfLine_Def_Ref@S@@2HB" = constant i32 5, align 4