[PATCH] D70791: Workaround for MSVC 16.3.* pre-c++17 type trait linkage

Erich Keane via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed Nov 27 09:41:32 PST 2019


erichkeane created this revision.
erichkeane added reviewers: rnk, rjmccall, majnemer.

MSVC's type_trait header for the 16.3.* release in pre-c++17 mode
exposes explicitly specialized constexpr variables for _Is_integral,
is_void_v, and _Is_floating_point as not-inline (since that isn't
available in pre-C++17). The result is duplicate-symbols in any
program that includes <type_traits> more than once.

This patch works around this issue by making fairly specific cases (in
the system header, in MSVC mode, and in pre-c++17 mode) be weak_odr
linkage rather than External linkage.


https://reviews.llvm.org/D70791

Files:
  clang/lib/AST/ASTContext.cpp
  clang/test/CodeGenCXX/Inputs/ms-constexpr-typetraits.h
  clang/test/CodeGenCXX/microsoft-type-traits-pre-cxx17.cpp


Index: clang/test/CodeGenCXX/microsoft-type-traits-pre-cxx17.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/microsoft-type-traits-pre-cxx17.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -std=c++14 -o - %s -isystem%S/Inputs | FileCheck %s
+#include <ms-constexpr-typetraits.h>
+
+// CHECK: @"??$_Is_integral at _N@@3_NB" = weak_odr dso_local constant
+// CHECK: @"??$_Is_floating_point at M@@3_NB" = weak_odr dso_local constant
+// CHECK: @"??$is_void_v at X@@3_NB" = weak_odr dso_local constant
+
Index: clang/test/CodeGenCXX/Inputs/ms-constexpr-typetraits.h
===================================================================
--- /dev/null
+++ clang/test/CodeGenCXX/Inputs/ms-constexpr-typetraits.h
@@ -0,0 +1,17 @@
+template <class>
+constexpr bool _Is_integral = false;
+
+template <>
+constexpr bool _Is_integral<bool> = true;
+
+template <class>
+constexpr bool _Is_floating_point = false;
+
+template <>
+constexpr bool _Is_floating_point<float> = true;
+
+template <class>
+constexpr bool is_void_v = false;
+
+template <>
+constexpr bool is_void_v<void> = true;
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -9860,6 +9860,19 @@
   return L;
 }
 
+// The MSVC type_traits header defines a handful of type-trait constexpr
+// variables as non-inline in pre-C++17 mode which causes duplicate symbols.
+// In C++17 cases, they mark these as 'inline', which avoids this issue.
+// This fixup alters the linkage to be odr for this case.
+static bool isMSVCPreCxx17TypeTrait(const ASTContext &Context,
+                                    const VarDecl *VD) {
+  assert(VD->getTemplateSpecializationKind() == TSK_ExplicitSpecialization &&
+         "Only valid for explicit specializations");
+  return VD->isConstexpr() && !VD->isInline() &&
+         !Context.getLangOpts().CPlusPlus17 &&
+         Context.getSourceManager().isInSystemHeader(VD->getLocation());
+}
+
 GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const {
   return adjustGVALinkageForExternalDefinitionKind(*this, FD,
            adjustGVALinkageForAttributes(*this, FD,
@@ -9926,7 +9939,8 @@
 
   case TSK_ExplicitSpecialization:
     return Context.getTargetInfo().getCXXABI().isMicrosoft() &&
-                   VD->isStaticDataMember()
+                   (VD->isStaticDataMember() ||
+                    isMSVCPreCxx17TypeTrait(Context, VD))
                ? GVA_StrongODR
                : StrongLinkage;
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D70791.231280.patch
Type: text/x-patch
Size: 2625 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191127/9b0df660/attachment.bin>


More information about the cfe-commits mailing list