[clang] [Clang] Fix __is_array returning true for zero-sized arrays (PR #86652)

Nikolas Klauser via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 28 15:28:53 PDT 2024


philnik777 wrote:

> I wonder if we should be considering making zero-length arrays into a non-conforming extension behind a flag? e.g., `-fzero-sized-arrays` and then it does report true for `__is_array`, `__is_bounded_array`, and handles template specializations, etc as though it were really an array. That solves two problems: 1) we can make the feature regular as opposed to having so many sharp edges, 2) it pushes a surprising and questionable extension behind an opt-in feature flag, and it creates at least one problem: 1) potentially would change behavior of existing code in C++. So maybe this isn't a tenable idea, but do we think it's worth exploring?

I think it may be worth exploring, but I'm not sure it's feasible. We've been using them accidentally a lot in the test suite in libc++ simply because it's really easy to miss that it's an extension, and we're also using it in our `string` implementation for padding.

> > My natural inclination is that it is array-like, but... that just makes me want `__is_array` to return `true` for it all the more.
> 
> Yes. An array is an array, regardless of its size. The size is just a storage characteristic. It'd almost be like arguing that `NaN` isn't a float.

I don't think the float analogy really works here. The fact is that zero-sized arrays aren't acknowledged as being valid by the standard, so they don't behave like other arrays. It's _not_ just a storage characteristic. Having `-ffast-math` and then passing `NAN` somewhere seems like a better analogy to me. Things are mostly treated as if `NAN` didn't exist, and `NAN` also doesn't work like other floats.

> > I wonder if we should be considering making zero-length arrays into a non-conforming extension behind a flag?
> 
> It was never as simple as zero-length arrays. It was also _trailing arrays of any size_ in structures. Those extensions create huge problems with being able to reason about the characteristics of arrays, and we do have a flag for this: `-fstrict-flex-arrays=3`. It is designed to disable all of the "treat it like a flexible array" logic for the old "fake flexible array" objects. But a flexible array is _still an array_. And also note that its size can _change at runtime_ (see the `counted_by` attribute), which even more clearly argues that you can't claim a flexible array isn't an array.

I'm not sure how the array being able to change its size at runtime makes it harder to claim it isn't one? non-zero-sized arrays don't do that. It's actually another thing that is different from the rest of the arrays.
I'm also not sure that it makes a ton of sense to talk about flexible arrays, since they aren't part of the type system, but `T[0]` happen to become flexible arrays if it is at the end of a struct (IIUC).

Another option (that I haven't thought deeply about): Make `T[0]` not be a type at all, i.e. make it illegal to `decltype`, `sizeof` etc. uses of it. I don't know how breaking that would be, and it's probably just as confusing as the current state of things, or even more so. Just wanted to throw it out.


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


More information about the cfe-commits mailing list