On Mon, Jul 29, 2024 at 10:55 AM Alejandro Colomar <a...@kernel.org> wrote:
>
> 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.

Just array_type_nelts needs renaming, build_array_type_nelts is fine.

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

Thanks.

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

The point is that if you make this a general API it should be safe to be used,
not depending on constraints that are apparently checked right now.

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

It means the function can return TYPE_MAX_VALUE of the TYPE_DOMAIN
unchanged.

Richard.

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

Reply via email to