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 <[email protected]> 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 <[email protected]> > > --- > > 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/>
signature.asc
Description: PGP signature
