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
> 

Reply via email to