================
@@ -1131,63 +1151,98 @@ llvm::Value *CodeGenFunction::emitCountedByPointerSize(
   //        cmp  = (cmp && index > 0)
   //    return cmp ? result : 0;
 
-  auto GetElementBaseSize = [&](QualType ElementTy) {
-    CharUnits ElementSize =
-        getContext().getTypeSizeInChars(ElementTy->getPointeeType());
-
-    if (ElementSize.isZero()) {
-      // This might be a __sized_by (or __counted_by) on a
-      // 'void *', which counts bytes, not elements.
-      [[maybe_unused]] auto *CAT = ElementTy->getAs<CountAttributedType>();
-      assert(CAT && "must have an CountAttributedType");
-
-      ElementSize = CharUnits::One();
+  auto GetPointeeSize = [&](QualType PtrTy) -> CharUnits {
+    assert(!PtrTy.isNull());
+    QualType PointeeTy = PtrTy->getPointeeType();
+    assert(!PointeeTy.isNull() &&
+           (PointeeTy->isVoidType() || !PointeeTy->isIncompleteType()) &&
+           "pointee type must have a computable size");
+
+    CharUnits PointeeSize = getContext().getTypeSizeInChars(PointeeTy);
+    if (PointeeSize.isZero()) {
+      // Support GNU extension of treating `void` having size 1.
+      PointeeSize = CharUnits::One();
     }
 
-    return std::optional<CharUnits>(ElementSize);
+    return PointeeSize;
   };
 
-  // Get the sizes of the original array element and the casted array element,
-  // if different.
-  std::optional<CharUnits> ArrayElementBaseSize =
-      GetElementBaseSize(ArrayBaseFD->getType());
-  if (!ArrayElementBaseSize)
-    return nullptr;
-
-  std::optional<CharUnits> CastedArrayElementBaseSize = ArrayElementBaseSize;
-  if (!CastedArrayElementTy.isNull() && CastedArrayElementTy->isPointerType()) 
{
-    CastedArrayElementBaseSize = GetElementBaseSize(CastedArrayElementTy);
-    if (!CastedArrayElementBaseSize)
-      return nullptr;
-  }
-
   bool IsSigned = CountFD->getType()->isSignedIntegerType();
+  const auto *CountAttributedTy =
+      ArrayBaseFD->getType()->getAs<CountAttributedType>();
+  assert(CountAttributedTy && "the field's type is not a CountAttributedType");
 
   //  count = ptr->count;
-  //  index = ptr->index;
+  //  index = idx;
   Value *Count, *Index;
   std::tie(Count, Index) = GetCountFieldAndIndex(
       *this, ME, ArrayBaseFD, CountFD, Idx, ResType, IsSigned);
   if (!Count)
     return nullptr;
 
-  //  array_element_size = sizeof (*ptr->array)
-  auto *ArrayElementSize = llvm::ConstantInt::get(
-      ResType, ArrayElementBaseSize->getQuantity(), IsSigned);
-
-  //  casted_array_element_size = sizeof (*((cast) ptr->array));
-  auto *CastedArrayElementSize = llvm::ConstantInt::get(
-      ResType, CastedArrayElementBaseSize->getQuantity(), IsSigned);
-
-  //  array_size = count * array_element_size;
-  Value *ArraySize = Builder.CreateMul(Count, ArrayElementSize, "array_size",
-                                       !IsSigned, IsSigned);
+  //  For the _or_null variants, a null pointer describes no accessible memory:
+  //    count = ptr->array ? count : 0;
+  if (CountAttributedTy->isOrNull()) {
+    assert(EmittedE && "emitBuiltinObjectSize always passes a non-null value");
+    Value *Ptr = nullptr;
+    if (!Idx) {
+      //  1) 'ptr->array'
+      // Reuse the already-emitted pointer value rather than re-loading `ME`.
+      // Re-loading would produce a second, observable access for a volatile
+      // pointer field
+      Ptr = EmittedE;
+    } else {
+      // 2) '&((cast) ptr->array)[idx]'
+      // FIXME: `EmittedE` is the element address, not `ptr->array`, so we fall
+      // back to re-emitting `ME` and the pointer field is loaded twice. This 
is
+      // normally harmless accept when the pointer is `volatile`. Avoiding that
----------------
delcypher wrote:

Thanks for spotting that. Fixed.

https://github.com/llvm/llvm-project/pull/213794
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to