From ef34bcb258ffbf7a500bb715edced98fe6348676 Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
Date: Mon, 23 Oct 2017 03:58:34 +0000
Subject: [PATCH] For better compatibility with C++11 and C++14, emit a
 nondiscardable definition of a static constexpr data member if it's defined
 'constexpr' out of line, not only if it's defined 'constexpr' in the class.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@316310 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/AST/ASTContext.cpp                     |  6 +++---
 test/CodeGenCXX/cxx1z-inline-variables.cpp | 18 ++++++++++++++----
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 15aa4531b8c..a7ff9e10e9d 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -5635,14 +5635,14 @@ ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const {
 
   // In almost all cases, it's a weak definition.
   auto *First = VD->getFirstDecl();
-  if (!First->isConstexpr() || First->isInlineSpecified() ||
-      !VD->isStaticDataMember())
+  if (First->isInlineSpecified() || !First->isStaticDataMember())
     return InlineVariableDefinitionKind::Weak;
 
   // If there's a file-context declaration in this translation unit, it's a
   // non-discardable definition.
   for (auto *D : VD->redecls())
-    if (D->getLexicalDeclContext()->isFileContext())
+    if (D->getLexicalDeclContext()->isFileContext() &&
+        !D->isInlineSpecified() && (D->isConstexpr() || First->isConstexpr()))
       return InlineVariableDefinitionKind::Strong;
 
   // If we've not seen one yet, we don't know.
diff --git a/test/CodeGenCXX/cxx1z-inline-variables.cpp b/test/CodeGenCXX/cxx1z-inline-variables.cpp
index 183709373d1..0d2ec92a7af 100644
--- a/test/CodeGenCXX/cxx1z-inline-variables.cpp
+++ b/test/CodeGenCXX/cxx1z-inline-variables.cpp
@@ -31,18 +31,28 @@ struct compat {
   static constexpr int b = 2;
   static constexpr int c = 3;
   static inline constexpr int d = 4;
+  static const int e = 5;
+  static const int f = 6;
+  static const int g = 7;
 };
 const int &compat_use_before_redecl = compat::b;
 const int compat::a;
 const int compat::b;
 const int compat::c;
 const int compat::d;
+const int compat::e;
+constexpr int compat::f;
+constexpr inline int compat::g;
 const int &compat_use_after_redecl1 = compat::c;
 const int &compat_use_after_redecl2 = compat::d;
-// CHECK: @_ZN6compat1bE = weak_odr constant i32 2
-// CHECK: @_ZN6compat1aE = weak_odr constant i32 1
-// CHECK: @_ZN6compat1cE = weak_odr constant i32 3
-// CHECK: @_ZN6compat1dE = linkonce_odr constant i32 4
+const int &compat_use_after_redecl3 = compat::g;
+// CHECK-DAG: @_ZN6compat1bE = weak_odr constant i32 2
+// CHECK-DAG: @_ZN6compat1aE = weak_odr constant i32 1
+// CHECK-DAG: @_ZN6compat1cE = weak_odr constant i32 3
+// CHECK-DAG: @_ZN6compat1dE = linkonce_odr constant i32 4
+// CHECK-DAG: @_ZN6compat1eE = constant i32 5
+// CHECK-DAG: @_ZN6compat1fE = weak_odr constant i32 6
+// CHECK-DAG: @_ZN6compat1gE = linkonce_odr constant i32 7
 
 template<typename T> struct X {
   static int a;
-- 
GitLab