[clang] [BoundsSafety][Sema] Allow counted_by and counted_by_or_null on pointers where the pointee type is incomplete but potentially completable (PR #106321)

via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 13 09:20:34 PST 2025


================
@@ -186,4 +218,188 @@ bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
   return false;
 }
 
+static void EmitIncompleteCountedByPointeeNotes(Sema &S,
+                                                const CountAttributedType *CATy,
+                                                NamedDecl *IncompleteTyDecl,
+                                                bool NoteAttrLocation = true) {
+  assert(IncompleteTyDecl == nullptr || isa<TypeDecl>(IncompleteTyDecl));
+
+  if (NoteAttrLocation) {
+    // Note where the attribute is declared
+    // This is an approximation that's not quite right. This points to the
+    // the expression inside the attribute rather than the attribute itself.
+    //
+    // TODO: Implement logic to find the relevant TypeLoc for the attribute and
+    // get the SourceRange from that (#113582).
+    SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange();
+    S.Diag(AttrSrcRange.getBegin(), diag::note_named_attribute)
+        << CATy->getAttributeName(/*WithMacroPrefix=*/true) << AttrSrcRange;
+  }
+
+  if (!IncompleteTyDecl)
+    return;
+
+  // If there's an associated forward declaration display it to emphasize
+  // why the type is incomplete (all we have is a forward declaration).
+
+  // Note the `IncompleteTyDecl` type is the underlying type which might not
+  // be the same as `CATy->getPointeeType()` which could be a typedef.
+  //
+  // The diagnostic printed will be at the location of the underlying type but
+  // the diagnostic text will print the type of `CATy->getPointeeType()` which
+  // could be a typedef name rather than the underlying type. This is ok
+  // though because the diagnostic will print the underlying type name too.
+  // E.g:
+  //
+  // `forward declaration of 'Incomplete_Struct_t'
+  //  (aka 'struct IncompleteStructTy')`
+  S.Diag(IncompleteTyDecl->getBeginLoc(), diag::note_forward_declaration)
+      << CATy->getPointeeType();
+}
+
+static std::tuple<const CountAttributedType *, QualType>
+HasCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND) {
+  auto *CATy = Ty->getAs<CountAttributedType>();
+  if (!CATy)
+    return {};
+
+  // Incomplete pointee type is only a problem for
+  // counted_by/counted_by_or_null
+  if (CATy->isCountInBytes())
+    return {};
+
+  auto PointeeTy = CATy->getPointeeType();
+  if (PointeeTy.isNull())
+    return {}; // Reachable?
----------------
Sirraide wrote:

```suggestion
  auto PointeeTy = CATy->getPointeeType();
  if (PointeeTy.isNull())
    return {}; // Reachable?
```
Does a `CountAttributedType` *always* desugar to a `PointerType`? If so, then I don’t think this is reachable because `getPointeeType()` ignores type sugar. In that case, we might want to add `assert(!PointeeTy.isNull())` here?

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


More information about the cfe-commits mailing list