summaryrefslogtreecommitdiff
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.cpp98
1 files changed, 62 insertions, 36 deletions
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 4ed3775f156c..7dc2eaf1e9f7 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -91,6 +91,8 @@ public:
case Dtor_Comdat:
llvm_unreachable("emitting dtor comdat as function?");
+ case Dtor_Unified:
+ llvm_unreachable("emitting unified dtor as function?");
}
llvm_unreachable("bad dtor kind");
}
@@ -108,6 +110,9 @@ public:
case Ctor_Comdat:
llvm_unreachable("emitting ctor comdat as function?");
+
+ case Ctor_Unified:
+ llvm_unreachable("emitting unified ctor as function?");
}
llvm_unreachable("bad dtor kind");
}
@@ -1397,9 +1402,7 @@ 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>()->getOriginalDecl())
- ->getDefinitionOrSelf();
+ auto *ClassDecl = ElementType->castAsCXXRecordDecl();
llvm::Value *VTable = CGF.GetVTablePtr(Ptr, CGF.UnqualPtrTy, ClassDecl);
// Track back to entry -2 and pull out the offset there.
@@ -1484,21 +1487,18 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
// The address of the destructor. If the exception type has a
// 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->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
- // discriminator based on their type.
- const ASTContext &Ctx = getContext();
- QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy},
- FunctionProtoType::ExtProtoInfo());
-
- CXXDestructorDecl *DtorD = Record->getDestructor();
- Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
- Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
- }
+ if (const auto *Record = ThrowType->getAsCXXRecordDecl();
+ Record && !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
+ // discriminator based on their type.
+ const ASTContext &Ctx = getContext();
+ QualType DtorTy = Ctx.getFunctionType(Ctx.VoidTy, {Ctx.VoidPtrTy},
+ FunctionProtoType::ExtProtoInfo());
+
+ CXXDestructorDecl *DtorD = Record->getDestructor();
+ Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
+ Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
}
if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
@@ -1612,9 +1612,7 @@ llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
QualType SrcRecordTy,
Address ThisPtr,
llvm::Type *StdTypeInfoPtrTy) {
- auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
- ->getDefinitionOrSelf();
+ auto *ClassDecl = SrcRecordTy->castAsCXXRecordDecl();
llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
ClassDecl);
@@ -1748,7 +1746,14 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
llvm::BasicBlock *CastFail) {
const CXXRecordDecl *SrcDecl = SrcRecordTy->getAsCXXRecordDecl();
const CXXRecordDecl *DestDecl = DestRecordTy->getAsCXXRecordDecl();
+ auto AuthenticateVTable = [&](Address ThisAddr, const CXXRecordDecl *Decl) {
+ if (!CGF.getLangOpts().PointerAuthCalls)
+ return;
+ (void)CGF.GetVTablePtr(ThisAddr, CGF.UnqualPtrTy, Decl,
+ CodeGenFunction::VTableAuthMode::MustTrap);
+ };
+ bool PerformPostCastAuthentication = false;
llvm::Value *VTable = nullptr;
if (ExactCastInfo.RequiresCastToPrimaryBase) {
// Base appears in at least two different places. Find the most-derived
@@ -1759,8 +1764,16 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
emitDynamicCastToVoid(CGF, ThisAddr, SrcRecordTy);
ThisAddr = Address(PrimaryBase, CGF.VoidPtrTy, ThisAddr.getAlignment());
SrcDecl = DestDecl;
+ // This unauthenticated load is unavoidable, so we're relying on the
+ // authenticated load in the dynamic cast to void, and we'll manually
+ // authenticate the resulting v-table at the end of the cast check.
+ PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;
+ CGPointerAuthInfo StrippingAuthInfo(0, PointerAuthenticationMode::Strip,
+ false, false, nullptr);
Address VTablePtrPtr = ThisAddr.withElementType(CGF.VoidPtrPtrTy);
VTable = CGF.Builder.CreateLoad(VTablePtrPtr, "vtable");
+ if (PerformPostCastAuthentication)
+ VTable = CGF.EmitPointerAuthAuth(StrippingAuthInfo, VTable);
} else
VTable = CGF.GetVTablePtr(ThisAddr, CGF.UnqualPtrTy, SrcDecl);
@@ -1777,8 +1790,32 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
llvm::ConstantInt::get(CGF.PtrDiffTy, -Offset);
AdjustedThisPtr = CGF.Builder.CreateInBoundsGEP(CGF.CharTy, AdjustedThisPtr,
OffsetConstant);
+ PerformPostCastAuthentication = CGF.getLangOpts().PointerAuthCalls;
}
+ if (PerformPostCastAuthentication) {
+ // If we've changed the object pointer we authenticate the vtable pointer
+ // of the resulting object.
+ llvm::BasicBlock *NonNullBlock = CGF.Builder.GetInsertBlock();
+ llvm::BasicBlock *PostCastAuthSuccess =
+ CGF.createBasicBlock("dynamic_cast.postauth.success");
+ llvm::BasicBlock *PostCastAuthComplete =
+ CGF.createBasicBlock("dynamic_cast.postauth.complete");
+ CGF.Builder.CreateCondBr(Success, PostCastAuthSuccess,
+ PostCastAuthComplete);
+ CGF.EmitBlock(PostCastAuthSuccess);
+ Address AdjustedThisAddr =
+ Address(AdjustedThisPtr, CGF.IntPtrTy, CGF.getPointerAlign());
+ AuthenticateVTable(AdjustedThisAddr, DestDecl);
+ CGF.EmitBranch(PostCastAuthComplete);
+ CGF.EmitBlock(PostCastAuthComplete);
+ llvm::PHINode *PHI = CGF.Builder.CreatePHI(AdjustedThisPtr->getType(), 2);
+ PHI->addIncoming(AdjustedThisPtr, PostCastAuthSuccess);
+ llvm::Value *NullValue =
+ llvm::Constant::getNullValue(AdjustedThisPtr->getType());
+ PHI->addIncoming(NullValue, NonNullBlock);
+ AdjustedThisPtr = PHI;
+ }
CGF.Builder.CreateCondBr(Success, CastSuccess, CastFail);
return AdjustedThisPtr;
}
@@ -1786,9 +1823,7 @@ llvm::Value *ItaniumCXXABI::emitExactDynamicCast(
llvm::Value *ItaniumCXXABI::emitDynamicCastToVoid(CodeGenFunction &CGF,
Address ThisAddr,
QualType SrcRecordTy) {
- auto *ClassDecl =
- cast<CXXRecordDecl>(SrcRecordTy->castAs<RecordType>()->getOriginalDecl())
- ->getDefinitionOrSelf();
+ auto *ClassDecl = SrcRecordTy->castAsCXXRecordDecl();
llvm::Value *OffsetToTop;
if (CGM.getItaniumVTableContext().isRelativeLayout()) {
// Get the vtable pointer.
@@ -3872,9 +3907,7 @@ 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>()->getOriginalDecl())
- ->getDefinitionOrSelf();
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
if (!BaseDecl->isEmpty() &&
BaseDecl->isDynamicClass() != RD->isDynamicClass())
return false;
@@ -4394,10 +4427,7 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXBaseSpecifier *Base,
unsigned Flags = 0;
- auto *BaseDecl = cast<CXXRecordDecl>(
- Base->getType()->castAs<RecordType>()->getOriginalDecl())
- ->getDefinitionOrSelf();
-
+ auto *BaseDecl = Base->getType()->castAsCXXRecordDecl();
if (Base->isVirtual()) {
// Mark the virtual base as seen.
if (!Bases.VirtualBases.insert(BaseDecl).second) {
@@ -4495,11 +4525,7 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
// The __base_type member points to the RTTI for the base type.
Fields.push_back(ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(Base.getType()));
- auto *BaseDecl =
- cast<CXXRecordDecl>(
- Base.getType()->castAs<RecordType>()->getOriginalDecl())
- ->getDefinitionOrSelf();
-
+ auto *BaseDecl = Base.getType()->castAsCXXRecordDecl();
int64_t OffsetFlags = 0;
// All but the lower 8 bits of __offset_flags are a signed offset.