]> granicus.if.org Git - clang/commitdiff
[MS] Make constexpr static data members implicitly inline
authorReid Kleckner <rnk@google.com>
Fri, 16 Feb 2018 19:44:47 +0000 (19:44 +0000)
committerReid Kleckner <rnk@google.com>
Fri, 16 Feb 2018 19:44:47 +0000 (19:44 +0000)
This handles them exactly the same way that we handle const integral
static data members with inline definitions, which is what MSVC does.

As a follow-up, now that we have a way to mark variables inline in the
AST, we should consider marking them implicitly inline there instead of
only treating them as inline in CodeGen. Unfortunately, this breaks a
lot of dllimport test cases, so that is future work for now.

Fixes PR36125.

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

lib/AST/ASTContext.cpp
test/CodeGenCXX/static-data-member.cpp

index fff714cb6aa96d3254a01dff2bf1b3d3c96be6e5..466a5d58e252e5adf6a417f6b65a0fb9932ae8ec 100644 (file)
@@ -5857,7 +5857,7 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const {
 bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const {
   return getTargetInfo().getCXXABI().isMicrosoft() &&
          VD->isStaticDataMember() &&
-         VD->getType()->isIntegralOrEnumerationType() &&
+         (VD->getType()->isIntegralOrEnumerationType() || VD->isConstexpr()) &&
          !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit();
 }
 
index 5ffd83ff023b144f253c0ad060b7a8de5e8443bd..5f4d9b6599b8cf5937d4a64e1d5b91c9d8600c08 100644 (file)
@@ -1,6 +1,10 @@
-// RUN: %clang_cc1 -triple x86_64-pc-linux -emit-llvm -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple x86_64-apple-darwin -emit-llvm -o - %s | \
-// RUN: FileCheck --check-prefix=MACHO %s
+// RUN: %clang_cc1 -triple x86_64-pc-linux -std=c++14 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -std=c++14 -emit-llvm -o - %s \
+// RUN:     | FileCheck %s --check-prefix=MACHO
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++14 -emit-llvm -o - %s \
+// RUN:     | FileCheck %s --check-prefix=MSVC
+// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++17 -emit-llvm -o - %s \
+// RUN:     | FileCheck %s --check-prefix=MSVC
 
 // CHECK: @_ZN5test11A1aE = constant i32 10, align 4
 // CHECK: @_ZN5test212_GLOBAL__N_11AIiE1xE = internal global i32 0, align 4
 // MACHO: @_ZGVN5test31AIiE1xE = weak_odr global i64 0
 // MACHO-NOT: comdat
 
+// MSVC: @"\01?a@A@test1@@2HB" = linkonce_odr constant i32 10, comdat, align 4
+// MSVC: @"\01?i@S@test1@@2HA" = external global i32
+// MSVC: @"\01?x@?$A@H@?A@test2@@2HA" = internal global i32 0, align 4
+
 // CHECK: _ZN5test51U2k0E = global i32 0
 // CHECK: _ZN5test51U2k1E = global i32 0
 // CHECK: _ZN5test51U2k2E = constant i32 76
 // CHECK-NOT: test51U2k3E
 // CHECK-NOT: test51U2k4E
 
+// On Linux in C++14, neither of these are inline.
+// CHECK: @_ZN16inline_constexpr1A10just_constE = available_externally constant i32 42
+// CHECK: @_ZN16inline_constexpr1A10const_exprE = available_externally constant i32 43
+//
+// In MSVC, these are both implicitly inline regardless of the C++ standard
+// version.
+// MSVC: @"\01?just_const@A@inline_constexpr@@2HB" = linkonce_odr constant i32 42, comdat, align 4
+// MSVC: @"\01?const_expr@A@inline_constexpr@@2HB" = linkonce_odr constant i32 43, comdat, align 4
+
 // PR5564.
 namespace test1 {
   struct A {
@@ -28,7 +45,7 @@ namespace test1 {
   };
 
   void f() { 
-    int a = S::i;
+    int a = *&A::a + S::i;
   }
 }
 
@@ -50,6 +67,11 @@ namespace test2 {
   // CHECK:      [[TMP:%.*]] = call i32 @_ZN5test23fooEv()
   // CHECK-NEXT: store i32 [[TMP]], i32* @_ZN5test212_GLOBAL__N_11AIiE1xE, align 4
   // CHECK-NEXT: ret void
+
+  // MSVC-LABEL: define internal void @"\01??__Ex@?$A@H@?A@test2@@2HA@YAXXZ"()
+  // MSVC:      [[TMP:%.*]] = call i32 @"\01?foo@test2@@YAHXZ"()
+  // MSVC-NEXT: store i32 [[TMP]], i32* @"\01?x@?$A@H@?A@test2@@2HA", align 4
+  // MSVC-NEXT: ret void
 }
 
 // Test that we don't use threadsafe statics when initializing
@@ -108,3 +130,13 @@ namespace test5 {
   // CHECK: store i32 {{.*}}, i32* @_ZN5test51U2k1E
   // CHECK-NOT: store {{.*}} i32* @_ZN5test51U2k2E
 }
+
+// Test that MSVC mode static constexpr data members are always inline, even pre
+// C++17.
+namespace inline_constexpr {
+struct A {
+  static const int just_const = 42;
+  static constexpr int const_expr = 43;
+};
+int useit() { return *&A::just_const + *&A::const_expr; }
+}