Hi Martin, On Mon, Aug 05, 2024 at 06:05:15PM GMT, Martin Uecker wrote: > > > > However, if I turn on -Wvla, both get a warning: > > > > len.c: At top level: > > len.c:288:1: warning: ISO C90 forbids variable length array ‘x’ [-Wvla] > > 288 | void foo(char (*a)[3][*], int (*x)[__lengthof__(*a)]); > > | ^~~~ > > len.c:289:1: warning: ISO C90 forbids variable length array ‘x’ [-Wvla] > > 289 | void bar(char (*a)[*][3], int (*x)[__lengthof__(*a)]); > > | ^~~~ > > > > You should check the the result you get from __lengthof__ > is an integer constant expression in the first case. > > > I suspect that the problem is in: > > > > $ grepc -tfd array_type_nelts_minus_one gcc > > gcc/tree.cc:tree > > array_type_nelts_minus_one (const_tree type) > > { > > tree index_type, min, max; > > > > /* If they did it with unspecified bounds, then we should have already > > given an error about it before we got here. */ > > if (! TYPE_DOMAIN (type)) > > return error_mark_node; > > > > index_type = TYPE_DOMAIN (type); > > min = TYPE_MIN_VALUE (index_type); > > max = TYPE_MAX_VALUE (index_type); > > > > /* TYPE_MAX_VALUE may not be set if the array has unknown length. */ > > if (!max) > > { > > /* zero sized arrays are represented from C FE as complete types > > with > > NULL TYPE_MAX_VALUE and zero TYPE_SIZE, while C++ FE represents > > them as min 0, max -1. */ > > if (COMPLETE_TYPE_P (type) > > && integer_zerop (TYPE_SIZE (type)) > > && integer_zerop (min)) > > return build_int_cst (TREE_TYPE (min), -1); > > > > return error_mark_node; > > } > > > > return (integer_zerop (min) > > ? max > > : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min)); > > } > > > > With some debugging code, I've seen that in the fixed-length case, this > > reaches the last return (integer_zerop() is true, so it returns max), > > which is exactly the same as with any normal fixed-length array. > > > > In the variable-length case (i.e., [*][3]), it returns build_int_cst(). > > > > So, it seems my problem is that 'max' does not represent an integer > > constant, even though we know it is. Can we coerce it to an integer > > constant somehow? Or maybe it's some of the in_lengthof that's messing > > with me? > > > > I would suspect the logic related to the C_MAYBE_CONST_EXPR. > In your original patch this still used C_TYPE_VARIABLE_SIZE, > which is not what we want for lengthof.
Ahhh, I blindly pasted that from sizeof, IIRC. I'll check. Thanks a lot! > > > It is possible that you can not properly distinguish between > > > > > > int a[0][n]; > > > int a[*][n]; > > > > > > those two cases. The logic will treat the first as the second. > > > > Those can be distinguished. [0] triggers the zero test, while [*] > > triggers the second var test. > > Are you sure? Both types should have C_TYPE_VARIABLE_SIZE set to 1. You were right. They're the same. I was thinking of [0] vs [*], but [0][n] is bad. It gets treated as a VLA. I won't worry too much about it, since GCC doesn't properly support 0-length arrays. We'll have to worry about it if we start discussing full support for 0-length arrays. > > > I think this is ok for now. All this array stuff should be > > > implified and refactored anyway, but this is for another time. > > > > > > > > > I am also not sure you even need to use array_type_nelts in C > > > because there is never a non-zero minimum size. > > > > How should I get the number of elements without array_type_nelts()? Is > > there any other existing way to get it? It just had a good name that > > matched my grep, but maybe I'm missing something easier. > > Maybe it is ok, but there is also code which just adds one > to TYPE_MAX_VALUE. Hmmm. I'll check. > > Martin Cheers, Alex -- <https://www.alejandro-colomar.es/>
signature.asc
Description: PGP signature