aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/ItaniumCXXABI.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/ItaniumCXXABI.cpp')
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp157
1 files changed, 95 insertions, 62 deletions
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index f4a9946..4ed3775 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -226,6 +226,10 @@ public:
return hasUniqueVTablePointer(DestRecordTy);
}
+ std::optional<ExactDynamicCastInfo>
+ getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
+ QualType DestRecordTy) override;
+
llvm::Value *emitDynamicCastCall(CodeGenFunction &CGF, Address Value,
QualType SrcRecordTy, QualType DestTy,
QualType DestRecordTy,
@@ -234,6 +238,7 @@ public:
llvm::Value *emitExactDynamicCast(CodeGenFunction &CGF, Address ThisAddr,
QualType SrcRecordTy, QualType DestTy,
QualType DestRecordTy,
+ const ExactDynamicCastInfo &CastInfo,
llvm::BasicBlock *CastSuccess,
llvm::BasicBlock *CastFail) override;
@@ -826,7 +831,7 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
for (const CXXRecordDecl *Base : CGM.getMostBaseClasses(RD)) {
llvm::Metadata *MD = CGM.CreateMetadataIdentifierForType(
getContext().getMemberPointerType(MPT->getPointeeType(),
- /*Qualifier=*/nullptr,
+ /*Qualifier=*/std::nullopt,
Base->getCanonicalDecl()));
llvm::Value *TypeId =
llvm::MetadataAsValue::get(CGF.getLLVMContext(), MD);
@@ -1236,7 +1241,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MPD)) {
llvm::Constant *Src = BuildMemberPointer(MD, ThisAdjustment);
QualType SrcType = getContext().getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+ MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent());
return pointerAuthResignMemberFunctionPointer(Src, MPType, SrcType, CGM);
}
@@ -1392,8 +1397,9 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
// to pass to the deallocation function.
// Grab the vtable pointer as an intptr_t*.
- auto *ClassDecl =
- cast<CXXRecordDecl>(ElementType->castAs<RecordType>()->getDecl());
+ auto *ClassDecl = cast<CXXRecordDecl>(
+ ElementType->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.UnqualPtrTy, ClassDecl);
// Track back to entry -2 and pull out the offset there.
@@ -1479,7 +1485,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
// trivial destructor (or isn't a record), we just pass null.
llvm::Constant *Dtor = nullptr;
if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) {
- CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl());
+ CXXRecordDecl *Record =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf();
if (!Record->hasTrivialDestructor()) {
// __cxa_throw is declared to take its destructor as void (*)(void *). We
// must match that if function pointers can be authenticated with a
@@ -1606,7 +1613,8 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
ClassDecl);
@@ -1681,10 +1689,11 @@ llvm::Value *ItaniumCXXABI::emitDynamicCastCall(
return Value;
}
-llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
- CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
- QualType DestTy, QualType DestRecordTy, llvm::BasicBlock *CastSuccess,
- llvm::BasicBlock *CastFail) {
+std::optional<CGCXXABI::ExactDynamicCastInfo>
+ItaniumCXXABI::getExactDynamicCastInfo(QualType SrcRecordTy, QualType DestTy,
+ QualType DestRecordTy) {
+ assert(shouldEmitExactDynamicCast(DestRecordTy));
+
ASTContext &Context = getContext();
// Find all the inheritance paths.
@@ -1722,48 +1731,64 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
if (!Offset)
Offset = PathOffset;
else if (Offset != PathOffset) {
- // Base appears in at least two different places. Find the most-derived
- // object and see if it's a DestDecl. Note that the most-derived object
- // must be at least as aligned as this base class subobject, and must
- // have a vptr at offset 0.
- ThisAddr = Address(emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy),
- CGF.VoidPtrTy, ThisAddr.getAlignment());
- SrcDecl = DestDecl;
- Offset = CharUnits::Zero();
- break;
+ // Base appears in at least two different places.
+ return ExactDynamicCastInfo{/*RequiresCastToPrimaryBase=*/true,
+ CharUnits::Zero()};
}
}
+ if (!Offset)
+ return std::nullopt;
+ return ExactDynamicCastInfo{/*RequiresCastToPrimaryBase=*/false, *Offset};
+}
- if (!Offset) {
- // If there are no public inheritance paths, the cast always fails.
- CGF.EmitBranch(CastFail);
- return llvm::PoisonValue::get(CGF.VoidPtrTy);
- }
+llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
+ CodeGenFunction &CGF, Address ThisAddr, QualType SrcRecordTy,
+ QualType DestTy, QualType DestRecordTy,
+ const ExactDynamicCastInfo &ExactCastInfo, llvm::BasicBlock *CastSuccess,
+ llvm::BasicBlock *CastFail) {
+ const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
+ const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
+
+ llvm::Value *VTable = nullptr;
+ if (ExactCastInfo.RequiresCastToPrimaryBase) {
+ // Base appears in at least two different places. Find the most-derived
+ // object and see if it's a DestDecl. Note that the most-derived object
+ // must be at least as aligned as this base class subobject, and must
+ // have a vptr at offset 0.
+ llvm::Value *PrimaryBase =
+ emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy);
+ ThisAddr = Address(PrimaryBase, CGF.VoidPtrTy, ThisAddr.getAlignment());
+ SrcDecl = DestDecl;
+ Address VTablePtrPtr = ThisAddr.withElementType(CGF.VoidPtrPtrTy);
+ VTable = CGF.Builder.CreateLoad(VTablePtrPtr, "vtable");
+ } else
+ VTable = CGF.GetVTablePtr(ThisAddr, CGF.UnqualPtrTy, SrcDecl);
// Compare the vptr against the expected vptr for the destination type at
- // this offset. Note that we do not know what type ThisAddr points to in
- // the case where the derived class multiply inherits from the base class
- // so we can't use GetVTablePtr, so we load the vptr directly instead.
- llvm::Instruction *VPtr = CGF.Builder.CreateLoad(
- ThisAddr.withElementType(CGF.VoidPtrPtrTy), "vtable");
- CGM.DecorateInstructionWithTBAA(
- VPtr, CGM.getTBAAVTablePtrAccessInfo(CGF.VoidPtrPtrTy));
- llvm::Value *Success = CGF.Builder.CreateICmpEQ(
- VPtr, getVTableAddressPoint(BaseSubobject(SrcDecl, *Offset), DestDecl));
- llvm::Value *Result = ThisAddr.emitRawPointer(CGF);
- if (!Offset->isZero())
- Result = CGF.Builder.CreateInBoundsGEP(
- CGF.CharTy, Result,
- {llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset->getQuantity())});
+ // this offset.
+ llvm::Constant *ExpectedVTable = getVTableAddressPoint(
+ BaseSubobject(SrcDecl, ExactCastInfo.Offset), DestDecl);
+ llvm::Value *Success = CGF.Builder.CreateICmpEQ(VTable, ExpectedVTable);
+ llvm::Value *AdjustedThisPtr = ThisAddr.emitRawPointer(CGF);
+
+ if (!ExactCastInfo.Offset.isZero()) {
+ CharUnits::QuantityType Offset = ExactCastInfo.Offset.getQuantity();
+ llvm::Constant *OffsetConstant =
+ llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset);
+ AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(CGF.CharTy, AdjustedThisPtr,
+ OffsetConstant);
+ }
+
CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);
- return Result;
+ return AdjustedThisPtr;
}
llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
Address ThisAddr,
QualType SrcRecordTy) {
auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
llvm::Value *OffsetToTop;
if (CGM.getItaniumVTableContext().isRelativeLayout()) {
// Get the vtable pointer.
@@ -2016,7 +2041,7 @@ void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
const VTableLayout &VTLayout = VTContext.getVTableLayout(RD);
llvm::GlobalVariable::LinkageTypes Linkage = CGM.getVTableLinkage(RD);
llvm::Constant *RTTI =
- CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getTagDeclType(RD));
+ CGM.GetAddrOfRTTIDescriptor(CGM.getContext().getCanonicalTagType(RD));
// Create and set the initializer.
ConstantInitBuilder builder(CGM);
@@ -2262,7 +2287,7 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
auto *CE = dyn_cast<const CXXMemberCallExpr *>(E);
auto *D = dyn_cast<const CXXDeleteExpr *>(E);
assert((CE != nullptr) ^ (D != nullptr));
- assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
+ assert(CE == nullptr || CE->arguments().empty());
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
GlobalDecl GD(Dtor, DtorType);
@@ -3755,7 +3780,8 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
if (!Context.getLangOpts().RTTI) return false;
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(RecordTy->getOriginalDecl())->getDefinitionOrSelf();
if (!RD->hasDefinition())
return false;
@@ -3789,7 +3815,9 @@ static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
/// IsIncompleteClassType - Returns whether the given record type is incomplete.
static bool IsIncompleteClassType(const RecordType *RecordTy) {
- return !RecordTy->getDecl()->isCompleteDefinition();
+ return !RecordTy->getOriginalDecl()
+ ->getDefinitionOrSelf()
+ ->isCompleteDefinition();
}
/// ContainsIncompleteClassType - Returns whether the given type contains an
@@ -3815,9 +3843,7 @@ static bool ContainsIncompleteClassType(QualType Ty) {
if (const MemberPointerType *MemberPointerTy =
dyn_cast<MemberPointerType>(Ty)) {
// Check if the class type is incomplete.
- const auto *ClassType = cast<RecordType>(
- MemberPointerTy->getMostRecentCXXRecordDecl()->getTypeForDecl());
- if (IsIncompleteClassType(ClassType))
+ if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
return true;
return ContainsIncompleteClassType(MemberPointerTy->getPointeeType());
@@ -3846,8 +3872,9 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
return false;
// Check that the class is dynamic iff the base is.
- auto *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ auto *BaseDecl = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!BaseDecl->isEmpty() &&
BaseDecl->isDynamicClass() != RD->isDynamicClass())
return false;
@@ -3926,7 +3953,8 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
case Type::Record: {
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!RD->hasDefinition() || !RD->getNumBases()) {
VTableName = ClassTypeInfo;
@@ -4048,7 +4076,8 @@ static llvm::GlobalVariable::LinkageTypes getTypeInfoLinkage(CodeGenModule &CGM,
return llvm::GlobalValue::LinkOnceODRLinkage;
if (const RecordType *Record = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(Record->getDecl());
+ const CXXRecordDecl *RD =
+ cast<CXXRecordDecl>(Record->getOriginalDecl())->getDefinitionOrSelf();
if (RD->hasAttr<WeakAttr>())
return llvm::GlobalValue::WeakODRLinkage;
if (CGM.getTriple().isWindowsItaniumEnvironment())
@@ -4212,7 +4241,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
case Type::Record: {
const CXXRecordDecl *RD =
- cast<CXXRecordDecl>(cast<RecordType>(Ty)->getDecl());
+ cast<CXXRecordDecl>(cast<RecordType>(Ty)->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (!RD->hasDefinition() || !RD->getNumBases()) {
// We don't need to emit any fields.
break;
@@ -4259,7 +4289,8 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
if (CGM.getTarget().hasPS4DLLImportExport() &&
GVDLLStorageClass != llvm::GlobalVariable::DLLExportStorageClass) {
if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
- const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getDecl());
+ const CXXRecordDecl *RD = cast<CXXRecordDecl>(RecordTy->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (RD->hasAttr<DLLExportAttr>() ||
CXXRecordNonInlineHasAttr<DLLExportAttr>(RD))
GVDLLStorageClass = llvm::GlobalVariable::DLLExportStorageClass;
@@ -4363,8 +4394,9 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
unsigned Flags = 0;
- auto *BaseDecl =
- cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
+ auto *BaseDecl = cast<CXXRecordDecl>(
+ Base->getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
if (Base->isVirtual()) {
// Mark the virtual base as seen.
@@ -4464,7 +4496,9 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
auto *BaseDecl =
- cast<CXXRecordDecl>(Base.getType()->castAs<RecordType>()->getDecl());
+ cast<CXXRecordDecl>(
+ Base.getType()->castAs<RecordType>()->getOriginalDecl())
+ ->getDefinitionOrSelf();
int64_t OffsetFlags = 0;
@@ -4554,9 +4588,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// attributes of the type pointed to.
unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
- const auto *ClassType =
- cast<RecordType>(Ty->getMostRecentCXXRecordDecl()->getTypeForDecl());
- if (IsIncompleteClassType(ClassType))
+ const auto *RD = Ty->getMostRecentCXXRecordDecl();
+ if (!RD->hasDefinition())
Flags |= PTI_ContainingClassIncomplete;
llvm::Type *UnsignedIntLTy =
@@ -4574,8 +4607,8 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
// __context is a pointer to an abi::__class_type_info corresponding to the
// class type containing the member pointed to
// (e.g., the "A" in "int A::*").
- Fields.push_back(
- ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(QualType(ClassType, 0)));
+ CanQualType T = CGM.getContext().getCanonicalTagType(RD);
+ Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(T));
}
llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
@@ -5155,7 +5188,7 @@ ItaniumCXXABI::getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD) {
.getDecl());
llvm::Constant *thunk = getOrCreateVirtualFunctionPointerThunk(origMD);
QualType funcType = CGM.getContext().getMemberPointerType(
- MD->getType(), /*Qualifier=*/nullptr, MD->getParent());
+ MD->getType(), /*Qualifier=*/std::nullopt, MD->getParent());
return CGM.getMemberFunctionPointer(thunk, funcType);
}