[Clang] Warn when a __counted_by flexible array member is in static storage
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
### Summary
A flexible array member annotated with `__counted_by` only makes
sense when the underlying object is dynamically allocated (e.g.
`malloc(sizeof(*p) + count * sizeof(elem))`). The `__counted_by`
attribute promises a runtime-aware bound on the trailing array; in
static storage that promise is fundamentally unsatisfiable, because
the count cannot grow or shrink the fixed allocation.
I'd like to propose a warning -- working name
`-Wcounted-by-static-allocation` -- that fires at the *declaration*
when a struct type with a `__counted_by` FAM is given automatic or
static storage.
### Why this matters
When the FAM lives in static storage, the value of `count` and the
size of the actual allocation are independent. The decay form of
`__bdos` returns the count-derived bound, layout-derived queries
(including `&fam`-style `__bdos`) return the physical storage, and
the two can disagree in either direction:
```c
typedef __SIZE_TYPE__ size_t;
struct annotated_flex {
size_t count;
char induce_padding;
char fam[] __attribute__((counted_by(count)));
};
// Initializer is 15 bytes; count says 10. Storage > count.
struct annotated_flex gaf = { .fam = \"i am very long\", .count = 10 };
size_t global_count_bound(void) {
// 10 -- consults count, under-reports the physical storage
return __builtin_dynamic_object_size(gaf.fam, 1);
}
size_t global_layout_bound(void) {
// 15 -- layout-derived, ignores count
return __builtin_dynamic_object_size(&gaf.fam, 1);
}
size_t local(size_t n) {
// storage is sizeof(struct annotated_flex) = 16, with 7 trailing
// bytes available to fam. count says n. If n > 7, count
// over-reports; if n < 7, layout over-reports.
struct annotated_flex af = { .count = n };
return __builtin_dynamic_object_size(af.fam, 1); // n
}
```
Neither answer is wrong on its own; both are reporting a different
property of the same suspect declaration. The right fix is almost
always to move the object to the heap, where `count` and storage are
designed to agree.
### Proposed behavior
- New warning `-Wcounted-by-static-allocation` (name TBD).
- Fires at the declaration of a variable with automatic or static
storage duration whose type (or a type it transitively contains?
open question) has a `__counted_by`-annotated FAM.
- Diagnostic should point at the declaration and ideally name the
FAM and its `count` field, so the user can see what was annotated.
- Fix-it is harder than the address-of case: the right rewrite is
often a heap allocation, which is too invasive for an automatic
fix-it. A note suggesting the pattern is probably sufficient.
Open question: should the warning fire on *any* static-storage
declaration of such a type, or only when the count and storage are
known to disagree (e.g. a global with an initializer whose FAM
element count differs from the `count` field's initializer)? The
broad form is simpler and catches more bugs; the narrow form has
fewer false positives. I'd lean broad with a note in the diagnostic.
### Default state
Off by default to start, opt-in via `-W` / `-Wall`. The static-FAM
pattern is rare in well-maintained code but does exist in some
codebases, so a soft launch lets adopters migrate before flipping
the default.
### Related
#206536 -- `-Wcounted-by-addrof`, a sibling proposal that catches
the *use* site (`&fam`) where the count is silently discarded. The
two warnings are complementary: this one catches the root cause
(annotation incompatible with static storage); the other catches
one specific symptom (`&fam` falling through to layout).
Contributor guide
Research direction
No implementation files, tests, or Clang entry points are named. Start by resolving the proposed warning's scope—any automatic or static declaration versus only known count/storage mismatches—and define the diagnostic, note, and default behavior; done means the warning semantics and coverage are agreed and validated by compiler tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100