rnk created this revision. rnk added a reviewer: rsmith. Herald added a project: clang.
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. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D63175 Files: clang/lib/AST/ASTContext.cpp clang/test/CodeGenCXX/ms-constexpr-var-template.cpp Index: clang/test/CodeGenCXX/ms-constexpr-var-template.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/ms-constexpr-var-template.cpp @@ -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@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@D@@3_NB" +// CHECK: @escape = dso_local global i8* @"??$_Is_integer@H@@3_NB", align 8 Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -9799,10 +9799,22 @@ 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;
Index: clang/test/CodeGenCXX/ms-constexpr-var-template.cpp =================================================================== --- /dev/null +++ clang/test/CodeGenCXX/ms-constexpr-var-template.cpp @@ -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@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@D@@3_NB" +// CHECK: @escape = dso_local global i8* @"??$_Is_integer@H@@3_NB", align 8 Index: clang/lib/AST/ASTContext.cpp =================================================================== --- clang/lib/AST/ASTContext.cpp +++ clang/lib/AST/ASTContext.cpp @@ -9799,10 +9799,22 @@ 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;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits