[PATCH] D12821: Allow for C's "writing off the end" idiom in __builtin_object_size

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 11 16:46:32 PDT 2015


rsmith added inline comments.

================
Comment at: lib/AST/ExprConstant.cpp:165
@@ -159,1 +164,3 @@
 
+    /// Indicator of whether the most-derived object is an array.
+    bool MostDerivedIsArrayElement : 1;
----------------
array -> array element.

================
Comment at: lib/AST/ExprConstant.cpp:4457-4460
@@ -4434,1 +4456,6 @@
 
+    // Because we set the Base to be the MemberExpr instead of E->getBase(), the
+    // Offset should be from the MemberExpr instead of the MemberExpr's base.
+    if (Result.InvalidBase)
+      Result.Offset = CharUnits::Zero();
+
----------------
I think you should bail out above, with the base set to the `MemberExpr` and with an empty designator, rather than applying a member designator on top of a base that already refers to the member (and then needing to undo the effect on the offset here).

================
Comment at: lib/AST/ExprConstant.cpp:6402
@@ +6401,3 @@
+  // that behaves this way.
+  if (End.InvalidBase && (Type & 1) != 0 &&
+      End.Designator.MostDerivedIsArrayElement &&
----------------
This only seems necessary when `Type` is 1; for type 3, returning 1 would be conservatively correct as a lower bound on the known-accessible storage, and is better than giving up here and evaluating the object size as 0.

================
Comment at: lib/AST/ExprConstant.cpp:6403-6404
@@ +6402,4 @@
+  if (End.InvalidBase && (Type & 1) != 0 &&
+      End.Designator.MostDerivedIsArrayElement &&
+      End.Designator.MostDerivedArraySize < 2) {
+    // EM_FoldDesignator requires that all invalid bases be MemberExprs
----------------
Ideally, we should walk the designator and make sure that at each step we picked the last subobject (last array element, last field, ...) -- that is, we want to know that we're really looking at a trailing flexible array member, and not just a size-1 array in the middle of some object.

You should also check that the designator refers to the most-derived object (that is, that `Entries.size() == MostDerivedPathLength`), because given:

  struct A { char buffer[10]; };
  struct B : A {};
  struct C { B b[1]; } *c;
  int m = __builtin_object_size(c->b[0], 1);
  int n = __builtin_object_size((A*)c->b[0], 1);

... we should presumably compute `m == -1` but `n == 10`, because for `n` the `A` subobject of the `B` object is known to have size 10, even though we're looking at a base subobject of a size-1 trailing array.


http://reviews.llvm.org/D12821





More information about the cfe-commits mailing list