@@ -15181,3 +15181,97 @@ bool ASTContext::useAbbreviatedThunkName(GlobalDecl VirtualMethodDecl,
1518115181 ThunksToBeAbbreviated[VirtualMethodDecl] = std::move(SimplifiedThunkNames);
1518215182 return Result;
1518315183}
15184+
15185+ bool ASTContext::arePFPFieldsTriviallyRelocatable(const RecordDecl *RD) const {
15186+ if (getLangOpts().getPointerFieldProtection() ==
15187+ LangOptions::PointerFieldProtectionKind::Tagged)
15188+ return !isa<CXXRecordDecl>(RD) ||
15189+ cast<CXXRecordDecl>(RD)->hasTrivialDestructor();
15190+ return true;
15191+ }
15192+
15193+ bool ASTContext::isPFPStruct(const RecordDecl *rec) const {
15194+ if (getLangOpts().getPointerFieldProtection() !=
15195+ LangOptions::PointerFieldProtectionKind::None)
15196+ if (auto *cxxRec = dyn_cast<CXXRecordDecl>(rec))
15197+ return !cxxRec->isStandardLayout();
15198+ return false;
15199+ }
15200+
15201+ void ASTContext::findPFPFields(QualType Ty, CharUnits Offset,
15202+ std::vector<PFPField> &Fields,
15203+ bool IncludeVBases) const {
15204+ if (auto *AT = getAsConstantArrayType(Ty)) {
15205+ if (auto *ElemDecl = AT->getElementType()->getAsCXXRecordDecl()) {
15206+ const ASTRecordLayout &ElemRL = getASTRecordLayout(ElemDecl);
15207+ for (unsigned i = 0; i != AT->getSize(); ++i) {
15208+ findPFPFields(AT->getElementType(), Offset + i * ElemRL.getSize(),
15209+ Fields, true);
15210+ }
15211+ }
15212+ }
15213+ auto *Decl = Ty->getAsCXXRecordDecl();
15214+ if (!Decl)
15215+ return;
15216+ const ASTRecordLayout &RL = getASTRecordLayout(Decl);
15217+ for (FieldDecl *field : Decl->fields()) {
15218+ CharUnits fieldOffset =
15219+ Offset + toCharUnitsFromBits(RL.getFieldOffset(field->getFieldIndex()));
15220+ if (isPFPField(field))
15221+ Fields.push_back({fieldOffset, field});
15222+ findPFPFields(field->getType(), fieldOffset, Fields, true);
15223+ }
15224+ for (auto &Base : Decl->bases()) {
15225+ if (Base.isVirtual())
15226+ continue;
15227+ CharUnits BaseOffset =
15228+ Offset + RL.getBaseClassOffset(Base.getType()->getAsCXXRecordDecl());
15229+ findPFPFields(Base.getType(), BaseOffset, Fields, false);
15230+ }
15231+ if (IncludeVBases) {
15232+ for (auto &Base : Decl->vbases()) {
15233+ CharUnits BaseOffset =
15234+ Offset + RL.getVBaseClassOffset(Base.getType()->getAsCXXRecordDecl());
15235+ findPFPFields(Base.getType(), BaseOffset, Fields, false);
15236+ }
15237+ }
15238+ }
15239+
15240+ bool ASTContext::hasPFPFields(QualType ty) const {
15241+ std::vector<PFPField> pfpFields;
15242+ findPFPFields(ty, CharUnits::Zero(), pfpFields, true);
15243+ return !pfpFields.empty();
15244+ }
15245+
15246+ bool ASTContext::isPFPField(const FieldDecl *field) const {
15247+ if (!isPFPStruct(field->getParent()))
15248+ return false;
15249+ return field->getType()->isPointerType() &&
15250+ !field->hasAttr<NoPointerFieldProtectionAttr>();
15251+ }
15252+
15253+ void ASTContext::recordMemberDataPointerEvaluation(const ValueDecl *VD) {
15254+ if (getLangOpts().getPointerFieldProtection() ==
15255+ LangOptions::PointerFieldProtectionKind::None)
15256+ return;
15257+ auto *FD = dyn_cast<FieldDecl>(VD);
15258+ if (!FD)
15259+ FD = cast<FieldDecl>(cast<IndirectFieldDecl>(VD)->chain().back());
15260+ if (!isPFPField(FD))
15261+ return;
15262+ PFPFieldsWithEvaluatedOffset.insert(FD);
15263+ }
15264+
15265+ void ASTContext::recordOffsetOfEvaluation(const OffsetOfExpr *E) {
15266+ if (getLangOpts().getPointerFieldProtection() ==
15267+ LangOptions::PointerFieldProtectionKind::None ||
15268+ E->getNumComponents() == 0)
15269+ return;
15270+ OffsetOfNode Comp = E->getComponent(E->getNumComponents() - 1);
15271+ if (Comp.getKind() != OffsetOfNode::Field)
15272+ return;
15273+ FieldDecl *FD = Comp.getField();
15274+ if (!isPFPField(FD))
15275+ return;
15276+ PFPFieldsWithEvaluatedOffset.insert(FD);
15277+ }
0 commit comments