Index: cfe/trunk/lib/AST/ASTContext.cpp =================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp +++ cfe/trunk/lib/AST/ASTContext.cpp @@ -4931,7 +4931,7 @@ 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: cfe/trunk/test/CodeGenCXX/dllexport-members.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/dllexport-members.cpp +++ cfe/trunk/test/CodeGenCXX/dllexport-members.cpp @@ -110,9 +110,10 @@ // 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 @@ __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 @@ 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 @@ // 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 @@ __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 @@ 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: cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp +++ cfe/trunk/test/CodeGenCXX/ms-integer-static-data-members.cpp @@ -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