================ @@ -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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits