Hi Richard,

On Mon, Jul 29, 2024 at 10:27:35AM GMT, Richard Biener wrote:
> On Sun, Jul 28, 2024 at 4:16 PM Alejandro Colomar <a...@kernel.org> wrote:
> >
> > There were two identical definitions, and none of them are available
> > where they are needed for implementing _Lengthof().  Merge them, and
> > provide the single definition in gcc/tree.{h,cc}, where it's available
> > for _Lengthof().
> >
> > Signed-off-by: Alejandro Colomar <a...@kernel.org>
> > ---
> >  gcc/cp/cp-tree.h              |  1 -
> >  gcc/cp/tree.cc                | 13 -------------
> >  gcc/rust/backend/rust-tree.cc | 13 -------------
> >  gcc/rust/backend/rust-tree.h  |  2 --
> >  gcc/tree.cc                   | 13 +++++++++++++
> >  gcc/tree.h                    |  1 +
> >  6 files changed, 14 insertions(+), 29 deletions(-)
> >

[...]

> > diff --git a/gcc/tree.cc b/gcc/tree.cc
> > index 2d2d5b6db6e..3b0adb4cd9f 100644
> > --- a/gcc/tree.cc
> > +++ b/gcc/tree.cc
> > @@ -3729,6 +3729,19 @@ array_type_nelts (const_tree type)
> >           ? max
> >           : fold_build2 (MINUS_EXPR, TREE_TYPE (max), max, min));
> >  }
> > +
> > +/* Return, as an INTEGER_CST node, the number of elements for TYPE
> > +   (which is an ARRAY_TYPE).  This counts only elements of the top
> > +   array.  */
> > +
> > +tree
> > +array_type_nelts_top (tree type)
> > +{
> > +  return fold_build2_loc (input_location,
> > +                     PLUS_EXPR, sizetype,
> > +                     array_type_nelts (type),
> > +                     size_one_node);
> > +}
> 
> But this is now extremely confusing API with array_type_nelts above this
> saying
> 
> /* Return, as a tree node, the number of elements for TYPE (which is an
>    ARRAY_TYPE) minus one.  This counts only elements of the top array.  */
> 
> so both are "_top".  And there's build_array_type_nelts that's taking
> the number of elements.
> 
> Can you please rename the existing array_type_nelts to
> array_type_nelts_minus_one?  Then _top could be dropped as well from
> the alternate API  you add.

I wanted to do that, but then I found other functions that are named
similarly, such as build_array_type_nelts(), and thought that I wasn't
sure if all of them should be renamed to _minus_one, or just some.  So
I decided to start without renaming.

But yeah, I think I should rename.  I'll prepare a patch for renaming it
independently of this patch set, and send it to be merged before this
patch set.

> I'll also note since array_type_nelts_top calls the other function and that 
> has
> 
>   /* 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;
> 
> the function should handle error_mark_node (and pass that down).

Hmmmm, now I understand that (! TYPE_DOMAIN (type))

        $ grep -rn return.array_type_nelts gcc
        gcc/cp/call.cc:12111:    return array_type_nelts_top (c->type);
        gcc/c-family/c-common.cc:4090:  return array_type_nelts_top (type);

        $ sed -n 12102,12119p gcc/cp/call.cc
        /* Return a tree representing the number of elements initialized by the
           list-initialization C.  The caller must check that C converts to an
           array type.  */

        static tree
        nelts_initialized_by_list_init (conversion *c)
        {
          /* If the array we're converting to has a dimension, we'll use that.  
*/
          if (TYPE_DOMAIN (c->type))
            return array_type_nelts_top (c->type);
          else
            {
              /* Otherwise, we look at how many elements the constructor we're
                 initializing from has.  */
              tree ctor = conv_get_original_expr (c);
              return size_int (CONSTRUCTOR_NELTS (ctor));
            }
        }

It seems that would fail when measuring for example

        #define memberof(T, member)  ((T){}.member)

        struct s {
                int x;
                int a[];
        };

        __lengthof__(memberof(struct s, a));

I guess?

        $ cat len.c 
        #include <stdio.h>

        #define memberof(T, member)  ((T){}.member)

        struct s {
                int x;
                int y[];
        };

        int
        main(int argc, char *argv[argc + 1])
        {
                int     a[42];
                size_t  n;

                (void) argv;

                //n = __lengthof__(argv);
                //printf("__lengthof__(argv) == %zu\n", n);

                n = __lengthof__(a);
                printf("lengthof(a):\t %zu\n", n);

                n = __lengthof__(long [99]);
                printf("lengthof(long [99]):\t %zu\n", n);

                n = __lengthof__(short [n - 10]);
                printf("lengthof(short [n - 10]):\t %zu\n", n);

                int  b[n / 2];
                n = __lengthof__(b);
                printf("lengthof(b):\t %zu\n", n);

                n = __lengthof__(memberof(struct s, y));
                printf("lengthof(memberof(struct s, y)):\t %zu\n", n);
        }
        alx@debian:~/tmp/gcc$ /opt/local/gnu/gcc/lengthof/bin/gcc len.c 
        alx@debian:~/tmp/gcc$ ./a.out 
        lengthof(a):     42
        lengthof(long [99]):     99
        lengthof(short [n - 10]):        89
        lengthof(b):     44
        lengthof(memberof(struct s, y)):         44

Indeed, it's misbehaving.  I'll have a look at that.  I'll probably have
to add an error similar to sizeof's one:

len.c: In function ‘main’:
len.c:37:19: error: invalid application of ‘sizeof’ to incomplete type ‘int[]’
   37 |         n = sizeof(memberof(struct s, y));
      |                   ^

Thanks!

> 
> Note array_type_nelts returns nelts - 1 because that avoids building
> a new tree node for arrays with lower bound zero.

What does it mean that the lower bound is zero?  I didn't understand
that part.

> 
> Thanks,
> Richard.
> 
> >  /* If arg is static -- a reference to an object in static storage -- then
> >     return the object.  This is not the same as the C meaning of `static'.

Have a lovely day!
Alex

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

Attachment: signature.asc
Description: PGP signature

Reply via email to