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; Index: clang/test/CodeGenCXX/Inputs/ms-constexpr-typetraits.h =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/Inputs/ms-constexpr-typetraits.h @@ -0,0 +1,17 @@ +template +constexpr bool _Is_integral = false; + +template <> +constexpr bool _Is_integral = true; + +template +constexpr bool _Is_floating_point = false; + +template <> +constexpr bool _Is_floating_point = true; + +template +constexpr bool is_void_v = false; + +template <> +constexpr bool is_void_v = true; 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 + +// CHECK: @"??$_Is_integral@_N@@3_NB" = weak_odr dso_local constant +// CHECK: @"??$_Is_floating_point@M@@3_NB" = weak_odr dso_local constant +// CHECK: @"??$is_void_v@X@@3_NB" = weak_odr dso_local constant +