[clang] e11ede5 - Revert "[MS][clang] Add support for vector deleting destructors (#126240)"
Hans Wennborg via cfe-commits
cfe-commits at lists.llvm.org
Wed Mar 12 08:26:11 PDT 2025
Author: Hans Wennborg
Date: 2025-03-12T16:26:00+01:00
New Revision: e11ede5e90ee193dde179fe1a9ac9af718ede3db
URL: https://github.com/llvm/llvm-project/commit/e11ede5e90ee193dde179fe1a9ac9af718ede3db
DIFF: https://github.com/llvm/llvm-project/commit/e11ede5e90ee193dde179fe1a9ac9af718ede3db.diff
LOG: Revert "[MS][clang] Add support for vector deleting destructors (#126240)"
This caused link errors when building with sancov. See comment on the PR.
> Whereas it is UB in terms of the standard to delete an array of objects
> via pointer whose static type doesn't match its dynamic type, MSVC
> supports an extension allowing to do it.
> Aside from array deletion not working correctly in the mentioned case,
> currently not having this extension implemented causes clang to generate
> code that is not compatible with the code generated by MSVC, because
> clang always puts scalar deleting destructor to the vftable. This PR
> aims to resolve these problems.
>
> Fixes https://github.com/llvm/llvm-project/issues/19772
This reverts commit d6942d54f677000cf713d2b0eba57b641452beb4.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/VTableBuilder.h
clang/include/clang/Basic/ABI.h
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/MicrosoftMangle.cpp
clang/lib/AST/VTableBuilder.cpp
clang/lib/CodeGen/CGCXX.cpp
clang/lib/CodeGen/CGCXXABI.cpp
clang/lib/CodeGen/CGCXXABI.h
clang/lib/CodeGen/CGClass.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CGExprCXX.cpp
clang/lib/CodeGen/CGVTables.cpp
clang/lib/CodeGen/CodeGenModule.cpp
clang/lib/CodeGen/CodeGenModule.h
clang/lib/CodeGen/ItaniumCXXABI.cpp
clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/test/CodeGenCXX/debug-info-windows-dtor.cpp
clang/test/CodeGenCXX/dllexport.cpp
clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp
clang/test/CodeGenCXX/microsoft-abi-structors.cpp
clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp
clang/test/CodeGenCXX/vtable-consteval.cpp
clang/test/Modules/vtable-windows.cppm
clang/test/Profile/cxx-abc-deleting-dtor.cpp
Removed:
clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f6e4d6a34e5dc..e16cfc69590fa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -357,8 +357,6 @@ Android Support
Windows Support
^^^^^^^^^^^^^^^
-- Clang now supports MSVC vector deleting destructors (GH19772).
-
LoongArch Support
^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/VTableBuilder.h b/clang/include/clang/AST/VTableBuilder.h
index e1efe8cddcc5e..a5de41dbc22f1 100644
--- a/clang/include/clang/AST/VTableBuilder.h
+++ b/clang/include/clang/AST/VTableBuilder.h
@@ -150,7 +150,7 @@ class VTableComponent {
bool isRTTIKind() const { return isRTTIKind(getKind()); }
- GlobalDecl getGlobalDecl(bool HasVectorDeletingDtors) const {
+ GlobalDecl getGlobalDecl() const {
assert(isUsedFunctionPointerKind() &&
"GlobalDecl can be created only from virtual function");
@@ -161,9 +161,7 @@ class VTableComponent {
case CK_CompleteDtorPointer:
return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Complete);
case CK_DeletingDtorPointer:
- return GlobalDecl(DtorDecl, (HasVectorDeletingDtors)
- ? CXXDtorType::Dtor_VectorDeleting
- : CXXDtorType::Dtor_Deleting);
+ return GlobalDecl(DtorDecl, CXXDtorType::Dtor_Deleting);
case CK_VCallOffset:
case CK_VBaseOffset:
case CK_OffsetToTop:
diff --git a/clang/include/clang/Basic/ABI.h b/clang/include/clang/Basic/ABI.h
index 48969e4f295c3..231bad799a42c 100644
--- a/clang/include/clang/Basic/ABI.h
+++ b/clang/include/clang/Basic/ABI.h
@@ -31,11 +31,10 @@ enum CXXCtorType {
/// C++ destructor types.
enum CXXDtorType {
- Dtor_Deleting, ///< Deleting dtor
- Dtor_Complete, ///< Complete object dtor
- Dtor_Base, ///< Base object dtor
- Dtor_Comdat, ///< The COMDAT used for dtors
- Dtor_VectorDeleting ///< Vector deleting dtor
+ Dtor_Deleting, ///< Deleting dtor
+ Dtor_Complete, ///< Complete object dtor
+ Dtor_Base, ///< Base object dtor
+ Dtor_Comdat ///< The COMDAT used for dtors
};
} // end namespace clang
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index b80dd1c86092f..b6ba36784f38a 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -6014,8 +6014,6 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Comdat:
Out << "D5";
break;
- case Dtor_VectorDeleting:
- llvm_unreachable("Itanium ABI does not use vector deleting dtors");
}
}
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 6e2be2557d0a7..fe34251688a98 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -1484,9 +1484,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_G # scalar deleting destructor
case Dtor_Deleting: Out << "?_G"; return;
// <operator-name> ::= ?_E # vector deleting destructor
- case Dtor_VectorDeleting:
- Out << "?_E";
- return;
+ // FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
+ // it.
case Dtor_Comdat:
llvm_unreachable("not expecting a COMDAT");
}
@@ -2887,12 +2886,9 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T,
// ::= @ # structors (they have no declared return type)
if (IsStructor) {
if (isa<CXXDestructorDecl>(D) && isStructorDecl(D)) {
- // The deleting destructors take an extra argument of type int that
- // indicates whether the storage for the object should be deleted and
- // whether a single object or an array of objects is being destroyed. This
- // extra argument is not reflected in the AST.
- if (StructorType == Dtor_Deleting ||
- StructorType == Dtor_VectorDeleting) {
+ // The scalar deleting destructor takes an extra int argument which is not
+ // reflected in the AST.
+ if (StructorType == Dtor_Deleting) {
Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
return;
}
@@ -3865,10 +3861,10 @@ void MicrosoftMangleContextImpl::mangleCXXDtorThunk(const CXXDestructorDecl *DD,
const ThunkInfo &Thunk,
bool /*ElideOverrideInfo*/,
raw_ostream &Out) {
- // The dtor thunk should use vector deleting dtor mangling, however as an
- // optimization we may end up emitting only scalar deleting dtor body, so just
- // use the vector deleting dtor mangling manually.
- assert(Type == Dtor_Deleting || Type == Dtor_VectorDeleting);
+ // FIXME: Actually, the dtor thunk should be emitted for vector deleting
+ // dtors rather than scalar deleting dtors. Just use the vector deleting dtor
+ // mangling manually until we support both deleting dtor types.
+ assert(Type == Dtor_Deleting);
msvc_hashing_ostream MHO(Out);
MicrosoftCXXNameMangler Mangler(*this, MHO, DD, Type);
Mangler.getStream() << "??_E";
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index b7c6ad85b8889..18893b996b5d6 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -1735,8 +1735,8 @@ void ItaniumVTableBuilder::LayoutPrimaryAndSecondaryVTables(
const CXXMethodDecl *MD = I.first;
const MethodInfo &MI = I.second;
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)] =
- MI.VTableIndex - AddressPoint;
+ MethodVTableIndices[GlobalDecl(DD, Dtor_Complete)]
+ = MI.VTableIndex - AddressPoint;
MethodVTableIndices[GlobalDecl(DD, Dtor_Deleting)]
= MI.VTableIndex + 1 - AddressPoint;
} else {
@@ -2657,11 +2657,7 @@ class VFTableBuilder {
MethodVFTableLocation Loc(MI.VBTableIndex, WhichVFPtr.getVBaseWithVPtr(),
WhichVFPtr.NonVirtualOffset, MI.VFTableIndex);
if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(MD)) {
- // In Microsoft ABI vftable always references vector deleting dtor.
- CXXDtorType DtorTy = Context.getTargetInfo().getCXXABI().isMicrosoft()
- ? Dtor_VectorDeleting
- : Dtor_Deleting;
- MethodVFTableLocations[GlobalDecl(DD, DtorTy)] = Loc;
+ MethodVFTableLocations[GlobalDecl(DD, Dtor_Deleting)] = Loc;
} else {
MethodVFTableLocations[MD] = Loc;
}
@@ -3291,10 +3287,7 @@ void VFTableBuilder::dumpLayout(raw_ostream &Out) {
const CXXDestructorDecl *DD = Component.getDestructorDecl();
DD->printQualifiedName(Out);
- if (Context.getTargetInfo().getCXXABI().isMicrosoft())
- Out << "() [vector deleting]";
- else
- Out << "() [scalar deleting]";
+ Out << "() [scalar deleting]";
if (DD->isPureVirtual())
Out << " [pure]";
@@ -3765,7 +3758,7 @@ void MicrosoftVTableContext::dumpMethodLocations(
PredefinedIdentKind::PrettyFunctionNoVirtual, MD);
if (isa<CXXDestructorDecl>(MD)) {
- IndicesMap[I.second] = MethodName + " [vector deleting]";
+ IndicesMap[I.second] = MethodName + " [scalar deleting]";
} else {
IndicesMap[I.second] = MethodName;
}
@@ -3882,7 +3875,7 @@ MicrosoftVTableContext::getMethodVFTableLocation(GlobalDecl GD) {
assert(hasVtableSlot(cast<CXXMethodDecl>(GD.getDecl())) &&
"Only use this method for virtual methods or dtors");
if (isa<CXXDestructorDecl>(GD.getDecl()))
- assert(GD.getDtorType() == Dtor_VectorDeleting);
+ assert(GD.getDtorType() == Dtor_Deleting);
GD = GD.getCanonicalDecl();
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 6f47e24eed5b3..78a7b021855b7 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -175,6 +175,7 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// requires explicit comdat support in the IL.
if (llvm::GlobalValue::isWeakForLinker(TargetLinkage))
return true;
+
// Create the alias with no name.
auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
Aliasee, &getModule());
@@ -200,42 +201,6 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
return false;
}
-/// Emit a definition as a global alias for another definition, unconditionally.
-void CodeGenModule::EmitDefinitionAsAlias(GlobalDecl AliasDecl,
- GlobalDecl TargetDecl) {
-
- llvm::Type *AliasValueType = getTypes().GetFunctionType(AliasDecl);
-
- StringRef MangledName = getMangledName(AliasDecl);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- if (Entry && !Entry->isDeclaration())
- return;
- auto *Aliasee = cast<llvm::GlobalValue>(GetAddrOfGlobal(TargetDecl));
-
- // Determine the linkage type for the alias.
- llvm::GlobalValue::LinkageTypes Linkage = getFunctionLinkage(AliasDecl);
-
- // Create the alias with no name.
- auto *Alias = llvm::GlobalAlias::create(AliasValueType, 0, Linkage, "",
- Aliasee, &getModule());
- // Destructors are always unnamed_addr.
- Alias->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
-
- if (Entry) {
- assert(Entry->getValueType() == AliasValueType &&
- Entry->getAddressSpace() == Alias->getAddressSpace() &&
- "declaration exists with
diff erent type");
- Alias->takeName(Entry);
- Entry->replaceAllUsesWith(Alias);
- Entry->eraseFromParent();
- } else {
- Alias->setName(MangledName);
- }
-
- // Set any additional necessary attributes for the alias.
- SetCommonAttributes(AliasDecl, Alias);
-}
-
llvm::Function *CodeGenModule::codegenCXXStructor(GlobalDecl GD) {
const CGFunctionInfo &FnInfo = getTypes().arrangeCXXStructorDeclaration(GD);
auto *Fn = cast<llvm::Function>(
diff --git a/clang/lib/CodeGen/CGCXXABI.cpp b/clang/lib/CodeGen/CGCXXABI.cpp
index e109fd0c443f6..7c6dfc3e59d8c 100644
--- a/clang/lib/CodeGen/CGCXXABI.cpp
+++ b/clang/lib/CodeGen/CGCXXABI.cpp
@@ -273,20 +273,6 @@ void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
}
-void CGCXXABI::ReadArrayCookie(CodeGenFunction &CGF, Address ptr,
- QualType eltTy, llvm::Value *&numElements,
- llvm::Value *&allocPtr, CharUnits &cookieSize) {
- assert(eltTy.isDestructedType());
-
- // Derive a char* in the same address space as the pointer.
- ptr = ptr.withElementType(CGF.Int8Ty);
-
- cookieSize = getArrayCookieSizeImpl(eltTy);
- Address allocAddr = CGF.Builder.CreateConstInBoundsByteGEP(ptr, -cookieSize);
- allocPtr = allocAddr.emitRawPointer(CGF);
- numElements = readArrayCookieImpl(CGF, allocAddr, cookieSize);
-}
-
llvm::Value *CGCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
Address ptr,
CharUnits cookieSize) {
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h
index 148a7ba6df7e6..687ff7fb84444 100644
--- a/clang/lib/CodeGen/CGCXXABI.h
+++ b/clang/lib/CodeGen/CGCXXABI.h
@@ -275,7 +275,6 @@ class CGCXXABI {
virtual CatchTypeInfo getCatchAllTypeInfo();
virtual bool shouldTypeidBeNullChecked(QualType SrcRecordTy) = 0;
- virtual bool hasVectorDeletingDtors() = 0;
virtual void EmitBadTypeidCall(CodeGenFunction &CGF) = 0;
virtual llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
Address ThisPtr,
@@ -576,12 +575,6 @@ class CGCXXABI {
QualType ElementType, llvm::Value *&NumElements,
llvm::Value *&AllocPtr, CharUnits &CookieSize);
- /// Reads the array cookie associated with the given pointer,
- /// that should have one.
- void ReadArrayCookie(CodeGenFunction &CGF, Address Ptr, QualType ElementType,
- llvm::Value *&NumElements, llvm::Value *&AllocPtr,
- CharUnits &CookieSize);
-
/// Return whether the given global decl needs a VTT parameter.
virtual bool NeedsVTTParameter(GlobalDecl GD);
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index e54fd543f217b..fa69caa41936c 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1433,70 +1433,6 @@ static bool CanSkipVTablePointerInitialization(CodeGenFunction &CGF,
return true;
}
-static void EmitConditionalArrayDtorCall(const CXXDestructorDecl *DD,
- CodeGenFunction &CGF,
- llvm::Value *ShouldDeleteCondition) {
- Address ThisPtr = CGF.LoadCXXThisAddress();
- llvm::BasicBlock *ScalarBB = CGF.createBasicBlock("dtor.scalar");
- llvm::BasicBlock *callDeleteBB =
- CGF.createBasicBlock("dtor.call_delete_after_array_destroy");
- llvm::BasicBlock *VectorBB = CGF.createBasicBlock("dtor.vector");
- auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
- llvm::Value *CheckTheBitForArrayDestroy = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 2));
- llvm::Value *ShouldDestroyArray =
- CGF.Builder.CreateIsNull(CheckTheBitForArrayDestroy);
- CGF.Builder.CreateCondBr(ShouldDestroyArray, ScalarBB, VectorBB);
-
- CGF.EmitBlock(VectorBB);
-
- llvm::Value *numElements = nullptr;
- llvm::Value *allocatedPtr = nullptr;
- CharUnits cookieSize;
- QualType EltTy = DD->getThisType()->getPointeeType();
- CGF.CGM.getCXXABI().ReadArrayCookie(CGF, ThisPtr, EltTy, numElements,
- allocatedPtr, cookieSize);
-
- // Destroy the elements.
- QualType::DestructionKind dtorKind = EltTy.isDestructedType();
-
- assert(dtorKind);
- assert(numElements && "no element count for a type with a destructor!");
-
- CharUnits elementSize = CGF.getContext().getTypeSizeInChars(EltTy);
- CharUnits elementAlign =
- ThisPtr.getAlignment().alignmentOfArrayElement(elementSize);
-
- llvm::Value *arrayBegin = ThisPtr.emitRawPointer(CGF);
- llvm::Value *arrayEnd = CGF.Builder.CreateInBoundsGEP(
- ThisPtr.getElementType(), arrayBegin, numElements, "delete.end");
-
- // We already checked that the array is not 0-length before entering vector
- // deleting dtor.
- CGF.emitArrayDestroy(arrayBegin, arrayEnd, EltTy, elementAlign,
- CGF.getDestroyer(dtorKind),
- /*checkZeroLength*/ false, CGF.needsEHCleanup(dtorKind));
-
- llvm::BasicBlock *VectorBBCont = CGF.createBasicBlock("dtor.vector.cont");
- CGF.EmitBlock(VectorBBCont);
-
- llvm::Value *CheckTheBitForDeleteCall = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
-
- llvm::Value *ShouldCallDelete =
- CGF.Builder.CreateIsNull(CheckTheBitForDeleteCall);
- CGF.Builder.CreateCondBr(ShouldCallDelete, CGF.ReturnBlock.getBlock(),
- callDeleteBB);
- CGF.EmitBlock(callDeleteBB);
- const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CGF.CurCodeDecl);
- const CXXRecordDecl *ClassDecl = Dtor->getParent();
- CGF.EmitDeleteCall(Dtor->getOperatorDelete(), allocatedPtr,
- CGF.getContext().getTagDeclType(ClassDecl));
-
- CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
- CGF.EmitBlock(ScalarBB);
-}
-
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -1526,9 +1462,7 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// outside of the function-try-block, which means it's always
// possible to delegate the destructor body to the complete
// destructor. Do so.
- if (DtorType == Dtor_Deleting || DtorType == Dtor_VectorDeleting) {
- if (CXXStructorImplicitParamValue && DtorType == Dtor_VectorDeleting)
- EmitConditionalArrayDtorCall(Dtor, *this, CXXStructorImplicitParamValue);
+ if (DtorType == Dtor_Deleting) {
RunCleanupsScope DtorEpilogue(*this);
EnterDtorCleanups(Dtor, Dtor_Deleting);
if (HaveInsertPoint()) {
@@ -1557,8 +1491,6 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
switch (DtorType) {
case Dtor_Comdat: llvm_unreachable("not expecting a COMDAT");
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
- case Dtor_VectorDeleting:
- llvm_unreachable("already handled vector deleting case");
case Dtor_Complete:
assert((Body || getTarget().getCXXABI().isMicrosoft()) &&
@@ -1641,6 +1573,7 @@ namespace {
return CGF.EmitScalarExpr(ThisArg);
return CGF.LoadCXXThis();
}
+
/// Call the operator delete associated with the current destructor.
struct CallDtorDelete final : EHScopeStack::Cleanup {
CallDtorDelete() {}
@@ -1659,10 +1592,8 @@ namespace {
bool ReturnAfterDelete) {
llvm::BasicBlock *callDeleteBB = CGF.createBasicBlock("dtor.call_delete");
llvm::BasicBlock *continueBB = CGF.createBasicBlock("dtor.continue");
- auto *CondTy = cast<llvm::IntegerType>(ShouldDeleteCondition->getType());
- llvm::Value *CheckTheBit = CGF.Builder.CreateAnd(
- ShouldDeleteCondition, llvm::ConstantInt::get(CondTy, 1));
- llvm::Value *ShouldCallDelete = CGF.Builder.CreateIsNull(CheckTheBit);
+ llvm::Value *ShouldCallDelete
+ = CGF.Builder.CreateIsNull(ShouldDeleteCondition);
CGF.Builder.CreateCondBr(ShouldCallDelete, continueBB, callDeleteBB);
CGF.EmitBlock(callDeleteBB);
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 7020cef875170..c462b02676813 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2119,8 +2119,7 @@ llvm::DISubprogram *CGDebugInfo::CreateCXXMemberFunction(
// Emit MS ABI vftable information. There is only one entry for the
// deleting dtor.
const auto *DD = dyn_cast<CXXDestructorDecl>(Method);
- GlobalDecl GD =
- DD ? GlobalDecl(DD, Dtor_VectorDeleting) : GlobalDecl(Method);
+ GlobalDecl GD = DD ? GlobalDecl(DD, Dtor_Deleting) : GlobalDecl(Method);
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(GD);
VIndex = ML.Index;
diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp
index d4e14f4574b87..f71c18a8041b1 100644
--- a/clang/lib/CodeGen/CGExprCXX.cpp
+++ b/clang/lib/CodeGen/CGExprCXX.cpp
@@ -1209,8 +1209,6 @@ void CodeGenFunction::EmitNewArrayInitializer(
EmitCXXAggrConstructorCall(Ctor, NumElements, CurPtr, CCE,
/*NewPointerIsChecked*/true,
CCE->requiresZeroInitialization());
- if (CGM.getCXXABI().hasVectorDeletingDtors())
- CGM.requireVectorDestructorDefinition(Ctor->getParent());
return;
}
@@ -1914,8 +1912,10 @@ static void EmitDestroyingObjectDelete(CodeGenFunction &CGF,
/// Emit the code for deleting a single object.
/// \return \c true if we started emitting UnconditionalDeleteBlock, \c false
/// if not.
-static bool EmitObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
- Address Ptr, QualType ElementType,
+static bool EmitObjectDelete(CodeGenFunction &CGF,
+ const CXXDeleteExpr *DE,
+ Address Ptr,
+ QualType ElementType,
llvm::BasicBlock *UnconditionalDeleteBlock) {
// C++11 [expr.delete]p3:
// If the static type of the object to be deleted is
diff erent from its
@@ -2131,40 +2131,6 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) {
assert(ConvertTypeForMem(DeleteTy) == Ptr.getElementType());
- if (E->isArrayForm() && CGM.getCXXABI().hasVectorDeletingDtors()) {
- if (auto *RD = DeleteTy->getAsCXXRecordDecl()) {
- auto *Dtor = RD->getDestructor();
- if (Dtor && Dtor->isVirtual()) {
- llvm::Value *NumElements = nullptr;
- llvm::Value *AllocatedPtr = nullptr;
- CharUnits CookieSize;
- llvm::BasicBlock *bodyBB = createBasicBlock("vdtor.call");
- llvm::BasicBlock *doneBB = createBasicBlock("vdtor.nocall");
- // Check array cookie to see if the array has 0 length. Don't call
- // the destructor in that case.
- CGM.getCXXABI().ReadArrayCookie(*this, Ptr, E, DeleteTy, NumElements,
- AllocatedPtr, CookieSize);
-
- auto *CondTy = cast<llvm::IntegerType>(NumElements->getType());
- llvm::Value *isEmpty = Builder.CreateICmpEQ(
- NumElements, llvm::ConstantInt::get(CondTy, 0));
- Builder.CreateCondBr(isEmpty, doneBB, bodyBB);
-
- // Delete cookie for empty array.
- const FunctionDecl *operatorDelete = E->getOperatorDelete();
- EmitBlock(doneBB);
- EmitDeleteCall(operatorDelete, AllocatedPtr, DeleteTy, NumElements,
- CookieSize);
- EmitBranch(DeleteEnd);
-
- EmitBlock(bodyBB);
- if (!EmitObjectDelete(*this, E, Ptr, DeleteTy, DeleteEnd))
- EmitBlock(DeleteEnd);
- return;
- }
- }
- }
-
if (E->isArrayForm()) {
EmitArrayDelete(*this, E, Ptr, DeleteTy);
EmitBlock(DeleteEnd);
diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp
index 66d75efa0a9a0..c9108938bca50 100644
--- a/clang/lib/CodeGen/CGVTables.cpp
+++ b/clang/lib/CodeGen/CGVTables.cpp
@@ -769,8 +769,7 @@ void CodeGenVTables::addVTableComponent(ConstantArrayBuilder &builder,
case VTableComponent::CK_FunctionPointer:
case VTableComponent::CK_CompleteDtorPointer:
case VTableComponent::CK_DeletingDtorPointer: {
- GlobalDecl GD =
- component.getGlobalDecl(CGM.getCXXABI().hasVectorDeletingDtors());
+ GlobalDecl GD = component.getGlobalDecl();
const bool IsThunk =
nextVTableThunkIndex < layout.vtable_thunks().size() &&
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 1f6321a5908e6..f88d6202ad381 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -7939,49 +7939,3 @@ void CodeGenModule::moveLazyEmissionStates(CodeGenModule *NewBuilder) {
NewBuilder->ABI->MangleCtx = std::move(ABI->MangleCtx);
}
-
-bool CodeGenModule::classNeedsVectorDestructor(const CXXRecordDecl *RD) {
- CXXDestructorDecl *Dtor = RD->getDestructor();
- // The compiler can't know if new[]/delete[] will be used outside of the DLL,
- // so just force vector deleting destructor emission if dllexport is present.
- // This matches MSVC behavior.
- if (Dtor && Dtor->isVirtual() && Dtor->isDefined() &&
- Dtor->hasAttr<DLLExportAttr>())
- return true;
-
- assert(getCXXABI().hasVectorDeletingDtors());
- return RequireVectorDeletingDtor.count(RD);
-}
-
-void CodeGenModule::requireVectorDestructorDefinition(const CXXRecordDecl *RD) {
- assert(getCXXABI().hasVectorDeletingDtors());
- RequireVectorDeletingDtor.insert(RD);
-
- // To reduce code size in general case we lazily emit scalar deleting
- // destructor definition and an alias from vector deleting destructor to
- // scalar deleting destructor. It may happen that we first emitted the scalar
- // deleting destructor definition and the alias and then discovered that the
- // definition of the vector deleting destructor is required. Then we need to
- // remove the alias and the scalar deleting destructor and queue vector
- // deleting destructor body for emission. Check if that is the case.
- CXXDestructorDecl *DtorD = RD->getDestructor();
- GlobalDecl ScalarDtorGD(DtorD, Dtor_Deleting);
- StringRef MangledName = getMangledName(ScalarDtorGD);
- llvm::GlobalValue *Entry = GetGlobalValue(MangledName);
- if (Entry && !Entry->isDeclaration()) {
- GlobalDecl VectorDtorGD(DtorD, Dtor_VectorDeleting);
- StringRef VDName = getMangledName(VectorDtorGD);
- llvm::GlobalValue *VDEntry = GetGlobalValue(VDName);
- // It exists and it should be an alias.
- assert(VDEntry && isa<llvm::GlobalAlias>(VDEntry));
- auto *NewFn = llvm::Function::Create(
- cast<llvm::FunctionType>(VDEntry->getValueType()),
- llvm::Function::ExternalLinkage, VDName, &getModule());
- NewFn->takeName(VDEntry);
- VDEntry->replaceAllUsesWith(NewFn);
- VDEntry->eraseFromParent();
- Entry->replaceAllUsesWith(NewFn);
- Entry->eraseFromParent();
- addDeferredDeclToEmit(VectorDtorGD);
- }
-}
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index e7c923834238f..6deb467b2cc9f 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -528,9 +528,6 @@ class CodeGenModule : public CodeGenTypeCache {
/// that we don't re-emit the initializer.
llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition;
- /// To remember which types did require a vector deleting dtor.
- llvm::SmallPtrSet<const CXXRecordDecl *, 16> RequireVectorDeletingDtor;
-
typedef std::pair<OrderGlobalInitsOrStermFinalizers, llvm::Function *>
GlobalInitData;
@@ -1547,7 +1544,6 @@ class CodeGenModule : public CodeGenTypeCache {
void EmitGlobal(GlobalDecl D);
bool TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D);
- void EmitDefinitionAsAlias(GlobalDecl Alias, GlobalDecl Target);
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
@@ -1815,8 +1811,6 @@ class CodeGenModule : public CodeGenTypeCache {
// behavior. So projects like the Linux kernel can rely on it.
return !getLangOpts().CPlusPlus;
}
- void requireVectorDestructorDefinition(const CXXRecordDecl *RD);
- bool classNeedsVectorDestructor(const CXXRecordDecl *RD);
private:
bool shouldDropDLLAttribute(const Decl *D, const llvm::GlobalValue *GV) const;
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index b145da0f0ec09..7e26a0da3d7d2 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -90,8 +90,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
case Dtor_Comdat:
llvm_unreachable("emitting dtor comdat as function?");
- case Dtor_VectorDeleting:
- llvm_unreachable("unexpected dtor kind for this ABI");
}
llvm_unreachable("bad dtor kind");
}
@@ -181,7 +179,6 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
}
bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override;
- bool hasVectorDeletingDtors() override { return false; }
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
Address ThisPtr,
@@ -451,8 +448,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
if (!IsInlined)
continue;
- StringRef Name = CGM.getMangledName(
- VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
+ StringRef Name = CGM.getMangledName(VtableComponent.getGlobalDecl());
auto *Entry = CGM.GetGlobalValue(Name);
// This checks if virtual inline function has already been emitted.
// Note that it is possible that this inline function would be emitted
diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
index 4b55fc3f17bd7..5cb742a92a9bd 100644
--- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp
+++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp
@@ -70,8 +70,8 @@ class MicrosoftCXXABI : public CGCXXABI {
switch (GD.getDtorType()) {
case Dtor_Complete:
case Dtor_Deleting:
- case Dtor_VectorDeleting:
return true;
+
case Dtor_Base:
return false;
@@ -145,7 +145,6 @@ class MicrosoftCXXABI : public CGCXXABI {
}
bool shouldTypeidBeNullChecked(QualType SrcRecordTy) override;
- bool hasVectorDeletingDtors() override { return true; }
void EmitBadTypeidCall(CodeGenFunction &CGF) override;
llvm::Value *EmitTypeid(CodeGenFunction &CGF, QualType SrcRecordTy,
Address ThisPtr,
@@ -261,7 +260,7 @@ class MicrosoftCXXABI : public CGCXXABI {
// There's only Dtor_Deleting in vftable but it shares the this
// adjustment with the base one, so look up the deleting one instead.
- LookupGD = GlobalDecl(DD, Dtor_VectorDeleting);
+ LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
@@ -343,8 +342,8 @@ class MicrosoftCXXABI : public CGCXXABI {
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
CallArgList &CallArgs) override {
- assert(GD.getDtorType() == Dtor_VectorDeleting &&
- "Only vector deleting destructor thunks are available in this ABI");
+ assert(GD.getDtorType() == Dtor_Deleting &&
+ "Only deleting destructor thunks are available in this ABI");
CallArgs.add(RValue::get(getStructorImplicitParamValue(CGF)),
getContext().IntTy);
}
@@ -1091,8 +1090,7 @@ bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
static bool isDeletingDtor(GlobalDecl GD) {
return isa<CXXDestructorDecl>(GD.getDecl()) &&
- (GD.getDtorType() == Dtor_Deleting ||
- GD.getDtorType() == Dtor_VectorDeleting);
+ GD.getDtorType() == Dtor_Deleting;
}
bool MicrosoftCXXABI::hasMostDerivedReturn(GlobalDecl GD) const {
@@ -1345,8 +1343,7 @@ MicrosoftCXXABI::buildStructorSignature(GlobalDecl GD,
AddedStructorArgCounts Added;
// TODO: 'for base' flag
if (isa<CXXDestructorDecl>(GD.getDecl()) &&
- (GD.getDtorType() == Dtor_Deleting ||
- GD.getDtorType() == Dtor_VectorDeleting)) {
+ GD.getDtorType() == Dtor_Deleting) {
// The scalar deleting destructor takes an implicit int parameter.
ArgTys.push_back(getContext().IntTy);
++Added.Suffix;
@@ -1378,7 +1375,7 @@ void MicrosoftCXXABI::setCXXDestructorDLLStorage(llvm::GlobalValue *GV,
CXXDtorType DT) const {
// Deleting destructor variants are never imported or exported. Give them the
// default storage class.
- if (DT == Dtor_Deleting || DT == Dtor_VectorDeleting) {
+ if (DT == Dtor_Deleting) {
GV->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
} else {
const NamedDecl *ND = Dtor;
@@ -1412,12 +1409,6 @@ llvm::GlobalValue::LinkageTypes MicrosoftCXXABI::getCXXDestructorLinkage(
// and are emitted everywhere they are used. They are internal if the class
// is internal.
return llvm::GlobalValue::LinkOnceODRLinkage;
- case Dtor_VectorDeleting:
- // Use the weak, non-ODR linkage for vector deleting destructors to block
- // inlining. This enables an MS ABI code-size saving optimization that
- // allows us to avoid emitting array deletion code when arrays of a given
- // type are not allocated within the final linkage unit.
- return llvm::GlobalValue::WeakAnyLinkage;
case Dtor_Comdat:
llvm_unreachable("MS C++ ABI does not support comdat dtors");
}
@@ -1449,7 +1440,7 @@ MicrosoftCXXABI::getVirtualFunctionPrologueThisAdjustment(GlobalDecl GD) {
// There's no Dtor_Base in vftable but it shares the this adjustment with
// the deleting one, so look it up instead.
- GD = GlobalDecl(DD, Dtor_VectorDeleting);
+ GD = GlobalDecl(DD, Dtor_Deleting);
}
MethodVFTableLocation ML =
@@ -1498,7 +1489,7 @@ Address MicrosoftCXXABI::adjustThisArgumentForVirtualFunctionCall(
// There's only Dtor_Deleting in vftable but it shares the this adjustment
// with the base one, so look up the deleting one instead.
- LookupGD = GlobalDecl(DD, Dtor_VectorDeleting);
+ LookupGD = GlobalDecl(DD, Dtor_Deleting);
}
MethodVFTableLocation ML =
CGM.getMicrosoftVTableContext().getMethodVFTableLocation(LookupGD);
@@ -2011,20 +2002,20 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
auto *D = dyn_cast<const CXXDeleteExpr *>(E);
assert((CE != nullptr) ^ (D != nullptr));
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
- assert(DtorType == Dtor_VectorDeleting || DtorType == Dtor_Complete ||
- DtorType == Dtor_Deleting);
+ assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
// We have only one destructor in the vftable but can get both behaviors
// by passing an implicit int parameter.
- GlobalDecl GD(Dtor, Dtor_VectorDeleting);
+ GlobalDecl GD(Dtor, Dtor_Deleting);
const CGFunctionInfo *FInfo =
&CGM.getTypes().arrangeCXXStructorDeclaration(GD);
llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
ASTContext &Context = getContext();
- uint32_t Flags = ((D && D->isArrayForm()) << 1) | (DtorType == Dtor_Deleting);
- llvm::Value *ImplicitParam = CGF.Builder.getInt32(Flags);
+ llvm::Value *ImplicitParam = llvm::ConstantInt::get(
+ llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
+ DtorType == Dtor_Deleting);
QualType ThisTy;
if (CE) {
@@ -4064,18 +4055,6 @@ void MicrosoftCXXABI::emitCXXStructor(GlobalDecl GD) {
if (GD.getDtorType() == Dtor_Base && !CGM.TryEmitBaseDestructorAsAlias(dtor))
return;
- if (GD.getDtorType() == Dtor_VectorDeleting &&
- !CGM.classNeedsVectorDestructor(dtor->getParent())) {
- // Create GlobalDecl object with the correct type for the scalar
- // deleting destructor.
- GlobalDecl ScalarDtorGD(dtor, Dtor_Deleting);
-
- // Emit an alias from the vector deleting destructor to the scalar deleting
- // destructor.
- CGM.EmitDefinitionAsAlias(GD, ScalarDtorGD);
- return;
- }
-
llvm::Function *Fn = CGM.codegenCXXStructor(GD);
if (Fn->isWeakForLinker())
Fn->setComdat(CGM.getModule().getOrInsertComdat(Fn->getName()));
diff --git a/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp b/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp
index ffef45b9f7d1b..beea56ce7368b 100644
--- a/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp
+++ b/clang/test/CodeGenCXX/debug-info-windows-dtor.cpp
@@ -16,7 +16,7 @@ struct AB: A, B {
template struct AB<int>;
// CHECK: define {{.*}}@"??_E?$AB at H@@W3AEPAXI at Z"({{.*}} !dbg [[THUNK_VEC_DEL_DTOR:![0-9]*]]
-// CHECK: call {{.*}}@"??_E?$AB at H@@UAEPAXI at Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
+// CHECK: call {{.*}}@"??_G?$AB at H@@UAEPAXI at Z"({{.*}}) #{{[0-9]*}}, !dbg [[THUNK_LOC:![0-9]*]]
// CHECK: define
// CHECK: [[THUNK_VEC_DEL_DTOR]] = distinct !DISubprogram
diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp
index 16eaac75e702f..c8ac526f4cbe3 100644
--- a/clang/test/CodeGenCXX/dllexport.cpp
+++ b/clang/test/CodeGenCXX/dllexport.cpp
@@ -631,7 +631,7 @@ struct __declspec(dllexport) Y {
struct __declspec(dllexport) Z { virtual ~Z() {} };
// The scalar deleting dtor does not get exported:
-// M32-DAG: define weak dso_local x86_thiscallcc ptr @"??_EZ@@UAEPAXI at Z"
+// M32-DAG: define linkonce_odr dso_local x86_thiscallcc ptr @"??_GZ@@UAEPAXI at Z"
// The user-defined dtor does get exported:
diff --git a/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp b/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp
index 67df330bc3263..ea12aa64ae305 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-extern-template.cpp
@@ -4,7 +4,7 @@
// own copy the vftable when emitting the available externally constructor.
// CHECK: @"??_7?$Foo at H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [
-// CHECK-SAME: ptr @"??_E?$Foo at H@@UEAAPEAXI at Z"
+// CHECK-SAME: ptr @"??_G?$Foo at H@@UEAAPEAXI at Z"
// CHECK-SAME: ] }, comdat
// CHECK-LABEL: define dso_local noundef ptr @"?f@@YAPEAU?$Foo at H@@XZ"()
diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
index 2ff7391ec8c8f..07abc3d065e5e 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp
@@ -52,8 +52,7 @@ struct C {
// DTORS: store ptr %{{.*}}, ptr %[[RETVAL:retval]]
// DTORS: %[[SHOULD_DELETE_VALUE:[0-9a-z._]+]] = load i32, ptr %[[SHOULD_DELETE_VAR]]
// DTORS: call x86_thiscallcc void @"??1C at basic@@UAE at XZ"(ptr {{[^,]*}} %[[THIS:[0-9a-z]+]])
-// DTORS-NEXT: %[[AND:[0-9]+]] = and i32 %[[SHOULD_DELETE_VALUE]], 1
-// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[AND]], 0
+// DTORS-NEXT: %[[CONDITION:[0-9]+]] = icmp eq i32 %[[SHOULD_DELETE_VALUE]], 0
// DTORS-NEXT: br i1 %[[CONDITION]], label %[[CONTINUE_LABEL:[0-9a-z._]+]], label %[[CALL_DELETE_LABEL:[0-9a-z._]+]]
//
// DTORS: [[CALL_DELETE_LABEL]]
@@ -167,7 +166,7 @@ void foo() {
// DTORS2-LABEL: define linkonce_odr dso_local x86_thiscallcc ptr @"??_EC at dtor_in_second_nvbase@@W3AEPAXI at Z"(ptr %this, i32 %should_call_delete)
// Do an adjustment from B* to C*.
// DTORS2: getelementptr i8, ptr %{{.*}}, i32 -4
-// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc ptr @"??_EC at dtor_in_second_nvbase@@UAEPAXI at Z"
+// DTORS2: %[[CALL:.*]] = tail call x86_thiscallcc ptr @"??_GC at dtor_in_second_nvbase@@UAEPAXI at Z"
// DTORS2: ret ptr %[[CALL]]
}
diff --git a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
index 83ec158ff7f51..38aa81253ccad 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-thunks.cpp
@@ -63,7 +63,8 @@ C::C() {} // Emits vftable and forces thunk generation.
// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_EC@@W3AEPAXI at Z"(ptr noundef %this, i32 noundef %should_call_delete) {{.*}} comdat
// CODEGEN: getelementptr i8, ptr {{.*}}, i32 -4
-// CODEGEN: call x86_thiscallcc noundef ptr @"??_EC@@UAEPAXI at Z"
+// FIXME: should actually call _EC, not _GC.
+// CODEGEN: call x86_thiscallcc noundef ptr @"??_GC@@UAEPAXI at Z"
// CODEGEN: ret
// CODEGEN-LABEL: define linkonce_odr dso_local x86_thiscallcc void @"?public_f at C@@W3AEXXZ"(ptr
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
index 7ceb15e40e582..bc278bdb847fc 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vftables.cpp
@@ -8,38 +8,38 @@ struct S {
virtual ~S();
} s;
-// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4S@@6B@", ptr @"??_ES@@UAEPAXI at Z"] }, comdat($"??_7S@@6B@")
+// RTTI-DAG: [[VTABLE_S:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4S@@6B@", ptr @"??_GS@@UAEPAXI at Z"] }, comdat($"??_7S@@6B@")
// RTTI-DAG: @"??_7S@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_S]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI at Z"] }
+// NO-RTTI-DAG: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GS@@UAEPAXI at Z"] }
struct __declspec(dllimport) U {
virtual ~U();
} u;
-// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4U@@6B@", ptr @"??_EU@@UAEPAXI at Z"] }
+// RTTI-DAG: [[VTABLE_U:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4U@@6B@", ptr @"??_GU@@UAEPAXI at Z"] }
// RTTI-DAG: @"??_SU@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_U]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EU@@UAEPAXI at Z"] }
+// NO-RTTI-DAG: @"??_SU@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GU@@UAEPAXI at Z"] }
struct __declspec(dllexport) V {
virtual ~V();
} v;
-// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4V@@6B@", ptr @"??_EV@@UAEPAXI at Z"] }, comdat($"??_7V@@6B@")
+// RTTI-DAG: [[VTABLE_V:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4V@@6B@", ptr @"??_GV@@UAEPAXI at Z"] }, comdat($"??_7V@@6B@")
// RTTI-DAG: @"??_7V@@6B@" = dllexport unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_V]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EV@@UAEPAXI at Z"] }
+// NO-RTTI-DAG: @"??_7V@@6B@" = weak_odr dllexport unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GV@@UAEPAXI at Z"] }
namespace {
struct W {
virtual ~W() {}
} w;
}
-// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4W@?A0x{{[^@]*}}@@6B@", ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI at Z"] }
+// RTTI-DAG: [[VTABLE_W:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4W@?A0x{{[^@]*}}@@6B@", ptr @"??_GW@?A0x{{[^@]*}}@@UAEPAXI at Z"] }
// RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_W]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_EW@?A0x{{[^@]*}}@@UAEPAXI at Z"] }
+// NO-RTTI-DAG: @"??_7W@?A0x{{[^@]*}}@@6B@" = internal unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GW@?A0x{{[^@]*}}@@UAEPAXI at Z"] }
struct X {};
template <class> struct Y : virtual X {
@@ -49,7 +49,7 @@ template <class> struct Y : virtual X {
extern template class Y<int>;
template Y<int>::Y();
-// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4?$Y at H@@6B@", ptr @"??_E?$Y at H@@UAEPAXI at Z"] }, comdat($"??_7?$Y at H@@6B@")
+// RTTI-DAG: [[VTABLE_Y:@.*]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4?$Y at H@@6B@", ptr @"??_G?$Y at H@@UAEPAXI at Z"] }, comdat($"??_7?$Y at H@@6B@")
// RTTI-DAG: @"??_7?$Y at H@@6B@" = unnamed_addr alias ptr, getelementptr inbounds ({ [2 x ptr] }, ptr [[VTABLE_Y]], i32 0, i32 0, i32 1)
-// NO-RTTI-DAG: @"??_7?$Y at H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_E?$Y at H@@UAEPAXI at Z"] }, comdat
+// NO-RTTI-DAG: @"??_7?$Y at H@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_G?$Y at H@@UAEPAXI at Z"] }, comdat
diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
index 7e9dce18b2797..b54775f6c5dd0 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp
@@ -80,15 +80,6 @@ B::~B() {
// CHECK2: call x86_thiscallcc void @"??1VBase@@UAE at XZ"(ptr {{[^,]*}} %[[VBASE_i8]])
// CHECK2: ret
- // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0B at test2@@QAE at XZ"
- // CHECK2: (ptr {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived)
- // CHECK2: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
- // CHECK2: ret
-
- // CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GD at pr36921@@UAEPAXI at Z"(
- // CHECK2: %[[THIS_RELOAD:.*]] = load ptr, ptr
- // CHECK2: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4
-
// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GB@@UAEPAXI at Z"
// CHECK2: store ptr %{{.*}}, ptr %[[THIS_ADDR:.*]], align 4
// CHECK2: %[[THIS_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_PARAM_i8:.*]], i32 -8
@@ -302,6 +293,11 @@ void callC() { C x; }
// CHECK: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
// CHECK: ret
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??0B at test2@@QAE at XZ"
+// CHECK2: (ptr {{[^,]*}} returned align 4 dereferenceable(4) %this, i32 noundef %is_most_derived)
+// CHECK2: call x86_thiscallcc noundef ptr @"??0A at test2@@QAE at XZ"(ptr {{[^,]*}} %{{.*}})
+// CHECK2: ret
+
}
namespace test3 {
@@ -484,6 +480,9 @@ struct B {
struct C : virtual B {};
struct D : virtual A, C {};
D d;
+// CHECK2-LABEL: define linkonce_odr dso_local x86_thiscallcc noundef ptr @"??_GD at pr36921@@UAEPAXI at Z"(
+// CHECK2: %[[THIS_RELOAD:.*]] = load ptr, ptr
+// CHECK2: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, ptr %[[THIS_RELOAD]], i32 -4
}
namespace issue_60465 {
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
index 74150b0ecb535..a407766f8ed9f 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-multiple-nonvirtual-inheritance-vdtors.cpp
@@ -12,18 +12,18 @@ struct B {
struct C : A, B {
// CHECK-LABEL: VFTable for 'A' in 'C' (2 entries).
- // CHECK-NEXT: 0 | C::~C() [vector deleting]
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-NEXT: 1 | void A::z1()
// CHECK-LABEL: VFTable for 'B' in 'C' (1 entry).
- // CHECK-NEXT: 0 | C::~C() [vector deleting]
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-LABEL: Thunks for 'C::~C()' (1 entry).
// CHECK-NEXT: 0 | [this adjustment: -4 non-virtual]
// CHECK-LABEL: VFTable indices for 'C' (1 entry).
- // CHECK-NEXT: 0 | C::~C() [vector deleting]
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
virtual ~C();
};
@@ -41,7 +41,7 @@ struct E : D, B {
// CHECK-NEXT: 0 | void D::z4()
// CHECK-LABEL: VFTable for 'B' in 'E' (1 entry).
- // CHECK-NEXT: 0 | E::~E() [vector deleting]
+ // CHECK-NEXT: 0 | E::~E() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-LABEL: Thunks for 'E::~E()' (1 entry).
@@ -49,7 +49,7 @@ struct E : D, B {
// CHECK-LABEL: VFTable indices for 'E' (1 entry).
// CHECK-NEXT: -- accessible via vfptr at offset 4 --
- // CHECK-NEXT: 0 | E::~E() [vector deleting]
+ // CHECK-NEXT: 0 | E::~E() [scalar deleting]
};
void build_vftable(E *obj) { delete obj; }
@@ -61,7 +61,7 @@ struct F : D, B {
// CHECK-NEXT: 0 | void D::z4()
// CHECK-LABEL: VFTable for 'B' in 'F' (1 entry).
- // CHECK-NEXT: 0 | F::~F() [vector deleting]
+ // CHECK-NEXT: 0 | F::~F() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-LABEL: Thunks for 'F::~F()' (1 entry).
@@ -69,7 +69,7 @@ struct F : D, B {
// CHECK-LABEL: VFTable indices for 'F' (1 entry).
// CHECK-NEXT: -- accessible via vfptr at offset 4 --
- // CHECK-NEXT: 0 | F::~F() [vector deleting]
+ // CHECK-NEXT: 0 | F::~F() [scalar deleting]
};
void build_vftable(F *obj) { delete obj; }
@@ -79,7 +79,7 @@ struct G : F {
// CHECK-NEXT: 0 | void D::z4()
// CHECK-LABEL: VFTable for 'B' in 'F' in 'G' (1 entry).
- // CHECK-NEXT: 0 | G::~G() [vector deleting]
+ // CHECK-NEXT: 0 | G::~G() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-LABEL: Thunks for 'G::~G()' (1 entry).
@@ -87,7 +87,7 @@ struct G : F {
// CHECK-LABEL: VFTable indices for 'G' (1 entry).
// CHECK-NEXT: -- accessible via vfptr at offset 4 --
- // CHECK-NEXT: 0 | G::~G() [vector deleting]
+ // CHECK-NEXT: 0 | G::~G() [scalar deleting]
virtual ~G();
};
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
index 1a589370d3a74..5030a5dcd2a50 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-return-thunks.cpp
@@ -213,6 +213,6 @@ struct C : virtual B { C *f(); };
C c;
// VFTABLES-LABEL: VFTable indices for 'pr34302::C' (2 entries).
// VFTABLES-NEXT: -- accessible via vbtable index 1, vfptr at offset 0 --
-// VFTABLES-NEXT: 0 | pr34302::C::~C() [vector deleting]
+// VFTABLES-NEXT: 0 | pr34302::C::~C() [scalar deleting]
// VFTABLES-NEXT: 2 | C *pr34302::C::f()
}
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
index c95202e8cc253..b0bf927d38f7c 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-single-inheritance.cpp
@@ -44,10 +44,10 @@ void use(B *obj) { obj->f(); }
struct C {
// CHECK-LABEL: VFTable for 'C' (2 entries)
- // CHECK-NEXT: 0 | C::~C() [vector deleting]
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-NEXT: 1 | void C::f()
// CHECK-LABEL: VFTable indices for 'C' (2 entries).
- // CHECK-NEXT: 0 | C::~C() [vector deleting]
+ // CHECK-NEXT: 0 | C::~C() [scalar deleting]
// CHECK-NEXT: 1 | void C::f()
virtual ~C();
@@ -60,10 +60,10 @@ void use(C *obj) { obj->f(); }
struct D {
// CHECK-LABEL: VFTable for 'D' (2 entries)
// CHECK-NEXT: 0 | void D::f()
- // CHECK-NEXT: 1 | D::~D() [vector deleting]
+ // CHECK-NEXT: 1 | D::~D() [scalar deleting]
// CHECK-LABEL: VFTable indices for 'D' (2 entries)
// CHECK-NEXT: 0 | void D::f()
- // CHECK-NEXT: 1 | D::~D() [vector deleting]
+ // CHECK-NEXT: 1 | D::~D() [scalar deleting]
virtual void f();
virtual ~D();
@@ -77,10 +77,10 @@ struct E : A {
// CHECK-NEXT: 0 | void A::f()
// CHECK-NEXT: 1 | void A::g()
// CHECK-NEXT: 2 | void A::h()
- // CHECK-NEXT: 3 | E::~E() [vector deleting]
+ // CHECK-NEXT: 3 | E::~E() [scalar deleting]
// CHECK-NEXT: 4 | void E::i()
// CHECK-LABEL: VFTable indices for 'E' (2 entries).
- // CHECK-NEXT: 3 | E::~E() [vector deleting]
+ // CHECK-NEXT: 3 | E::~E() [scalar deleting]
// CHECK-NEXT: 4 | void E::i()
// ~E would be the key method, but it isn't used, and MS ABI has no key
@@ -98,10 +98,10 @@ struct F : A {
// CHECK-NEXT: 1 | void A::g()
// CHECK-NEXT: 2 | void A::h()
// CHECK-NEXT: 3 | void F::i()
- // CHECK-NEXT: 4 | F::~F() [vector deleting]
+ // CHECK-NEXT: 4 | F::~F() [scalar deleting]
// CHECK-LABEL: VFTable indices for 'F' (2 entries).
// CHECK-NEXT: 3 | void F::i()
- // CHECK-NEXT: 4 | F::~F() [vector deleting]
+ // CHECK-NEXT: 4 | F::~F() [scalar deleting]
virtual void i();
virtual ~F();
@@ -115,12 +115,12 @@ struct G : E {
// CHECK-NEXT: 0 | void G::f()
// CHECK-NEXT: 1 | void A::g()
// CHECK-NEXT: 2 | void A::h()
- // CHECK-NEXT: 3 | G::~G() [vector deleting]
+ // CHECK-NEXT: 3 | G::~G() [scalar deleting]
// CHECK-NEXT: 4 | void E::i()
// CHECK-NEXT: 5 | void G::j()
// CHECK-LABEL: VFTable indices for 'G' (3 entries).
// CHECK-NEXT: 0 | void G::f()
- // CHECK-NEXT: 3 | G::~G() [vector deleting]
+ // CHECK-NEXT: 3 | G::~G() [scalar deleting]
// CHECK-NEXT: 5 | void G::j()
virtual void f(); // overrides A::f()
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
index be9f281560dcf..c5ce69f5cbcac 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance-vtordisps.cpp
@@ -57,7 +57,7 @@ struct A : virtual V1 {
// CHECK-LABEL: VFTable for 'V1' in 'simple::A' (2 entries).
// CHECK-NEXT: 0 | void simple::A::f()
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
- // CHECK-NEXT: 1 | simple::A::~A() [vector deleting]
+ // CHECK-NEXT: 1 | simple::A::~A() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'simple::A::~A()' (1 entry).
@@ -79,7 +79,7 @@ void use(A *obj) { obj->f(); }
struct B : virtual V3 {
// CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::B' (2 entries).
// CHECK-NEXT: 0 | void Z::g()
- // CHECK-NEXT: 1 | simple::B::~B() [vector deleting]
+ // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).
@@ -88,7 +88,7 @@ struct B : virtual V3 {
// CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' (2 entries).
// CHECK-NEXT: 0 | void simple::B::f()
// CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
- // CHECK-NEXT: 1 | simple::B::~B() [vector deleting]
+ // CHECK-NEXT: 1 | simple::B::~B() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
// CHECK-LABEL: Thunks for 'simple::B::~B()' (1 entry).
@@ -115,7 +115,7 @@ void use(B *obj) { obj->f(); }
struct C : virtual V4 {
// CHECK-LABEL: VFTable for 'Z' in 'V4' in 'simple::C' (2 entries).
// CHECK-NEXT: 0 | void Z::g()
- // CHECK-NEXT: 1 | simple::C::~C() [vector deleting]
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
@@ -124,7 +124,7 @@ struct C : virtual V4 {
// CHECK-LABEL: VFTable for 'V1' in 'V4' in 'simple::C' (2 entries).
// CHECK-NEXT: 0 | void simple::C::f()
// CHECK-NEXT: [this adjustment: vtordisp at -12, 0 non-virtual]
- // CHECK-NEXT: 1 | simple::C::~C() [vector deleting]
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
// CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
@@ -136,7 +136,7 @@ struct C : virtual V4 {
// CHECK-LABEL: VFTable for 'V2' in 'V4' in 'simple::C' (2 entries).
// CHECK-NEXT: 0 | void simple::C::f()
// CHECK-NEXT: [this adjustment: vtordisp at -16, -4 non-virtual]
- // CHECK-NEXT: 1 | simple::C::~C() [vector deleting]
+ // CHECK-NEXT: 1 | simple::C::~C() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -16, -12 non-virtual]
// CHECK-LABEL: Thunks for 'simple::C::~C()' (1 entry).
@@ -162,7 +162,7 @@ class D : B {
// CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::B' in 'simple::D' (2 entries).
// CHECK-NEXT: 0 | void simple::B::f()
// CHECK-NEXT: [this adjustment: vtordisp at -12, -4 non-virtual]
- // CHECK-NEXT: 1 | simple::D::~D() [vector deleting]
+ // CHECK-NEXT: 1 | simple::D::~D() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
D();
int z;
@@ -180,12 +180,12 @@ struct F : virtual E {
// CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' (2 entries).
// CHECK-NEXT: 0 | void simple::F::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
- // CHECK-NEXT: 1 | simple::F::~F() [vector deleting]
+ // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' (2 entries).
// CHECK-NEXT: 0 | void simple::E::f()
- // CHECK-NEXT: 1 | simple::F::~F() [vector deleting]
+ // CHECK-NEXT: 1 | simple::F::~F() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
F();
@@ -202,12 +202,12 @@ struct G : F {
// CHECK-LABEL: VFTable for 'Z' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).
// CHECK-NEXT: 0 | void simple::F::g()
// CHECK-NEXT: [this adjustment: vtordisp at -4, -4 non-virtual]
- // CHECK-NEXT: 1 | simple::G::~G() [vector deleting]
+ // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: VFTable for 'V2' in 'V3' in 'simple::E' in 'simple::F' in 'simple::G' (2 entries).
// CHECK-NEXT: 0 | void simple::E::f()
- // CHECK-NEXT: 1 | simple::G::~G() [vector deleting]
+ // CHECK-NEXT: 1 | simple::G::~G() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -12, -8 non-virtual]
G();
@@ -240,7 +240,7 @@ struct A : virtual simple::A {
// CHECK-NEXT: 0 | void simple::A::f()
// CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
- // CHECK-NEXT: 1 | extended::A::~A() [vector deleting]
+ // CHECK-NEXT: 1 | extended::A::~A() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
@@ -265,7 +265,7 @@ struct B : virtual simple::A {
// CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::B' (2 entries).
// ...
- // CHECK: 1 | extended::B::~B() [vector deleting]
+ // CHECK: 1 | extended::B::~B() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
@@ -353,7 +353,7 @@ struct G : virtual simple::A {
// CHECK-NEXT: 0 | void simple::A::f()
// CHECK-NEXT: [this adjustment: vtordisp at -4, vbptr at 8 to the left,
// CHECK-NEXT: vboffset at 8 in the vbtable, 8 non-virtual]
- // CHECK-NEXT: 1 | extended::G::~G() [vector deleting]
+ // CHECK-NEXT: 1 | extended::G::~G() [scalar deleting]
// CHECK-NEXT: [this adjustment: vtordisp at -4, 0 non-virtual]
// CHECK-LABEL: Thunks for 'void simple::A::f()' (1 entry).
@@ -374,7 +374,7 @@ void use(G *obj) { obj->g(); }
struct H : Z, A {
// CHECK-LABEL: VFTable for 'Z' in 'extended::H' (2 entries).
// CHECK-NEXT: 0 | void Z::g()
- // CHECK-NEXT: 1 | extended::H::~H() [vector deleting]
+ // CHECK-NEXT: 1 | extended::H::~H() [scalar deleting]
// CHECK-LABEL: VFTable for 'V1' in 'simple::A' in 'extended::A' in 'extended::H' (2 entries).
// CHECK-NEXT: 0 | void simple::A::f()
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index e5e6ea5f42c1c..257ba270291c8 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -492,7 +492,7 @@ struct X {
struct Y : virtual X {
// CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::Y' (2 entries).
- // CHECK-NEXT: 0 | vdtors::Y::~Y() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::Y::~Y() [scalar deleting]
// CHECK-NEXT: 1 | void vdtors::X::zzz()
// CHECK-NOT: Thunks for 'vdtors::Y::~Y()'
@@ -515,7 +515,7 @@ struct U : virtual W {
// CHECK-NEXT: 0 | void vdtors::Z::z()
// CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::U' (2 entries).
- // CHECK-NEXT: 0 | vdtors::U::~U() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-NEXT: 1 | void vdtors::X::zzz()
@@ -524,7 +524,7 @@ struct U : virtual W {
// CHECK-LABEL: VFTable indices for 'vdtors::U' (1 entry).
// CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
- // CHECK-NEXT: 0 | vdtors::U::~U() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::U::~U() [scalar deleting]
virtual ~U();
};
@@ -536,7 +536,7 @@ struct V : virtual W {
// CHECK-NEXT: 0 | void vdtors::Z::z()
// CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::W' in 'vdtors::V' (2 entries).
- // CHECK-NEXT: 0 | vdtors::V::~V() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
// CHECK-NEXT: [this adjustment: -4 non-virtual]
// CHECK-NEXT: 1 | void vdtors::X::zzz()
@@ -545,7 +545,7 @@ struct V : virtual W {
// CHECK-LABEL: VFTable indices for 'vdtors::V' (1 entry).
// CHECK-NEXT: -- accessible via vbtable index 1, vfptr at offset 4 --
- // CHECK-NEXT: 0 | vdtors::V::~V() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::V::~V() [scalar deleting]
};
V v;
@@ -557,7 +557,7 @@ struct T : virtual X {
struct P : T, Y {
// CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::T' in 'vdtors::P' (2 entries).
- // CHECK-NEXT: 0 | vdtors::P::~P() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::P::~P() [scalar deleting]
// CHECK-NEXT: 1 | void vdtors::X::zzz()
// CHECK-NOT: Thunks for 'vdtors::P::~P()'
@@ -574,18 +574,18 @@ struct Q {
// PR19172: Yet another diamond we miscompiled.
struct R : virtual Q, X {
// CHECK-LABEL: VFTable for 'vdtors::Q' in 'vdtors::R' (1 entry).
- // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
// CHECK-NEXT: [this adjustment: -8 non-virtual]
// CHECK-LABEL: Thunks for 'vdtors::R::~R()' (1 entry).
// CHECK-NEXT: 0 | [this adjustment: -8 non-virtual]
// CHECK-LABEL: VFTable for 'vdtors::X' in 'vdtors::R' (2 entries).
- // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
// CHECK-NEXT: 1 | void vdtors::X::zzz()
// CHECK-LABEL: VFTable indices for 'vdtors::R' (1 entry).
- // CHECK-NEXT: 0 | vdtors::R::~R() [vector deleting]
+ // CHECK-NEXT: 0 | vdtors::R::~R() [scalar deleting]
virtual ~R();
};
diff --git a/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp b/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp
index c8e374e51a031..069f0226ab948 100644
--- a/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp
+++ b/clang/test/CodeGenCXX/microsoft-no-rtti-data.cpp
@@ -2,7 +2,7 @@
// vftable shouldn't have RTTI data in it.
// CHECK-NOT: @"??_R4S@@6B@"
-// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_ES@@UAEPAXI at Z"] }, comdat
+// CHECK: @"??_7S@@6B@" = linkonce_odr unnamed_addr constant { [1 x ptr] } { [1 x ptr] [ptr @"??_GS@@UAEPAXI at Z"] }, comdat
struct type_info;
namespace std { using ::type_info; }
diff --git a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp b/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp
deleted file mode 100644
index f066902c41002..0000000000000
--- a/clang/test/CodeGenCXX/microsoft-vector-deleting-dtors.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-// RUN: %clang_cc1 -emit-llvm %s -triple=x86_64-pc-windows-msvc -o - | FileCheck %s
-
-struct Bird {
- virtual ~Bird();
-};
-
-struct Parrot : public Bird {
-// CHECK: @[[ParrotVtable:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Parrot@@6B@", ptr @"??_EParrot@@UEAAPEAXI at Z"] }, comdat($"??_7Parrot@@6B@")
-// CHECK: @[[Bird:[0-9]+]] = private unnamed_addr constant { [2 x ptr] } { [2 x ptr] [ptr @"??_R4Bird@@6B@", ptr @"??_EBird@@UEAAPEAXI at Z"] }, comdat($"??_7Bird@@6B@")
- virtual ~Parrot() {}
-};
-
-Bird::~Bird() {}
-
-// For the weird bird we first emit scalar deleting destructor, then find out
-// that we need vector deleting destructor and remove the alias.
-struct JustAWeirdBird {
- virtual ~JustAWeirdBird() {}
-
- bool doSmth(int n) {
- JustAWeirdBird *c = new JustAWeirdBird[n];
-
- delete[] c;
- return true;
- }
-};
-
-// Vector deleting dtor for Bird is an alias because no new Bird[] expressions
-// in the TU.
-// CHECK: @"??_EBird@@UEAAPEAXI at Z" = weak dso_local unnamed_addr alias ptr (ptr, i32), ptr @"??_GBird@@UEAAPEAXI at Z"
-// No scalar destructor for Parrot.
-// CHECK-NOT: @"??_GParrot"
-// No vector destructor definition for Bird.
-// CHECK-NOT: define{{.*}}@"??_EBird"
-// No scalar deleting dtor for JustAWeirdBird.
-// CHECK-NOT: @"??_GJustAWeirdBird"
-
-void dealloc(Bird *p) {
- delete[] p;
-}
-
-Bird* alloc() {
- Parrot* P = new Parrot[38];
- return P;
-}
-
-void bar() {
- dealloc(alloc());
-
- JustAWeirdBird B;
- B.doSmth(38);
-}
-
-// CHECK-LABEL: define dso_local void @{{.*}}dealloc{{.*}}(
-// CHECK-SAME: ptr noundef %[[PTR:.*]])
-// CHECK: entry:
-// CHECK-NEXT: %[[PTRADDR:.*]] = alloca ptr
-// CHECK-NEXT: store ptr %[[PTR]], ptr %[[PTRADDR]]
-// CHECK-NEXT: %[[LPTR:.*]] = load ptr, ptr %[[PTRADDR]]
-// CHECK-NEXT: %[[ISNULL:.*]] = icmp eq ptr %[[LPTR]], null
-// CHECK-NEXT: br i1 %[[ISNULL]], label %delete.end, label %delete.notnull
-// CHECK: delete.notnull:
-// CHECK-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LPTR]], i64 -8
-// CHECK-NEXT: %[[HOWMANY:.*]] = load i64, ptr %[[COOKIEGEP]]
-// CHECK-NEXT: %[[ISNOELEM:.*]] = icmp eq i64 %2, 0
-// CHECK-NEXT: br i1 %[[ISNOELEM]], label %vdtor.nocall, label %vdtor.call
-// CHECK: vdtor.nocall:
-// CHECK-NEXT: %[[HOWMANYBYTES:.*]] = mul i64 8, %[[HOWMANY]]
-// CHECK-NEXT: %[[ADDCOOKIESIZE:.*]] = add i64 %[[HOWMANYBYTES]], 8
-// CHECK-NEXT: call void @"??_V at YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef %[[ADDCOOKIESIZE]])
-// CHECK-NEXT: br label %delete.end
-// CHECK: vdtor.call:
-// CHECK-NEXT: %[[VTABLE:.*]] = load ptr, ptr %[[LPTR]], align 8
-// CHECK-NEXT: %[[FPGEP:.*]] = getelementptr inbounds ptr, ptr %[[VTABLE]], i64 0
-// CHECK-NEXT: %[[FPLOAD:.*]] = load ptr, ptr %[[FPGEP]], align 8
-// CHECK-NEXT: %[[CALL:.*]] = call noundef ptr %[[FPLOAD]](ptr noundef nonnull align 8 dereferenceable(8) %[[LPTR]], i32 noundef 3)
-// CHECK-NEXT: br label %delete.end
-// CHECK: delete.end:
-// CHECK-NEXT: ret void
-
-// Vector dtor definition for Parrot.
-// CHECK-LABEL: define weak dso_local noundef ptr @"??_EParrot@@UEAAPEAXI at Z"(
-// CHECK-SAME: ptr {{.*}} %[[THIS:.*]], i32 {{.*}} %[[IMPLICIT_PARAM:.*]])
-// CHECK: entry:
-// CHECK-NEXT: %[[RET:.*]] = alloca ptr
-// CHECK-NEXT: %[[IPADDR:.*]] = alloca i32
-// CHECK-NEXT: %[[THISADDR:.*]] = alloca ptr
-// CHECK-NEXT: store i32 %[[IMPLICIT_PARAM]], ptr %[[IPADDR]]
-// CHECK-NEXT: store ptr %[[THIS]], ptr %[[THISADDR]]
-// CHECK-NEXT: %[[LTHIS:.*]] = load ptr, ptr %[[THISADDR]]
-// CHECK-NEXT: store ptr %[[LTHIS]], ptr %[[RET]]
-// CHECK-NEXT: %[[LIP:.*]] = load i32, ptr %[[IPADDR]]
-// CHECK-NEXT: %[[SECONDBIT:.*]] = and i32 %[[LIP]], 2
-// CHECK-NEXT: %[[ISSECONDBITZERO:.*]] = icmp eq i32 %[[SECONDBIT]], 0
-// CHECK-NEXT: br i1 %[[ISSECONDBITZERO:.*]], label %dtor.scalar, label %dtor.vector
-// CHECK: dtor.vector:
-// CHECK-NEXT: %[[COOKIEGEP:.*]] = getelementptr inbounds i8, ptr %[[LTHIS]], i64 -8
-// CHECK-NEXT: %[[HOWMANY:.*]] = load i64, ptr %[[COOKIEGEP]]
-// CHECK-NEXT: %[[END:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[LTHIS]], i64 %[[HOWMANY]]
-// CHECK-NEXT: br label %arraydestroy.body
-// CHECK: arraydestroy.body:
-// CHECK-NEXT: %[[PASTELEM:.*]] = phi ptr [ %delete.end, %dtor.vector ], [ %arraydestroy.element, %arraydestroy.body ]
-// CHECK-NEXT: %[[CURELEM:.*]] = getelementptr inbounds %struct.Parrot, ptr %[[PASTELEM]], i64 -1
-// CHECK-NEXT: call void @"??1Parrot@@UEAA at XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[CURELEM]])
-// CHECK-NEXT: %[[DONE:.*]] = icmp eq ptr %[[CURELEM]], %[[LTHIS]]
-// CHECK-NEXT: br i1 %[[DONE]], label %arraydestroy.done3, label %arraydestroy.body
-// CHECK: arraydestroy.done3:
-// CHECK-NEXT: br label %dtor.vector.cont
-// CHECK: dtor.vector.cont:
-// CHECK-NEXT: %[[FIRSTBIT:.*]] = and i32 %[[LIP]], 1
-// CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0
-// CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete_after_array_destroy
-// CHECK: dtor.call_delete_after_array_destroy:
-// CHECK-NEXT: call void @"??3 at YAXPEAX_K@Z"(ptr noundef %[[COOKIEGEP]], i64 noundef 8)
-// CHECK-NEXT: br label %dtor.continue
-// CHECK: dtor.scalar:
-// CHECK-NEXT: call void @"??1Parrot@@UEAA at XZ"(ptr noundef nonnull align 8 dereferenceable(8) %[[LTHIS]])
-// CHECK-NEXT: %[[FIRSTBIT:.*]] = and i32 %[[LIP]], 1
-// CHECK-NEXT: %[[ISFIRSTBITZERO:.*]] = icmp eq i32 %[[FIRSTBIT]], 0
-// CHECK-NEXT: br i1 %[[ISFIRSTBITZERO]], label %dtor.continue, label %dtor.call_delete
-// CHECK: dtor.call_delete:
-// CHECK-NEXT: call void @"??3 at YAXPEAX_K@Z"(ptr noundef %[[LTHIS]], i64 noundef 8)
-// CHECK-NEXT: br label %dtor.continue
-// CHECK: dtor.continue:
-// CHECK-NEXT: %[[LOADRET:.*]] = load ptr, ptr %[[RET]], align 8
-// CHECK-NEXT: ret ptr %[[LOADRET]]
-
-// CHECK: define weak dso_local ptr @"??_EJustAWeirdBird@@UEAAPEAXI at Z"(
-// CHECK-SAME: ptr %this, i32 %should_call_delete)
diff --git a/clang/test/CodeGenCXX/vtable-consteval.cpp b/clang/test/CodeGenCXX/vtable-consteval.cpp
index 220143465c574..1454f6fde357d 100644
--- a/clang/test/CodeGenCXX/vtable-consteval.cpp
+++ b/clang/test/CodeGenCXX/vtable-consteval.cpp
@@ -26,7 +26,7 @@ struct B {
B b;
// ITANIUM-DAG: @_ZTV1C = {{.*}} constant { [4 x ptr] } {{.*}} null, ptr @_ZTI1C, ptr @_ZN1CD1Ev, ptr @_ZN1CD0Ev
-// MSABI-DAG: @[[C_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4C@@6B@", ptr @"??_EC@@UEAAPEAXI at Z"
+// MSABI-DAG: @[[C_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4C@@6B@", ptr @"??_GC@@UEAAPEAXI at Z"
struct C {
virtual ~C() = default;
virtual consteval C &operator=(const C&) = default;
@@ -36,7 +36,7 @@ struct C {
C c;
// ITANIUM-DAG: @_ZTV1D = {{.*}} constant { [4 x ptr] } {{.*}} null, ptr @_ZTI1D, ptr @_ZN1DD1Ev, ptr @_ZN1DD0Ev
-// MSABI-DAG: @[[D_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4D@@6B@", ptr @"??_ED@@UEAAPEAXI at Z"
+// MSABI-DAG: @[[D_VFTABLE:.*]] = {{.*}} constant { [2 x ptr] } {{.*}} @"??_R4D@@6B@", ptr @"??_GD@@UEAAPEAXI at Z"
struct D : C {};
// ITANIUM-DAG: @d = {{.*}}global { ptr } { {{.*}} @_ZTV1D,
// MSABI-DAG: @"?d@@3UD@@A" = {{.*}}global { ptr } { ptr @"??_7D@@6B@" }
diff --git a/clang/test/Modules/vtable-windows.cppm b/clang/test/Modules/vtable-windows.cppm
index e45e32d6b4d60..dbde24c8a9bdd 100644
--- a/clang/test/Modules/vtable-windows.cppm
+++ b/clang/test/Modules/vtable-windows.cppm
@@ -23,4 +23,4 @@ void test() {
// Check that the virtual table is an unnamed_addr constant in comdat that can
// be merged with the virtual table with other TUs.
-// CHECK: unnamed_addr constant {{.*}}[ptr @"??_R4Fruit@@6B@", ptr @"??_EFruit@@UAEPAXI at Z", ptr @"?eval at Fruit@@UAEXXZ"{{.*}}comdat($"??_7Fruit@@6B@")
+// CHECK: unnamed_addr constant {{.*}}[ptr @"??_R4Fruit@@6B@", ptr @"??_GFruit@@UAEPAXI at Z", ptr @"?eval at Fruit@@UAEXXZ"{{.*}}comdat($"??_7Fruit@@6B@")
diff --git a/clang/test/Profile/cxx-abc-deleting-dtor.cpp b/clang/test/Profile/cxx-abc-deleting-dtor.cpp
index 7c2a5bbc93af3..c65a8e8013c35 100644
--- a/clang/test/Profile/cxx-abc-deleting-dtor.cpp
+++ b/clang/test/Profile/cxx-abc-deleting-dtor.cpp
@@ -24,15 +24,16 @@ DerivedABC *useABCVTable() { return new DerivedABC(); }
// MSVC: @"__profn_??1ABC@@{{.*}}" =
// MSVC-NOT: @"__profn_??_G{{.*}}" =
+// MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GDerivedABC@@UEAAPEAXI at Z"(ptr {{[^,]*}} %this, {{.*}})
+// MSVC-NOT: call void @llvm.instrprof.increment({{.*}})
+// MSVC: call void @"??1DerivedABC@@UEAA at XZ"({{.*}})
+// MSVC: ret void
+
// MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GABC@@UEAAPEAXI at Z"(ptr {{[^,]*}} %this, {{.*}})
// MSVC-NOT: call void @llvm.instrprof.increment({{.*}})
// MSVC: call void @llvm.trap()
// MSVC-NEXT: unreachable
-// MSVC-LABEL: define linkonce_odr dso_local noundef ptr @"??_GDerivedABC@@UEAAPEAXI at Z"(ptr {{[^,]*}} %this, {{.*}})
-// MSVC-NOT: call void @llvm.instrprof.increment({{.*}})
-// MSVC: call void @"??1DerivedABC@@UEAA at XZ"({{.*}})
-
// MSVC-LABEL: define linkonce_odr dso_local void @"??1DerivedABC@@UEAA at XZ"({{.*}})
// MSVC: call void @llvm.instrprof.increment({{.*}})
// MSVC: call void @"??1ABC@@UEAA at XZ"({{.*}})
More information about the cfe-commits
mailing list