summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-02-19 14:07:28 +0000
committerHans Wennborg <hans@hanshq.net>2018-02-19 14:07:28 +0000
commitd535c7497ba16b93fc49b1587d10d32ea44e61a4 (patch)
treedf473c6a5a2c349973694336f4f175425f874b9f
parentb092852c1d76878d1e43bd539e9ae0af146e80e0 (diff)
Merging r325375:
------------------------------------------------------------------------ r325375 | rnk | 2018-02-16 20:44:47 +0100 (Fri, 16 Feb 2018) | 11 lines [MS] Make constexpr static data members implicitly inline 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/branches/release_60@325500 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTContext.cpp2
-rw-r--r--test/CodeGenCXX/static-data-member.cpp40
2 files changed, 37 insertions, 5 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index c73ae9efe1..94af21d4be 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -5854,7 +5854,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();
}
diff --git a/test/CodeGenCXX/static-data-member.cpp b/test/CodeGenCXX/static-data-member.cpp
index 5ffd83ff02..5f4d9b6599 100644
--- a/test/CodeGenCXX/static-data-member.cpp
+++ b/test/CodeGenCXX/static-data-member.cpp
@@ -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
@@ -9,12 +13,25 @@
// 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; }
+}