Hi Martin,

On Mon, Aug 05, 2024 at 03:35:06PM GMT, Martin Uecker wrote:
> > > > > > For incomplete arrays, basically we have the following different
> > > > > > variants for arrays:
> > > > > > 
> > > > > > T[ ] incomplete: !TYPE_DOMAIN 
> > > > > > T[1] constant size: TYPE_MAX_VALUE == INTEGER_CST
> > > > > > T[n] variable size: TYPE_MAX_VALUE != INTEGER_CST
> > > > > > T[0] flexible array member: !TYPE_MAX_VALUE && !C_TYPE_VARIABLE_SIZE
> > > > > >   (ISO version T[0] has TYPE_SIZE == NULL_TREE)
> > > > > > T[*] unspecified variable size: !TYPE_MAX_VALUE && 
> > > > > > C_TYPE_VARIABLE_SIZE
> > > > > 
> > > > > Could you describe the following types?  I've repeated the ones you
> > > > > already described, deduplicated some that have a different meaning in
> > > > > different contexts, and added some multi-dimensional arrays.
> > > > > 
> > > > > T[ ]     (incomplete type; function parameter)
> > > > > T[ ]     (flexible array member)
> > > > > T[0]     (zero-size array)
> > > > > T[0]     (GNU flexible array member)
> > > > > T[1]     (old flexible array member)
> > > > > T[7]     (constant size)
> > > > > T[7][n]  (constant size with inner variable size)
> > > > > T[7][*]  (constant size with inner unspecified size)
> > > > 
> > > > And please also describe T[7][4], although I expect that to be just the
> > > > same as T[7].
> > > 
> > > And it would also be interesting to describe T[7][ ].
> > 
> > And maybe also:
> > 
> > T[n][m]
> > T[n][*]
> > T[n][ ]
> > T[n][7]
> 
> I do not understand your question. What do you mean by
> "describe the type"?

I had in mind what you already did above, (e.g.,
T[1] constant size: TYPE_MAX_VALUE == INTEGER_CST), but with a more
comprehensive list.  comptypes_internal() seems what I wanted.

> 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)]);

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)]);
              | ^~~~

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?

> 
> 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.

> 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.

Thanks!

Cheers,
Alex

> Martin

-- 
<https://www.alejandro-colomar.es/>

Attachment: signature.asc
Description: PGP signature

Reply via email to