r363191 - [MS] Pretend constexpr variable template specializations are inline

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 12 11:53:49 PDT 2019


Author: rnk
Date: Wed Jun 12 11:53:49 2019
New Revision: 363191

URL: http://llvm.org/viewvc/llvm-project?rev=363191&view=rev
Log:
[MS] Pretend constexpr variable template specializations are inline

Fixes link errors with clang and the latest Visual C++ 14.21.27702
headers, which was reported as PR42027.

I chose to intentionally make these things linkonce_odr, i.e.
discardable, so that we don't emit definitions of these things in every
translation unit that includes STL headers.

Note that this is *not* what MSVC does: MSVC has not yet implemented C++
DR2387, so they emit fully specialized constexpr variable templates with
static / internal linkage.

Reviewers: rsmith

Differential Revision: https://reviews.llvm.org/D63175

Added:
    cfe/trunk/test/CodeGenCXX/ms-constexpr-var-template.cpp
Modified:
    cfe/trunk/lib/AST/ASTContext.cpp

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=363191&r1=363190&r2=363191&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Wed Jun 12 11:53:49 2019
@@ -9799,10 +9799,22 @@ static GVALinkage basicGVALinkageForVari
     return StrongLinkage;
 
   case TSK_ExplicitSpecialization:
-    return Context.getTargetInfo().getCXXABI().isMicrosoft() &&
-                   VD->isStaticDataMember()
-               ? GVA_StrongODR
-               : StrongLinkage;
+    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+      // If this is a fully specialized constexpr variable template, pretend it
+      // was marked inline. MSVC 14.21.27702 headers define _Is_integral in a
+      // header this way, and we don't want to emit non-discardable definitions
+      // of these variables in every TU that includes <type_traits>. This
+      // behavior can be removed if the headers change to explicitly mark such
+      // variable template specializations inline.
+      if (isa<VarTemplateSpecializationDecl>(VD) && VD->isConstexpr())
+        return GVA_DiscardableODR;
+
+      // Use ODR linkage for static data members of fully specialized templates
+      // to prevent duplicate definition errors with MSVC.
+      if (VD->isStaticDataMember())
+        return GVA_StrongODR;
+    }
+    return StrongLinkage;
 
   case TSK_ExplicitInstantiationDefinition:
     return GVA_StrongODR;

Added: cfe/trunk/test/CodeGenCXX/ms-constexpr-var-template.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ms-constexpr-var-template.cpp?rev=363191&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ms-constexpr-var-template.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/ms-constexpr-var-template.cpp Wed Jun 12 11:53:49 2019
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-windows-msvc -fms-compatibility %s -o - | FileCheck %s
+
+template <typename> constexpr bool _Is_integer = false;
+template <> constexpr bool _Is_integer<int> = true;
+template <> constexpr bool _Is_integer<char> = false;
+extern "C" const bool *escape = &_Is_integer<int>;
+
+// CHECK: @"??$_Is_integer at H@@3_NB" = linkonce_odr dso_local constant i8 1, comdat, align 1
+//   Should not emit _Is_integer<char>, since it's not referenced.
+// CHECK-NOT: @"??$_Is_integer at D@@3_NB"
+// CHECK: @escape = dso_local global i8* @"??$_Is_integer at H@@3_NB", align 8




More information about the cfe-commits mailing list