================ @@ -1052,11 +1053,143 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type, return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned)); } +namespace { + +/// SubobjectFinder - A simple visitor to find the "sub-object" pointed to by a +/// __builtin_dynamic_object_size call. Information gathered from the +/// sub-object is used by the back-end to determine the correct size when the +/// 'TYPE' of the __bdos call has the least significant bit set (i.e. asking +/// for the sub-object size). +/// +/// The expectation is that we'll eventually hit one of three expression types: +/// +/// 1. DeclRefExpr - This is the expression for the base of the structure. +/// 2. MemberExpr - This is the field in the structure. +/// 3. CompoundLiteralExpr - This is for people who create something +/// heretical like (struct foo has a flexible array member): +/// +/// (struct foo){ 1, 2 }.blah[idx]; +/// +/// All other expressions can be correctly handled with the current code. +struct SubobjectFinder + : public ConstStmtVisitor<SubobjectFinder, const Expr *> { + SubobjectFinder() = default; + + //===--------------------------------------------------------------------===// + // Visitor Methods + //===--------------------------------------------------------------------===// + + const Expr *VisitStmt(const Stmt *S) { return nullptr; } + + const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; } + const Expr *VisitMemberExpr(const MemberExpr *E) { return E; } + const Expr *VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) { + return E; + } + + const Expr *VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { + return Visit(E->getBase()); + } + const Expr *VisitCastExpr(const CastExpr *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitParenExpr(const ParenExpr *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryAddrOf(const clang::UnaryOperator *E) { + return Visit(E->getSubExpr()); + } + const Expr *VisitUnaryDeref(const clang::UnaryOperator *E) { + return Visit(E->getSubExpr()); + } +}; + +} // end anonymous namespace + +/// getFieldInfo - Gather the size and offset of the field \p VD in \p RD. +static std::pair<uint64_t, uint64_t> getFieldInfo(CodeGenFunction &CGF, + const RecordDecl *RD, + const ValueDecl *VD, + uint64_t Offset = 0) { + if (!RD) + return std::make_pair(0, 0); + + ASTContext &Ctx = CGF.getContext(); + const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD); + unsigned FieldNo = 0; + + for (const Decl *D : RD->decls()) { + if (const auto *Record = dyn_cast<RecordDecl>(D)) { + std::pair<uint64_t, uint64_t> Res = + getFieldInfo(CGF, Record->getDefinition(), VD, + Offset + Layout.getFieldOffset(FieldNo)); + if (Res.first != 0) + return Res; + continue; + } + + if (const auto *FD = dyn_cast<FieldDecl>(D); FD == VD) { + Offset += Layout.getFieldOffset(FieldNo); + return std::make_pair(Ctx.getTypeSizeInChars(FD->getType()).getQuantity(), + Ctx.toCharUnitsFromBits(Offset).getQuantity()); + } + + if (isa<FieldDecl>(D)) + ++FieldNo; + } ---------------- zygoloid wrote:
This work recursively looping through fields is not necessary: this function only succeeds when `VD` is a `FieldDecl`, so you can `dyn_cast` it to that type, then get the enclosing `DeclContext` to find the record, and use `FieldDecl::getFieldIndex` to find the field number. https://github.com/llvm/llvm-project/pull/83204 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits