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
>