Index: clang/include/clang/Basic/TargetInfo.h =================================================================== --- clang/include/clang/Basic/TargetInfo.h +++ clang/include/clang/Basic/TargetInfo.h @@ -1092,6 +1092,13 @@ /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } + /// Does this target aim for source level compatibility with + /// Microsoft C++ code using dllimport/export attributes? + virtual bool shouldDLLImportComdatSymbols() const { + return getTriple().isWindowsMSVCEnvironment() || + getTriple().isWindowsItaniumEnvironment() || getTriple().isPS4CPU(); + } + /// An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// Index: clang/lib/CodeGen/ItaniumCXXABI.cpp =================================================================== --- clang/lib/CodeGen/ItaniumCXXABI.cpp +++ clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -3198,7 +3198,7 @@ return false; if (CGM.getVTables().isVTableExternal(RD)) - return IsDLLImport && !CGM.getTriple().isWindowsItaniumEnvironment() + return IsDLLImport && !CGM.getTarget().shouldDLLImportComdatSymbols() ? false : true; @@ -3455,7 +3455,7 @@ const CXXRecordDecl *RD = cast(Record->getDecl()); if (RD->hasAttr()) return llvm::GlobalValue::WeakODRLinkage; - if (CGM.getTriple().isWindowsItaniumEnvironment()) + if (CGM.getTarget().shouldDLLImportComdatSymbols()) if (RD->hasAttr() && ShouldUseExternalRTTIDescriptor(CGM, Ty)) return llvm::GlobalValue::ExternalLinkage; @@ -3513,7 +3513,7 @@ llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass = llvm::GlobalValue::DefaultStorageClass; - if (CGM.getTriple().isWindowsItaniumEnvironment()) { + if (CGM.getTarget().shouldDLLImportComdatSymbols()) { auto RD = Ty->getAsCXXRecordDecl(); if (RD && RD->hasAttr()) DLLStorageClass = llvm::GlobalValue::DLLExportStorageClass; Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6775,16 +6775,14 @@ static void handleDLLAttr(Sema &S, Decl *D, const ParsedAttr &A) { if (isa(D) && - (S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + (S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored) << A; return; } if (const auto *FD = dyn_cast(D)) { if (FD->isInlined() && A.getKind() == ParsedAttr::AT_DLLImport && - !(S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + !(S.Context.getTargetInfo().shouldDLLImportComdatSymbols())) { // MinGW doesn't allow dllimport on inline functions. S.Diag(A.getRange().getBegin(), diag::warn_attribute_ignored_on_inline) << A; @@ -6793,8 +6791,7 @@ } if (const auto *MD = dyn_cast(D)) { - if ((S.Context.getTargetInfo().getCXXABI().isMicrosoft() || - S.Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && + if ((S.Context.getTargetInfo().shouldDLLImportComdatSymbols()) && MD->getParent()->isLambda()) { S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A; return; Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -6071,8 +6071,8 @@ Attr *ClassAttr = getDLLAttr(Class); // MSVC inherits DLL attributes to partial class template specializations. - if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && !ClassAttr) { + if (Context.getTargetInfo().getTarget().shouldDLLImportComdatSymbols() && + !ClassAttr) { if (auto *Spec = dyn_cast(Class)) { if (Attr *TemplateAttr = getDLLAttr(Spec->getSpecializedTemplate()->getTemplatedDecl())) { @@ -6092,8 +6092,7 @@ return; } - if ((Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment()) && + if (Context.getTargetInfo().shouldDLLImportComdatSymbols() && !ClassAttr->isInherited()) { // Diagnose dll attributes on members of class with dll attribute. for (Decl *Member : Class->decls()) { @@ -6158,8 +6157,7 @@ if (MD->isInlined()) { // MinGW does not import or export inline methods. But do it for // template instantiations. - if (!Context.getTargetInfo().getCXXABI().isMicrosoft() && - !Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment() && + if (!Context.getTargetInfo().shouldDLLImportComdatSymbols() && TSK != TSK_ExplicitInstantiationDeclaration && TSK != TSK_ExplicitInstantiationDefinition) continue; Index: clang/lib/Sema/SemaTemplate.cpp =================================================================== --- clang/lib/Sema/SemaTemplate.cpp +++ clang/lib/Sema/SemaTemplate.cpp @@ -9759,8 +9759,7 @@ Def->setTemplateSpecializationKind(TSK); if (!getDLLAttr(Def) && getDLLAttr(Specialization) && - (Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // In the MS ABI, an explicit instantiation definition can add a dll // attribute to a template with a previous instantiation declaration. // MinGW doesn't allow this. @@ -9777,8 +9776,7 @@ bool NewlyDLLExported = !PreviouslyDLLExported && Specialization->hasAttr(); if (Old_TSK == TSK_ImplicitInstantiation && NewlyDLLExported && - (Context.getTargetInfo().getCXXABI().isMicrosoft() || - Context.getTargetInfo().getTriple().isWindowsItaniumEnvironment())) { + Context.getTargetInfo().shouldDLLImportComdatSymbols()) { // In the MS ABI, an explicit instantiation definition can add a dll // attribute to a template with a previous implicit instantiation. // MinGW doesn't allow this. We limit clang to only adding dllexport, to