[clang] [Clang] Convert __builtin_dynamic_object_size into a calculation (PR #80256)

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 1 14:41:25 PST 2024


================
@@ -1051,6 +1052,145 @@ CodeGenFunction::emitFlexibleArrayMemberSize(const Expr *E, unsigned Type,
   return Builder.CreateSelect(Cmp, Res, ConstantInt::get(ResType, 0, IsSigned));
 }
 
+namespace {
+
+/// \p StructBaseExpr returns the base \p Expr with a structure or union type.
+struct StructBaseExpr : public ConstStmtVisitor<StructBaseExpr, const Expr *> {
+  StructBaseExpr() = default;
+
+  //===--------------------------------------------------------------------===//
+  //                            Visitor Methods
+  //===--------------------------------------------------------------------===//
+
+  const Expr *VisitStmt(const Stmt *S) { return nullptr; }
+
+  const Expr *Visit(const Expr *E) {
+    QualType Ty = E->getType();
+    if (Ty->isStructureType() || Ty->isUnionType())
+      return E;
+
+    return ConstStmtVisitor<StructBaseExpr, const Expr *>::Visit(E);
+  }
+
+  const Expr *VisitDeclRefExpr(const DeclRefExpr *E) { return E; }
+
+  const Expr *VisitMemberExpr(const MemberExpr *E) {
+    return Visit(E->getBase());
+  }
+  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());
+  }
----------------
zygoloid wrote:

Looking through both casts and dereferences seems like it won't be correct:

```
struct A { int ***p; } a;
int n = __builtin_dynamic_object_size(***a.p, 0);
```
... looks like it'll base the result on the size of `A`, which is unrelated.

I think you should be more conservative about the kinds of casts you'll walk through here: bitcasts and pointer casts seem potentially OK to step through, but things like lvalue-to-rvalue conversions will be problematic.

But looking at what you're doing with this below, I think it might be possible to avoid doing this walk entirely.

https://github.com/llvm/llvm-project/pull/80256


More information about the cfe-commits mailing list