[clang] [clang][PAC] Support trivially_relocating polymorphic objects (PR #144420)
Oliver Hunt via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 16 12:48:22 PDT 2025
================
@@ -420,6 +420,222 @@ void CodeGenFunction::EmitPointerAuthCopy(PointerAuthQualifier Qual, QualType T,
Builder.CreateStore(Value, DestAddress);
}
+static const ConstantArrayType *tryGetTypeAsConstantArrayType(QualType T) {
+ if (!T->isConstantArrayType())
+ return nullptr;
+ return cast<ConstantArrayType>(T->castAsArrayTypeUnsafe());
+}
+
+using FixupErrorTy = std::pair<const CXXRecordDecl *, CXXBaseSpecifier>;
+class CodeGenFunction::FixupFinder {
+public:
+ using FixupVectorTy = CodeGenFunction::FixupVectorTy;
+ static FixupVectorTy findFixups(CodeGenFunction &CGF, QualType T) {
+ FixupFinder Finder(CGF);
+ FixupVectorTy Result;
+ Finder.findFixups(Result, T, CharUnits::Zero());
+ std::sort(Result.begin(), Result.end(),
+ [](const auto &L, const auto &R) { return L.Offset < R.Offset; });
+ return Result;
+ }
+
+private:
+ explicit FixupFinder(CodeGenFunction &CGF)
+ : CGF(CGF), Context(CGF.getContext()) {}
+
+ void findVTablePointerFixups(FixupVectorTy &Output, CXXRecordDecl *RD,
+ CharUnits Offset) {
+ CodeGenFunction::VPtrsVector VPtrs = CGF.getVTablePointers(RD);
+ for (auto VPtr : VPtrs) {
+ std::optional<PointerAuthQualifier> PointerAuth =
+ CGF.CGM.getVTablePointerAuthentication(VPtr.Base.getBase());
+ if (PointerAuth && PointerAuth->isAddressDiscriminated())
+ Output.push_back(
+ {Offset + VPtr.Base.getBaseOffset(), KnownNonNull, *PointerAuth});
+ }
+ }
+ void findObjectFixups(FixupVectorTy &Output, CXXRecordDecl *RD,
+ CharUnits Offset) {
+ if (RD->isPolymorphic())
+ findVTablePointerFixups(Output, RD, Offset);
+ findFixups(Output, RD, Offset, /*SubobjectIsBase=*/true);
+ }
+
+ void findFixups(FixupVectorTy &Output, CXXRecordDecl *RD,
+ CharUnits SubobjectOffset, bool SubobjectIsBase) {
+ // If we've found a union it by definition cannot contain
+ // address discriminated fields.
+ if (RD->isUnion())
+ return;
+ const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
+ if (Layout.hasOwnVFPtr() && RD == Layout.getPrimaryBase())
+ findVTablePointerFixups(Output, RD, SubobjectOffset);
+
+ for (auto Base : RD->bases()) {
+ CXXRecordDecl *BaseDecl =
+ Base.getType()->getAsCXXRecordDecl()->getDefinition();
+ assert(!Base.isVirtual());
+ CharUnits BaseOffset = Layout.getBaseClassOffset(BaseDecl);
+ findFixups(Output, BaseDecl, SubobjectOffset + BaseOffset,
+ /*SubobjectIsBase=*/true);
+ }
+
+ for (const FieldDecl *Field : RD->fields()) {
+ if (Field->isBitField())
+ continue;
+ unsigned FieldBitOffset = Layout.getFieldOffset(Field->getFieldIndex());
+ CharUnits FieldOffset = Context.toCharUnitsFromBits(FieldBitOffset);
+ findFixups(Output, Field->getType(), SubobjectOffset + FieldOffset);
+ }
+ }
+ void findFixups(FixupVectorTy &Output, QualType T, CharUnits Offset) {
+ T = T.getCanonicalType();
+ if (!Context.containsAddressDiscriminatedPointerAuth(T))
+ return;
+
+ if (const ConstantArrayType *CAT = tryGetTypeAsConstantArrayType(T)) {
+ if (CAT->getSize() == 0)
+ return;
+ Output.push_back({Offset, CAT});
+ return;
+ }
+
+ if (PointerAuthQualifier Q = T.getPointerAuth();
+ Q && Q.isAddressDiscriminated()) {
+ // FIXME: Would it be reasonable to consider nullability?
+ Output.push_back({Offset, NotKnownNonNull, Q});
----------------
ojhunt wrote:
I think this is a reasonable question, but it would also turn an incorrectly null value become a runtime error?
https://github.com/llvm/llvm-project/pull/144420
More information about the cfe-commits
mailing list