Author: abataev
Date: Wed May 20 06:57:02 2015
New Revision: 237787

URL: http://llvm.org/viewvc/llvm-project?rev=237787&view=rev
Log:
[MSVC] Handle out-of-line definition of static data member correctly (fix for 
http://llvm.org/PR21164), by Alexey Frolov

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

Modified:
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
    cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=237787&r1=237786&r2=237787&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed May 20 06:57:02 2015
@@ -4931,7 +4931,7 @@ CharUnits ASTContext::getObjCEncodingTyp
 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 

Modified: cfe/trunk/test/CodeGenCXX/dllexport-members.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/dllexport-members.cpp?rev=237787&r1=237786&r2=237787&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/dllexport-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/dllexport-members.cpp Wed May 20 06:57:02 2015
@@ -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::staticInlineD
 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::stati
 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;
 
 

Modified: cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp?rev=237787&r1=237786&r2=237787&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp Wed May 20 
06:57:02 2015
@@ -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



_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to