}
// Finally, set up the alias with its proper name and attributes.
- setAliasAttributes(AliasDecl, Alias);
+ SetCommonAttributes(AliasDecl, Alias);
return false;
}
}
setFunctionLinkage(GD, Fn);
- setFunctionDLLStorageClass(GD, Fn);
CodeGenFunction(*this).GenerateCode(GD, Fn, FnInfo);
setNonAliasAttributes(GD, Fn);
/// base tables.
virtual void emitVirtualInheritanceTables(const CXXRecordDecl *RD) = 0;
+ virtual bool exportThunk() = 0;
virtual void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
GlobalDecl GD, bool ReturnAdjustment) = 0;
if (D.getTLSKind())
setTLSMode(GV, D);
- if (D.isExternallyVisible()) {
- if (D.hasAttr<DLLImportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (D.hasAttr<DLLExportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- }
-
setGVProperties(GV, &D);
// Make sure the result is of the correct type.
const ObjCInterfaceDecl *OID) {
auto *Value =
GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported());
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) {
- auto DLLStorage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->hasAttr<DLLExportAttr>())
- DLLStorage = llvm::GlobalValue::DLLExportStorageClass;
- else if (OID->hasAttr<DLLImportAttr>())
- DLLStorage = llvm::GlobalValue::DLLImportStorageClass;
- ClassSymbol->setDLLStorageClass(DLLStorage);
- }
- }
+ if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value))
+ CGM.setGVProperties(ClassSymbol, OID);
return Value;
}
if ((VD = dyn_cast<VarDecl>(Result)))
break;
- auto DLLStorage = llvm::GlobalValue::DefaultStorageClass;
- if (!VD || VD->hasAttr<DLLImportAttr>())
- DLLStorage = llvm::GlobalValue::DLLImportStorageClass;
- else if (VD->hasAttr<DLLExportAttr>())
- DLLStorage = llvm::GlobalValue::DLLExportStorageClass;
-
- ClassSymbol->setDLLStorageClass(DLLStorage);
+ CGM.setGVProperties(ClassSymbol, VD);
}
}
return Value;
NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0],
GenerateIvarList(empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr,
NULLPtr, ZeroPtr, ZeroPtr, true);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- auto Storage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
- Storage = llvm::GlobalValue::DLLImportStorageClass;
- else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
- Storage = llvm::GlobalValue::DLLExportStorageClass;
- cast<llvm::GlobalValue>(MetaClassStruct)->setDLLStorageClass(Storage);
- }
+ CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct),
+ OID->getClassInterface());
// Generate the class structure
llvm::Constant *ClassStruct = GenerateClassStructure(
llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList,
GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
StrongIvarBitmap, WeakIvarBitmap);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- auto Storage = llvm::GlobalValue::DefaultStorageClass;
- if (OID->getClassInterface()->hasAttr<DLLImportAttr>())
- Storage = llvm::GlobalValue::DLLImportStorageClass;
- else if (OID->getClassInterface()->hasAttr<DLLExportAttr>())
- Storage = llvm::GlobalValue::DLLExportStorageClass;
- cast<llvm::GlobalValue>(ClassStruct)->setDLLStorageClass(Storage);
- }
+ CGM.setGVProperties(cast<llvm::GlobalValue>(ClassStruct),
+ OID->getClassInterface());
// Resolve the class aliases, if they exist.
if (ClassPtrAlias) {
llvm::GlobalVariable *MetaTClass =
BuildClassObject(CI, /*metaclass*/ true,
IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLExportAttr>())
- MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(MetaTClass, CI);
DefinedMetaClasses.push_back(MetaTClass);
// Metadata for the class
llvm::GlobalVariable *ClassMD =
BuildClassObject(CI, /*metaclass*/ false,
MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (CI->hasAttr<DLLExportAttr>())
- ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(ClassMD, CI);
DefinedClasses.push_back(ClassMD);
ImplementedClasses.push_back(CI);
Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
false, llvm::GlobalValue::ExternalLinkage,
nullptr, EHTypeName);
- if (CGM.getTriple().isOSBinFormatCOFF()) {
- if (ID->hasAttr<DLLExportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
- else if (ID->hasAttr<DLLImportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- }
+ CGM.setGVProperties(Entry, ID);
return Entry;
}
}
CGM.getPointerAlign(),
/*constant*/ false,
L);
- if (CGM.getTriple().isOSBinFormatCOFF())
- if (hasObjCExceptionAttribute(CGM.getContext(), ID))
- if (ID->hasAttr<DLLExportAttr>())
- Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ if (hasObjCExceptionAttribute(CGM.getContext(), ID))
+ CGM.setGVProperties(Entry, ID);
}
assert(Entry->getLinkage() == L);
!Thunk.Return.isEmpty());
// Set the right visibility.
- CGM.setGVProperties(ThunkFn, cast<CXXMethodDecl>(GD.getDecl()));
+ CGM.setGVProperties(ThunkFn, GD);
+
+ if (!CGM.getCXXABI().exportThunk()) {
+ ThunkFn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ ThunkFn->setDSOLocal(true);
+ }
if (CGM.supportsCOMDAT() && ThunkFn->isWeakForLinker())
ThunkFn->setComdat(CGM.getModule().getOrInsertComdat(ThunkFn->getName()));
GV->setDSOLocal(true);
}
+void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
+ GlobalDecl GD) const {
+ const auto *D = dyn_cast<NamedDecl>(GD.getDecl());
+ if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(D)) {
+ if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
+ // Don't dllexport/import destructor thunks.
+ GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
+ return;
+ }
+ }
+ setDLLImportDLLExport(GV, D);
+}
+
+void CodeGenModule::setDLLImportDLLExport(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
+ if (D->isExternallyVisible()) {
+ if (D->hasAttr<DLLImportAttr>())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ else if (D->hasAttr<DLLExportAttr>() && !GV->isDeclarationForLinker())
+ GV->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
+ }
+}
+
+void CodeGenModule::setGVProperties(llvm::GlobalValue *GV,
+ GlobalDecl GD) const {
+ setDLLImportDLLExport(GV, GD);
+ setGlobalVisibilityAndLocal(GV, dyn_cast<NamedDecl>(GD.getDecl()));
+}
+
void CodeGenModule::setGVProperties(llvm::GlobalValue *GV,
const NamedDecl *D) const {
+ setDLLImportDLLExport(GV, D);
+ setGlobalVisibilityAndLocal(GV, D);
+}
+
+void CodeGenModule::setGlobalVisibilityAndLocal(llvm::GlobalValue *GV,
+ const NamedDecl *D) const {
setGlobalVisibility(GV, D);
setDSOLocal(GV);
}
return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false);
}
-void CodeGenModule::setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F) {
- const auto *FD = cast<FunctionDecl>(GD.getDecl());
-
- if (const auto *Dtor = dyn_cast_or_null<CXXDestructorDecl>(FD)) {
- if (getCXXABI().useThunkForDtorVariant(Dtor, GD.getDtorType())) {
- // Don't dllexport/import destructor thunks.
- F->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
- return;
- }
- }
-
- if (FD->hasAttr<DLLImportAttr>())
- F->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
- else if (FD->hasAttr<DLLExportAttr>())
- F->setDLLStorageClass(llvm::GlobalVariable::DLLExportStorageClass);
- else
- F->setDLLStorageClass(llvm::GlobalVariable::DefaultStorageClass);
-}
-
llvm::ConstantInt *CodeGenModule::CreateCrossDsoCfiTypeId(llvm::Metadata *MD) {
llvm::MDString *MDS = dyn_cast<llvm::MDString>(MD);
if (!MDS) return nullptr;
void CodeGenModule::SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
const Decl *D = GD.getDecl();
- if (const auto *ND = dyn_cast_or_null<NamedDecl>(D))
- setGVProperties(GV, ND);
+ if (dyn_cast_or_null<NamedDecl>(D))
+ setGVProperties(GV, GD);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
addUsedGlobal(GV);
}
-void CodeGenModule::setAliasAttributes(GlobalDecl GD, llvm::GlobalValue *GV) {
- const Decl *D = GD.getDecl();
- SetCommonAttributes(GD, GV);
-
- // Process the dllexport attribute based on whether the original definition
- // (not necessarily the aliasee) was exported.
- if (D->hasAttr<DLLExportAttr>())
- GV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
-}
-
bool CodeGenModule::GetCPUAndFeaturesAttributes(const Decl *D,
llvm::AttrBuilder &Attrs) {
// Add target-cpu and target-features attributes to functions. If
setNonAliasAttributes(GD, F);
}
-static void setLinkageForGV(llvm::GlobalValue *GV,
- const NamedDecl *ND) {
+static void setLinkageForGV(llvm::GlobalValue *GV, const NamedDecl *ND) {
// Set linkage and visibility in case we never see a definition.
LinkageInfo LV = ND->getLinkageAndVisibility();
- if (!isExternallyVisible(LV.getLinkage())) {
- // Don't set internal linkage on declarations.
- } else {
- if (ND->hasAttr<DLLImportAttr>()) {
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- GV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- } else if (ND->hasAttr<DLLExportAttr>()) {
- GV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else if (ND->hasAttr<WeakAttr>() || ND->isWeakImported()) {
- // "extern_weak" is overloaded in LLVM; we probably should have
- // separate linkage types for this.
- GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- }
- }
+ // Don't set internal linkage on declarations.
+ // "extern_weak" is overloaded in LLVM; we probably should have
+ // separate linkage types for this.
+ if (isExternallyVisible(LV.getLinkage()) &&
+ (ND->hasAttr<WeakAttr>() || ND->isWeakImported()))
+ GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
}
void CodeGenModule::CreateFunctionTypeMetadata(const FunctionDecl *FD,
// declarations).
auto *Fn = cast<llvm::Function>(GV);
setFunctionLinkage(GD, Fn);
- setFunctionDLLStorageClass(GD, Fn);
// FIXME: this is redundant with part of setFunctionDefinitionAttributes
- setGVProperties(Fn, D);
+ setGVProperties(Fn, GD);
MaybeHandleStaticInExternC(D, Fn);
if (VD->getTLSKind())
setTLSMode(GA, *VD);
- setAliasAttributes(GD, GA);
+ SetCommonAttributes(GD, GA);
}
void CodeGenModule::emitIFuncDefinition(GlobalDecl GD) {
/// Set the visibility for the given LLVM GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
+ void setGlobalVisibilityAndLocal(llvm::GlobalValue *GV,
+ const NamedDecl *D) const;
+
void setDSOLocal(llvm::GlobalValue *GV) const;
- /// Set visibility and dso_local.
+ void setDLLImportDLLExport(llvm::GlobalValue *GV, GlobalDecl D) const;
+ void setDLLImportDLLExport(llvm::GlobalValue *GV, const NamedDecl *D) const;
+ /// Set visibility, dllimport/dllexport and dso_local.
/// This must be called after dllimport/dllexport is set.
- /// FIXME: should this set dllimport/dllexport instead?
+ void setGVProperties(llvm::GlobalValue *GV, GlobalDecl GD) const;
void setGVProperties(llvm::GlobalValue *GV, const NamedDecl *D) const;
/// Set the TLS mode for the given LLVM GlobalValue for the thread-local
F->setLinkage(getFunctionLinkage(GD));
}
- /// Set the DLL storage class on F.
- void setFunctionDLLStorageClass(GlobalDecl GD, llvm::Function *F);
-
/// Return the appropriate linkage for the vtable, VTT, and type information
/// of the given class.
llvm::GlobalVariable::LinkageTypes getVTableLinkage(const CXXRecordDecl *RD);
/// NOTE: This should only be called for definitions.
void SetCommonAttributes(GlobalDecl GD, llvm::GlobalValue *GV);
- /// Set attributes which must be preserved by an alias. This includes common
- /// attributes (i.e. it includes a call to SetCommonAttributes).
- ///
- /// NOTE: This should only be called for definitions.
- void setAliasAttributes(GlobalDecl GD, llvm::GlobalValue *GV);
-
void addReplacement(StringRef Name, llvm::Constant *C);
void addGlobalValReplacement(llvm::GlobalValue *GV, llvm::Constant *C);
// linkage together with vtables when needed.
if (ForVTable && !Thunk->hasLocalLinkage())
Thunk->setLinkage(llvm::GlobalValue::AvailableExternallyLinkage);
-
- // Propagate dllexport storage, to enable the linker to generate import
- // thunks as necessary (e.g. when a parent class has a key function and a
- // child class doesn't, and the construction vtable for the parent in the
- // child needs to reference the parent's thunks).
- const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
- if (MD->hasAttr<DLLExportAttr>())
- Thunk->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(Thunk, GD);
}
+ bool exportThunk() override { return true; }
+
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
Name, VTableType, llvm::GlobalValue::ExternalLinkage);
VTable->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
- if (RD->hasAttr<DLLImportAttr>())
- VTable->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
- else if (RD->hasAttr<DLLExportAttr>())
- VTable->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
-
CGM.setGVProperties(VTable, RD);
return VTable;
Name);
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
- if (RD->hasAttr<DLLImportAttr>())
- GV->setDLLStorageClass(llvm::GlobalVariable::DLLImportStorageClass);
+ CGM.setGVProperties(GV, RD);
}
}
}
// Finally, set up the alias with its proper name and attributes.
- CGM.setAliasAttributes(AliasDecl, Alias);
+ CGM.SetCommonAttributes(AliasDecl, Alias);
}
void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
void setThunkLinkage(llvm::Function *Thunk, bool ForVTable,
GlobalDecl GD, bool ReturnAdjustment) override {
- // Never dllimport/dllexport thunks.
- Thunk->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
-
GVALinkage Linkage =
getContext().GetGVALinkageForFunction(cast<FunctionDecl>(GD.getDecl()));
Thunk->setLinkage(llvm::GlobalValue::LinkOnceODRLinkage);
}
+ bool exportThunk() override { return false; }
+
llvm::Value *performThisAdjustment(CodeGenFunction &CGF, Address This,
const ThisAdjustment &TA) override;
if (!hasDefaultCXXMethodCC(getContext(), D) || D->getNumParams() != 0) {
llvm::Function *Fn = getAddrOfCXXCtorClosure(D, Ctor_DefaultClosure);
Fn->setLinkage(llvm::GlobalValue::WeakODRLinkage);
- Fn->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
+ CGM.setGVProperties(Fn, D);
}
}
struct CtorWithClosure {
__declspec(dllexport) CtorWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.CtorWithClosure*, align 4
// CHECK: store %struct.CtorWithClosure* %this, %struct.CtorWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.CtorWithClosure*, %struct.CtorWithClosure** %[[this_addr]]
__declspec(dllexport) CtorWithClosureOutOfLine(...);
};
CtorWithClosureOutOfLine::CtorWithClosureOutOfLine(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorWithClosureOutOfLine@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
#define DELETE_IMPLICIT_MEMBERS(ClassName) \
ClassName(ClassName &&) = delete; \
struct __declspec(dllexport) ClassWithClosure {
DELETE_IMPLICIT_MEMBERS(ClassWithClosure);
ClassWithClosure(...) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FClassWithClosure@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: %[[this_addr:.*]] = alloca %struct.ClassWithClosure*, align 4
// CHECK: store %struct.ClassWithClosure* %this, %struct.ClassWithClosure** %[[this_addr]], align 4
// CHECK: %[[this:.*]] = load %struct.ClassWithClosure*, %struct.ClassWithClosure** %[[this_addr]]
extern template struct TemplateWithClosure<int>;
template struct __declspec(dllexport) TemplateWithClosure<int>;
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@D@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@D@@QAE@H@Z"({{.*}}, i32 1)
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$TemplateWithClosure@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
// CHECK: call {{.*}} @"\01??0?$TemplateWithClosure@H@@QAE@H@Z"({{.*}}, i32 4)
struct __declspec(dllexport) NestedOuter {
};
};
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct HasDtor {
~HasDtor();
};
CtorClosureOutOfLine::CtorClosureOutOfLine(const HasImplicitDtor2 &v) {}
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureInline@@QAEXXZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorClosureInline@@QAEXXZ"
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??1HasImplicitDtor1@@QAE@XZ"
-// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureOutOfLine@@QAEXXZ"
+// CHECK-LABEL: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FCtorClosureOutOfLine@@QAEXXZ"
// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"\01??1HasImplicitDtor2@@QAE@XZ"
// MSVC2013-DAG: define weak_odr dso_local dllexport {{.+}} @"\01??4?$SomeTemplate@H@@Q{{.+}}0@A{{.+}}0@@Z"
struct __declspec(dllexport) InheritFromTemplate : SomeTemplate<int> {};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_F?$SomeTemplate@H@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
namespace PR23801 {
template <typename>
}
//
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FB@PR23801@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
struct __declspec(dllexport) T {
// Copy assignment operator:
B(int = 0) {}
A<int> m_fn1() {}
};
-// M32-DAG: define weak_odr dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ"
+// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc void @"\01??_FB@pr26490@@QAEXXZ"
}
// dllexport trumps dllimport on an explicit instantiation.
@interface J : I
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_J" = dllexport global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_J" = dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_J" = dso_local dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_J" = dso_local dllexport global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_J = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_J = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_J = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_J = dso_local dllexport global
@implementation J {
id _ivar;
@interface K : J
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_K" = global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_K" = global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_K" = dso_local global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_K" = dso_local global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_K = global
-// CHECK-FW-DAG: @_OBJC_CLASS_K = global
+// CHECK-FW-DAG: @_OBJC_METACLASS_K = dso_local global
+// CHECK-FW-DAG: @_OBJC_CLASS_K = dso_local global
@implementation K {
id _ivar;
@interface L : K
@end
-// CHECK-IR-DAG: @"OBJC_METACLASS_$_L" = dllexport global %struct._class_t
-// CHECK-IR-DAG: @"OBJC_CLASS_$_L" = dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_METACLASS_$_L" = dso_local dllexport global %struct._class_t
+// CHECK-IR-DAG: @"OBJC_CLASS_$_L" = dso_local dllexport global %struct._class_t
-// CHECK-FW-DAG: @_OBJC_METACLASS_L = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_L = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_L = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_L = dso_local dllexport global
@implementation L {
id _none;
@interface N : I
@end
-// CHECK-FW-DAG: @_OBJC_METACLASS_N = dllexport global
-// CHECK-FW-DAG: @_OBJC_CLASS_N = dllexport global
+// CHECK-FW-DAG: @_OBJC_METACLASS_N = dso_local dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_N = dso_local dllexport global
@implementation N : I
@end
-// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dllexport global %struct._objc_typeinfo
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dso_local dllexport global %struct._objc_typeinfo
__declspec(dllimport)
__attribute__((__objc_exception__))
@interface P : I
@end
-// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external global %struct._objc_typeinfo
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external dso_local global %struct._objc_typeinfo
@interface Q : M
@end
// Demangles as:
// void Foo::`default constructor closure'(void)
-// CHECK: define weak_odr dllexport void @"\01??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
+// CHECK: define weak_odr dso_local dllexport void @"\01??_FFoo@@QEAAXXZ"(%struct.Foo*{{.*}})
// CHECK: call %struct.Foo* @"\01??0Foo@@QEAA@W4E@0@@Z"(%struct.Foo* {{.*}}, i32 0)
#else