|
@@ -9905,10 +9905,25 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context,
|
|
return StrongLinkage;
|
|
return StrongLinkage;
|
|
|
|
|
|
case TSK_ExplicitSpecialization:
|
|
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 is non-conforming, since another TU could use an extern
|
|
|
|
+ // template declaration for this variable, but for constexpr variables,
|
|
|
|
+ // it's unlikely for a user to want to do that. 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:
|
|
case TSK_ExplicitInstantiationDefinition:
|
|
return GVA_StrongODR;
|
|
return GVA_StrongODR;
|