Am Montag, dem 05.08.2024 um 17:27 +0200 schrieb Alejandro Colomar: > Hi Martin, > ...
> > But I think you might make it unnecessarily complicated. It > > should be sufficient to look at the outermost size. You > > can completely ignore thatever happens There > > should be three cases if I am not mistaken: > > > > - incomplete (includes ISO FAM) -> error > > - constant (includes GNU FAM) -> return fixed size > > - variable (includes unspecified) -> evaluate the > > argument and return the size, while making sure it is > > visibly non-constant. > > > > To check that the array has a variable length, you can use > > the same logic as in comptypes_internal (cf. d1_variable). > > Hmmm, comptypes_internal() has taught me what I was asking here. > However, it seems to not be enough for what I actually need. > > Here's my problem: > > The array is correctly considered a fixed-length array. I know it > because the following debugging code: > > +fprintf(stderr, "ALX: %s() %d\n", __func__, __LINE__); > +tree dom = TYPE_DOMAIN (type); > +int zero = !TYPE_MAX_VALUE (dom); > +fprintf(stderr, "ALX: zero: %d\n", zero); > +int var0 = !zero > + && (TREE_CODE (TYPE_MIN_VALUE (dom)) != INTEGER_CST > + || TREE_CODE (TYPE_MAX_VALUE (dom)) != INTEGER_CST); > +fprintf(stderr, "ALX: var: %d\n", var0); > +int var = var0 || (zero && TYPE_LANG_FLAG_1(type)); > +fprintf(stderr, "ALX: var: %d\n", var); > + ret = array_type_nelts_top (type); > +fprintf(stderr, "ALX: %s() %d\n", __func__, __LINE__); > > prints: > > ALX: c_lengthof_type() 4098 > ALX: zero: 0 > ALX: var: 0 > ALX: var: 0 > ALX: c_lengthof_type() 4109 > > for > void foo(char (*a)[3][*], int (*x)[__lengthof__(*a)]); > > That differs from > > ALX: c_lengthof_type() 4098 > ALX: zero: 1 > ALX: var: 0 > ALX: var: 1 > ALX: c_lengthof_type() 4109 > > for > void bar(char (*a)[*][3], int (*x)[__lengthof__(*a)]); That looks good. > > 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. > > > > 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. > > > 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. Martin > > Thanks! > > Cheers, > Alex > > > Martin >