Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

Science is to computer science as hydrodynamics is to plumbing.


devel / comp.lang.c / Incomplete Struct

SubjectAuthor
* Incomplete StructBart
+* Re: Incomplete Structrbowman
|`* Re: Incomplete StructKaz Kylheku
| `* Re: Incomplete Structrbowman
|  `* Re: Incomplete StructKaz Kylheku
|   `- Re: Incomplete Structrbowman
+* Re: Incomplete StructKaz Kylheku
|`* Re: Incomplete StructBart
| `* Re: Incomplete StructChris M. Thomasson
|  +* Re: Incomplete StructChris M. Thomasson
|  |`* Re: Incomplete StructBart
|  | `* Re: Incomplete StructRichard Damon
|  |  `* Re: Incomplete StructChris M. Thomasson
|  |   `* Re: Incomplete StructBen Bacarisse
|  |    `* Re: Incomplete StructChris M. Thomasson
|  |     +- Re: Incomplete StructChris M. Thomasson
|  |     `* Re: Incomplete StructAnton Shepelev
|  |      `- Re: Incomplete StructKaz Kylheku
|  `- Re: Incomplete StructBart
+* Re: Incomplete StructAndrey Tarasevich
|+- Re: Incomplete StructAndrey Tarasevich
|`- Re: Incomplete StructAndrey Tarasevich
+* Re: Incomplete StructDavid Brown
|`* Re: Incomplete StructBart
| `- Re: Incomplete StructManfred
`* Re: Incomplete StructBart
 `* Re: Incomplete StructKaz Kylheku
  `* Re: Incomplete StructBart
   `- Re: Incomplete StructKaz Kylheku

Pages:12
Incomplete Struct

<thscrh$1upp$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23436&group=comp.lang.c++#23436

  copy link   Newsgroups: comp.lang.c
 by: Bart - Sat, 8 Oct 2022 17:43 UTC

Can anyone explain why this isn't liked by gcc and clang:

struct tag {
int a,b,c,d;
struct tag (*e)[];
};

The last member is a pointer to unbounded array of 'struct tag'.

gcc complains of an incomplete type, and clang says something about the
struct not being complete until the closing }.

Yet, a last member of 'struct tag *e;', or even as a first member, is
fine, even though the } is some way off.

Neither tcc nor bcc compilers have a problem with it, and report a size
of 24 bytes.

Also, what is the workaround here?

Re: Incomplete Struct

<jqdtmhFlnb9U1@mid.individual.net>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23437&group=comp.lang.c++#23437

  copy link   Newsgroups: comp.lang.c
 by: rbowman - Sat, 8 Oct 2022 18:26 UTC

On 10/8/22 11:43, Bart wrote:
> Can anyone explain why this isn't liked by gcc and clang:
>
>
>     struct tag {
>         int a,b,c,d;
>         struct tag (*e)[];
>     };

Which version of gcc? I've been chasing a similar problem. A PostgreSQL
EDPG header file has

struct sqlca_t *ECPGget_sqlca(void);

#ifndef POSTGRES_ECPG_INTERNAL
#define sqlca (*ECPGget_sqlca())
#endif

gcc 10.2 on a Debian machine chokes on the #define. gcc 9.2 on a Ubuntu
wsl and gcc 11.2 on a bare metal Ubuntu installation have no problem
with it. It seems all gcc's aren't created equal.

Re: Incomplete Struct

<20221008112040.884@kylheku.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23438&group=comp.lang.c++#23438

  copy link   Newsgroups: comp.lang.c
 by: Kaz Kylheku - Sat, 8 Oct 2022 18:34 UTC

On 2022-10-08, Bart <bc@freeuk.com> wrote:
> Can anyone explain why this isn't liked by gcc and clang:
>
>
> struct tag {
> int a,b,c,d;
> struct tag (*e)[];
> };
>
> The last member is a pointer to unbounded array of 'struct tag'.
>
> gcc complains of an incomplete type, and clang says something about the
> struct not being complete until the closing }.

It seems you've hit a corner case by writing weird code.

Not handling this looks broken to me. A complete struct type is
not technically required to to declare a pointer to an array
of that struct type; the struct type just has to be complete by
the time code occurs where the array is used.

(Whether or not there is such a constraint violation is immaterial; it's
technically doable the same way void * pointers can be incremented by a
byte by GCC. GCC should handle this, whether by requirement or as
a matter of a reasonable extension.)

> Yet, a last member of 'struct tag *e;', or even as a first member, is
> fine, even though the } is some way off.
>
> Neither tcc nor bcc compilers have a problem with it, and report a size
> of 24 bytes.
>
> Also, what is the workaround here?

What is the use case for a pointer to an incomplete array?

If it were to work, you cannot do this

sizeof *instance.e

to get the size of the array. Because it's an array, when you evaluate
it it gives you a pointer to the first element.

So, you have an array whose size you cannot calculate which gives you
a pointer when you use it. Why not just use a pointer.

struct tag *e; // pointer to first element of array-like object
// of unknown size

and you don't have to do a silly dereference to use this;
just instance.e rather than *instance.e.

Of course, the downside is that you have to edit all code that
is using *instance.e or instance.e[0] to produce the array
expression which then yields the pointer.

You might also be enjoying the constraint that an assignment
like (*instance.e) = ... is a constraint violation, since
arrays are not assignable. Whereas (instance.e) = ... will cheerfully
overwrite the pointer, unless that pointer is const.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Re: Incomplete Struct

<20221008113800.827@kylheku.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23439&group=comp.lang.c++#23439

  copy link   Newsgroups: comp.lang.c
 by: Kaz Kylheku - Sat, 8 Oct 2022 18:40 UTC

On 2022-10-08, rbowman <bowman@montana.com> wrote:
> On 10/8/22 11:43, Bart wrote:
>> Can anyone explain why this isn't liked by gcc and clang:
>>
>>
>>     struct tag {
>>         int a,b,c,d;
>>         struct tag (*e)[];
>>     };
>
> Which version of gcc? I've been chasing a similar problem.

It doesn't look even remotely related to me.

A problem with some #define has absolutely nothing to with
a pointer to an incomplete array of an incomplete struct.

Care to connect the dots?

> A PostgreSQL
> EDPG header file has
>
> struct sqlca_t *ECPGget_sqlca(void);
>
> #ifndef POSTGRES_ECPG_INTERNAL
> #define sqlca (*ECPGget_sqlca())
> #endif
>
>
> gcc 10.2 on a Debian machine chokes on the #define. gcc 9.2 on a Ubuntu

That's amazing; it's just a simple preprocessor #define.

Maybe sqlca is an existing macro and the replacement sequence isn't
equivalent?

What is the diagnostic?

Is it choking on the #define itself, or some occurrence of sqlca?

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Re: Incomplete Struct

<thsp6o$94md$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23442&group=comp.lang.c++#23442

  copy link   Newsgroups: comp.lang.c
 by: Andrey Tarasevich - Sat, 8 Oct 2022 21:13 UTC

On 10/8/2022 10:43 AM, Bart wrote:
> Can anyone explain why this isn't liked by gcc and clang:
>
>
>     struct tag {
>         int a,b,c,d;
>         struct tag (*e)[];
>     };
>
> The last member is a pointer to unbounded array of 'struct tag'.
>
> gcc complains of an incomplete type, and clang says something about the
> struct not being complete until the closing }.
>
> Yet, a last member of 'struct tag *e;', or even as a first member, is
> fine, even though the } is some way off.
>

You ran into pretty much the same problem as in

struct S;

void foo(struct S *){}
void bar(struct S[]){}

The declaration of `bar` is legal, while the declaration of `foo` is
not, Even though for all practical means and purposes they are
equivalent. And they are actually supposed to become fully equivalent
after parameter type adjustment.

Nevertheless, C does not allow incomplete types in array declarations.
This rule kicks in before any other considerations do.

This is actually one of the differences between C and C++. C++ does not
apply the completeness requirement so early. In C++ my example is valid
as well as yours.

I believe there's a defect report dedicated to this matter and I also
vaguely recall that this was supposed to get fixed in C23.

--
Best regards,
Andrey

Re: Incomplete Struct

<thsp95$94md$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23443&group=comp.lang.c++#23443

  copy link   Newsgroups: comp.lang.c
 by: Andrey Tarasevich - Sat, 8 Oct 2022 21:15 UTC

On 10/8/2022 2:13 PM, Andrey Tarasevich wrote:
>
> You ran into pretty much the same problem as in
>
>   struct S;
>
>   void foo(struct S *){}
>   void bar(struct S[]){}
>
> The declaration of `bar` is legal, while the declaration of `foo` is
> not,

Oops.. Sorry, I ment to say it the other way around:

The declaration of `foo` is legal, while the declaration of `bar` is not.

--
Best regards,
Andrey

Re: Incomplete Struct

<thspen$94md$3@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23444&group=comp.lang.c++#23444

  copy link   Newsgroups: comp.lang.c
 by: Andrey Tarasevich - Sat, 8 Oct 2022 21:18 UTC

On 10/8/2022 2:13 PM, Andrey Tarasevich wrote:
>
> You ran into pretty much the same problem as in
>
>   struct S;
>
>   void foo(struct S *){}
>   void bar(struct S[]){}
>
> The declaration of `foo` is legal, while the declaration of `bar` is
> not,

<corrected>

.... and also, of course, before C23 we still need parameter names in C. So

struct S;
void foo(struct S *a){}
void bar(struct S a[]){}

The declaration of `foo` is legal, while the declaration of `bar` is not.

--
Best regards,
Andrey

Re: Incomplete Struct

<thsq1q$6t1$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23445&group=comp.lang.c++#23445

  copy link   Newsgroups: comp.lang.c
 by: Bart - Sat, 8 Oct 2022 21:28 UTC

On 08/10/2022 19:34, Kaz Kylheku wrote:
> On 2022-10-08, Bart <bc@freeuk.com> wrote:
>> Can anyone explain why this isn't liked by gcc and clang:
>>
>>
>> struct tag {
>> int a,b,c,d;
>> struct tag (*e)[];
>> };
>>
>> The last member is a pointer to unbounded array of 'struct tag'.
>>
>> gcc complains of an incomplete type, and clang says something about the
>> struct not being complete until the closing }.
>
> It seems you've hit a corner case by writing weird code.
>
> Not handling this looks broken to me. A complete struct type is
> not technically required to to declare a pointer to an array
> of that struct type; the struct type just has to be complete by
> the time code occurs where the array is used.
>
> (Whether or not there is such a constraint violation is immaterial; it's
> technically doable the same way void * pointers can be incremented by a
> byte by GCC. GCC should handle this, whether by requirement or as
> a matter of a reasonable extension.)
>
>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>> fine, even though the } is some way off.
>>
>> Neither tcc nor bcc compilers have a problem with it, and report a size
>> of 24 bytes.
>>
>> Also, what is the workaround here?
>
> What is the use case for a pointer to an incomplete array?

It comes up in generated C code.

This was the original C version of a benchmark:

struct Scene {
Vector center;
real radius;
struct Scene *child;
};

The last line is used for a dynamically-allocated, 5-element array
(created recursively).

I translated to my language where I use a proper 'pointer to array of
T', or 'T(*)[]', instead of the common C idiom of using T*.

But when mine gets transpiled back to C, then 'pointer to array of T` is
translated to `T(*)[]`, which C normally can cope with perfectly well,
even though it is rarely used.

It's in that context of a self-referential struct, that it gave problems.

Re: Incomplete Struct

<thsqsd$9a0m$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23446&group=comp.lang.c++#23446

  copy link   Newsgroups: comp.lang.c
 by: Chris M. Thomasson - Sat, 8 Oct 2022 21:42 UTC

On 10/8/2022 2:28 PM, Bart wrote:
> On 08/10/2022 19:34, Kaz Kylheku wrote:
>> On 2022-10-08, Bart <bc@freeuk.com> wrote:
>>> Can anyone explain why this isn't liked by gcc and clang:
>>>
>>>
>>>       struct tag {
>>>           int a,b,c,d;
>>>           struct tag (*e)[];
>>>       };
>>>
>>> The last member is a pointer to unbounded array of 'struct tag'.
>>>
>>> gcc complains of an incomplete type, and clang says something about the
>>> struct not being complete until the closing }.
>>
>> It seems you've hit a corner case by writing weird code.
>>
>> Not handling this looks broken to me.  A complete struct type is
>> not technically required to to declare a pointer to an array
>> of that struct type; the struct type just has to be complete by
>> the time code occurs where the array is used.
>>
>> (Whether or not there is such a constraint violation is immaterial; it's
>> technically doable the same way void * pointers can be incremented by a
>> byte by GCC. GCC should handle this, whether by requirement or as
>> a matter of a reasonable extension.)
>>
>>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>>> fine, even though the } is some way off.
>>>
>>> Neither tcc nor bcc compilers have a problem with it, and report a size
>>> of 24 bytes.
>>>
>>> Also, what is the workaround here?
>>
>> What is the use case for a pointer to an incomplete array?
>
> It comes up in generated C code.
>
> This was the original C version of a benchmark:
>
>     struct Scene {
>       Vector center;
>       real radius;
>       struct Scene *child;
>     };
>
> The last line is used for a dynamically-allocated, 5-element array
> (created recursively).
>
> I translated to my language where I use a proper 'pointer to array of
> T', or 'T(*)[]', instead of the common C idiom of using T*.
>
> But when mine gets transpiled back to C, then 'pointer to array of T` is
> translated to `T(*)[]`, which C normally can cope with perfectly well,
> even though it is rarely used.
>
> It's in that context of a self-referential struct, that it gave problems.

Looks ready to link into a container of struct Scene's?

struct Scene* scene_head = nullptr; // ?

Re: Incomplete Struct

<thsr47$9a0m$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23447&group=comp.lang.c++#23447

  copy link   Newsgroups: comp.lang.c
 by: Chris M. Thomasson - Sat, 8 Oct 2022 21:46 UTC

On 10/8/2022 2:42 PM, Chris M. Thomasson wrote:
> On 10/8/2022 2:28 PM, Bart wrote:
>> On 08/10/2022 19:34, Kaz Kylheku wrote:
>>> On 2022-10-08, Bart <bc@freeuk.com> wrote:
>>>> Can anyone explain why this isn't liked by gcc and clang:
>>>>
>>>>
>>>>       struct tag {
>>>>           int a,b,c,d;
>>>>           struct tag (*e)[];
>>>>       };
>>>>
>>>> The last member is a pointer to unbounded array of 'struct tag'.
>>>>
>>>> gcc complains of an incomplete type, and clang says something about the
>>>> struct not being complete until the closing }.
>>>
>>> It seems you've hit a corner case by writing weird code.
>>>
>>> Not handling this looks broken to me.  A complete struct type is
>>> not technically required to to declare a pointer to an array
>>> of that struct type; the struct type just has to be complete by
>>> the time code occurs where the array is used.
>>>
>>> (Whether or not there is such a constraint violation is immaterial; it's
>>> technically doable the same way void * pointers can be incremented by a
>>> byte by GCC. GCC should handle this, whether by requirement or as
>>> a matter of a reasonable extension.)
>>>
>>>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>>>> fine, even though the } is some way off.
>>>>
>>>> Neither tcc nor bcc compilers have a problem with it, and report a size
>>>> of 24 bytes.
>>>>
>>>> Also, what is the workaround here?
>>>
>>> What is the use case for a pointer to an incomplete array?
>>
>> It comes up in generated C code.
>>
>> This was the original C version of a benchmark:
>>
>>      struct Scene {
>>        Vector center;
>>        real radius;
>>        struct Scene *child;
>>      };
>>
>> The last line is used for a dynamically-allocated, 5-element array
>> (created recursively).

Oh ouch.

So Scene::child is not used for a node link in a container. It points to
a dynamically allocated 5 element array of struct Scene's.

Sorry.

>>
>> I translated to my language where I use a proper 'pointer to array of
>> T', or 'T(*)[]', instead of the common C idiom of using T*.
>>
>> But when mine gets transpiled back to C, then 'pointer to array of T`
>> is translated to `T(*)[]`, which C normally can cope with perfectly
>> well, even though it is rarely used.
>>
>> It's in that context of a self-referential struct, that it gave problems.
>
> Looks ready to link into a container of struct Scene's?
>
> struct Scene* scene_head = nullptr; // ?
>
>

Re: Incomplete Struct

<thss71$1230$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23448&group=comp.lang.c++#23448

  copy link   Newsgroups: comp.lang.c
 by: Bart - Sat, 8 Oct 2022 22:05 UTC

On 08/10/2022 22:42, Chris M. Thomasson wrote:
> On 10/8/2022 2:28 PM, Bart wrote:
>> On 08/10/2022 19:34, Kaz Kylheku wrote:
>>> On 2022-10-08, Bart <bc@freeuk.com> wrote:
>>>> Can anyone explain why this isn't liked by gcc and clang:
>>>>
>>>>
>>>>       struct tag {
>>>>           int a,b,c,d;
>>>>           struct tag (*e)[];
>>>>       };
>>>>
>>>> The last member is a pointer to unbounded array of 'struct tag'.
>>>>
>>>> gcc complains of an incomplete type, and clang says something about the
>>>> struct not being complete until the closing }.
>>>
>>> It seems you've hit a corner case by writing weird code.
>>>
>>> Not handling this looks broken to me.  A complete struct type is
>>> not technically required to to declare a pointer to an array
>>> of that struct type; the struct type just has to be complete by
>>> the time code occurs where the array is used.
>>>
>>> (Whether or not there is such a constraint violation is immaterial; it's
>>> technically doable the same way void * pointers can be incremented by a
>>> byte by GCC. GCC should handle this, whether by requirement or as
>>> a matter of a reasonable extension.)
>>>
>>>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>>>> fine, even though the } is some way off.
>>>>
>>>> Neither tcc nor bcc compilers have a problem with it, and report a size
>>>> of 24 bytes.
>>>>
>>>> Also, what is the workaround here?
>>>
>>> What is the use case for a pointer to an incomplete array?
>>
>> It comes up in generated C code.
>>
>> This was the original C version of a benchmark:
>>
>>      struct Scene {
>>        Vector center;
>>        real radius;
>>        struct Scene *child;
>>      };
>>
>> The last line is used for a dynamically-allocated, 5-element array
>> (created recursively).
>>
>> I translated to my language where I use a proper 'pointer to array of
>> T', or 'T(*)[]', instead of the common C idiom of using T*.
>>
>> But when mine gets transpiled back to C, then 'pointer to array of T`
>> is translated to `T(*)[]`, which C normally can cope with perfectly
>> well, even though it is rarely used.
>>
>> It's in that context of a self-referential struct, that it gave problems.
>
> Looks ready to link into a container of struct Scene's?
>
> struct Scene* scene_head = nullptr; // ?
>
>

It uses the code below to initialise it. This is for a raytracing
demo/benchmark and I believe it creates a hierarchy of spheres.

The problem is in my using something like:

struct Scene (*child)[];

which I did not expect to be a problem. Since this is in generated code,
I can't apply a workaround to the generated C; it needs a general
solution applied within the transpiler.

struct Scene create(int level, Vec c, real r) {
struct Scene scene;
scene.center = *c;
if (level == 1) {
scene.radius = r;
scene.child = NULL;
} else {
real rn = 3*r/sqrt(12);
Vector aa, v, s;
scene.radius = 3*r;

scene.child = malloc(5*sizeof(struct Scene));
scene.child[0] = create(1, c, r);
scene.child[1] = create(level-1, add(&aa,c, scale(&s,rn,
vec(&v,-1, 1, -1))), r/2);
scene.child[2] = create(level-1, add(&aa,c, scale(&s,rn, vec(&v,
1, 1, -1))), r/2);
scene.child[3] = create(level-1, add(&aa,c, scale(&s,rn,
vec(&v,-1, 1, 1))), r/2);
scene.child[4] = create(level-1, add(&aa,c, scale(&s,rn, vec(&v,
1, 1, 1))), r/2);
}
return scene;
}

Re: Incomplete Struct

<thsske$1722$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23449&group=comp.lang.c++#23449

  copy link   Newsgroups: comp.lang.c
 by: Bart - Sat, 8 Oct 2022 22:12 UTC

On 08/10/2022 22:46, Chris M. Thomasson wrote:
> On 10/8/2022 2:42 PM, Chris M. Thomasson wrote:
>> On 10/8/2022 2:28 PM, Bart wrote:

>>> The last line is used for a dynamically-allocated, 5-element array
>>> (created recursively).
>
> Oh ouch.
>
> So Scene::child is not used for a node link in a container. It points to
> a dynamically allocated 5 element array of struct Scene's.

You've hit upon a significant problem with C's T* idiom to represent
pointers to arrays:

T* P;

Is P intended to point to a single instance of T, such as your linked
list, or to the first of an array of P? This is why I had to add the
comment.

C's has the means to do it properly. It's just that the syntax is so
damn ugly:

T (*P)[]; // instead of T *P;
(*P)[i] // instead of P[i];

so I don't blame people for doing what everyone else does (I do it too
when writing C).

Re: Incomplete Struct

<BRn0L.131525$6gz7.45275@fx37.iad>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23451&group=comp.lang.c++#23451

  copy link   Newsgroups: comp.lang.c
 by: Richard Damon - Sat, 8 Oct 2022 23:38 UTC

On 10/8/22 6:12 PM, Bart wrote:
> On 08/10/2022 22:46, Chris M. Thomasson wrote:
>> On 10/8/2022 2:42 PM, Chris M. Thomasson wrote:
>>> On 10/8/2022 2:28 PM, Bart wrote:
>
>>>> The last line is used for a dynamically-allocated, 5-element array
>>>> (created recursively).
>>
>> Oh ouch.
>>
>> So Scene::child is not used for a node link in a container. It points
>> to a dynamically allocated 5 element array of struct Scene's.
>
> You've hit upon a significant problem with C's T* idiom to represent
> pointers to arrays:
>
>      T* P;
>
> Is P intended to point to a single instance of T, such as your linked
> list, or to the first of an array of P? This is why I had to add the
> comment.
>
> C's has the means to do it properly. It's just that the syntax is so
> damn ugly:
>
>      T (*P)[];            // instead of T *P;
>      (*P)[i]              // instead of P[i];
>
> so I don't blame people for doing what everyone else does (I do it too
> when writing C).

Actually, I would say that in C it is more common to have a pointer INTO
an array than TO the array itself, so the pointer can be used to walk
through the array.

This used to be a lot more efficient than having a base address pointer
and adding an index, as that indexing as almost always needing to be an
explicit address calculation (at the assembly level) as the processors
tended to have more limited addressing modes.

The fact that an array name and a pointer to the first element of the
array use the same syntax means that it also uses the familiar syntax if
you want to use it that way.

Since C was built of the philosophy of "Trust The Programmer, and Give
him the most powerful tools you can", this method worked for the major
cases.

Programming has changed over the decades, and the compiler is expected
to do more work at making the program efficient, and to provide more
"checking" for the programmer, which moves programming a bit away from C
initial design decisions.

Re: Incomplete Struct

<jqet0sFq93lU1@mid.individual.net>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23453&group=comp.lang.c++#23453

  copy link   Newsgroups: comp.lang.c
 by: rbowman - Sun, 9 Oct 2022 03:20 UTC

On 10/8/22 12:40, Kaz Kylheku wrote:
> On 2022-10-08, rbowman <bowman@montana.com> wrote:
>> On 10/8/22 11:43, Bart wrote:
>>> Can anyone explain why this isn't liked by gcc and clang:
>>>
>>>
>>>     struct tag {
>>>         int a,b,c,d;
>>>         struct tag (*e)[];
>>>     };
>>
>> Which version of gcc? I've been chasing a similar problem.
>
> It doesn't look even remotely related to me.
>
> A problem with some #define has absolutely nothing to with
> a pointer to an incomplete array of an incomplete struct.
>
> Care to connect the dots?
>
>> A PostgreSQL
>> EDPG header file has
>>
>> struct sqlca_t *ECPGget_sqlca(void);
>>
>> #ifndef POSTGRES_ECPG_INTERNAL
>> #define sqlca (*ECPGget_sqlca())
>> #endif
>>
>>
>> gcc 10.2 on a Debian machine chokes on the #define. gcc 9.2 on a Ubuntu
>
> That's amazing; it's just a simple preprocessor #define.
>
> Maybe sqlca is an existing macro and the replacement sequence isn't
> equivalent?
>
> What is the diagnostic?
>
> Is it choking on the #define itself, or some occurrence of sqlca?
>

The #define itself. The error is cryptic. I don't have it in front of me
but it's something like 'expected { before ... ' Further on down the
pile in ecpglib.h there is a

#define SQLERROR sqlca.sqlerror

which fails. In the actual code sqlca is frequently used. This is
typical in IBM embedded sql programming. Postgres apparently wanted to
use 'struct sqlca_t' and maintain compatibility. What bothers me is it
seems to be that one gcc on Debian that takes exception.

I'll try 9.2. The Debian 10.2 also is unhappy with multiple definitions
caused by variables defined in header files. It always was poor practice
but when you're dealing with legacy code it happens. -fcommon puts them
all in a common memory pool which I believe was the prior default.

Re: Incomplete Struct

<20221008223523.779@kylheku.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23454&group=comp.lang.c++#23454

  copy link   Newsgroups: comp.lang.c
 by: Kaz Kylheku - Sun, 9 Oct 2022 05:37 UTC

On 2022-10-09, rbowman <bowman@montana.com> wrote:
> On 10/8/22 12:40, Kaz Kylheku wrote:
>> On 2022-10-08, rbowman <bowman@montana.com> wrote:
>>> On 10/8/22 11:43, Bart wrote:
>>>> Can anyone explain why this isn't liked by gcc and clang:
>>>>
>>>>
>>>>     struct tag {
>>>>         int a,b,c,d;
>>>>         struct tag (*e)[];
>>>>     };
>>>
>>> Which version of gcc? I've been chasing a similar problem.
>>
>> It doesn't look even remotely related to me.
>>
>> A problem with some #define has absolutely nothing to with
>> a pointer to an incomplete array of an incomplete struct.
>>
>> Care to connect the dots?
>>
>>> A PostgreSQL
>>> EDPG header file has
>>>
>>> struct sqlca_t *ECPGget_sqlca(void);
>>>
>>> #ifndef POSTGRES_ECPG_INTERNAL
>>> #define sqlca (*ECPGget_sqlca())
>>> #endif
>>>
>>>
>>> gcc 10.2 on a Debian machine chokes on the #define. gcc 9.2 on a Ubuntu
>>
>> That's amazing; it's just a simple preprocessor #define.
>>
>> Maybe sqlca is an existing macro and the replacement sequence isn't
>> equivalent?
>>
>> What is the diagnostic?
>>
>> Is it choking on the #define itself, or some occurrence of sqlca?
>>
>
> The #define itself. The error is cryptic. I don't have it in front of me
> but it's something like 'expected { before ... ' Further on down the

Like this?

$ cat > bad.c
struct foo

#include <limits.h>

$ gcc bad.c
bad.c:3:0: error: expected identifier or ‘(’ at end of input
#include <limits.h>

Are you sure you're not doing something silly around the header files?

Re: Incomplete Struct

<thtn5m$e2l7$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23455&group=comp.lang.c++#23455

  copy link   Newsgroups: comp.lang.c
 by: Chris M. Thomasson - Sun, 9 Oct 2022 05:45 UTC

On 10/8/2022 4:38 PM, Richard Damon wrote:
> On 10/8/22 6:12 PM, Bart wrote:
>> On 08/10/2022 22:46, Chris M. Thomasson wrote:
>>> On 10/8/2022 2:42 PM, Chris M. Thomasson wrote:
>>>> On 10/8/2022 2:28 PM, Bart wrote:
>>
>>>>> The last line is used for a dynamically-allocated, 5-element array
>>>>> (created recursively).
>>>
>>> Oh ouch.
>>>
>>> So Scene::child is not used for a node link in a container. It points
>>> to a dynamically allocated 5 element array of struct Scene's.
>>
>> You've hit upon a significant problem with C's T* idiom to represent
>> pointers to arrays:
>>
>>       T* P;
>>
>> Is P intended to point to a single instance of T, such as your linked
>> list, or to the first of an array of P? This is why I had to add the
>> comment.
>>
>> C's has the means to do it properly. It's just that the syntax is so
>> damn ugly:
>>
>>       T (*P)[];            // instead of T *P;
>>       (*P)[i]              // instead of P[i];
>>
>> so I don't blame people for doing what everyone else does (I do it too
>> when writing C).
>
> Actually, I would say that in C it is more common to have a pointer INTO
> an array than TO the array itself, so the pointer can be used to walk
> through the array.

I have to be missing your point...
__________________________
#include <stdio.h>

static int g_array[] = { 0, 1, 2, 3 };

int main()
{ int* array_0 = g_array;
int* array_1 = &g_array[0];

printf("array_0 = %p\n", (void*)array_0);
printf("array_1 = %p\n", (void*)array_1);

if (array_0 != array_1)
{
printf("WTF!!! Strange shit is about to occur...");
}

printf("*array_0 == %d\n", *array_0);
printf("*array_1 == %d\n", *array_1);
printf("*(array_0 + 1) == %d\n", *(array_0 + 1));
printf("*(array_1 + 2) == %d\n", *(array_1 + 2));
printf("array_0[3] == %d\n", array_0[3]);

return 0;
} __________________________

array_0 will always equal array_1.

[...]

Re: Incomplete Struct

<jqf8abFrsnvU1@mid.individual.net>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23456&group=comp.lang.c++#23456

  copy link   Newsgroups: comp.lang.c
 by: rbowman - Sun, 9 Oct 2022 06:33 UTC

On 10/8/22 23:37, Kaz Kylheku wrote:
> On 2022-10-09, rbowman <bowman@montana.com> wrote:
>> On 10/8/22 12:40, Kaz Kylheku wrote:
>>> On 2022-10-08, rbowman <bowman@montana.com> wrote:
>>>> On 10/8/22 11:43, Bart wrote:
>>>>> Can anyone explain why this isn't liked by gcc and clang:
>>>>>
>>>>>
>>>>>     struct tag {
>>>>>         int a,b,c,d;
>>>>>         struct tag (*e)[];
>>>>>     };
>>>>
>>>> Which version of gcc? I've been chasing a similar problem.
>>>
>>> It doesn't look even remotely related to me.
>>>
>>> A problem with some #define has absolutely nothing to with
>>> a pointer to an incomplete array of an incomplete struct.
>>>
>>> Care to connect the dots?
>>>
>>>> A PostgreSQL
>>>> EDPG header file has
>>>>
>>>> struct sqlca_t *ECPGget_sqlca(void);
>>>>
>>>> #ifndef POSTGRES_ECPG_INTERNAL
>>>> #define sqlca (*ECPGget_sqlca())
>>>> #endif
>>>>
>>>>
>>>> gcc 10.2 on a Debian machine chokes on the #define. gcc 9.2 on a Ubuntu
>>>
>>> That's amazing; it's just a simple preprocessor #define.
>>>
>>> Maybe sqlca is an existing macro and the replacement sequence isn't
>>> equivalent?
>>>
>>> What is the diagnostic?
>>>
>>> Is it choking on the #define itself, or some occurrence of sqlca?
>>>
>>
>> The #define itself. The error is cryptic. I don't have it in front of me
>> but it's something like 'expected { before ... ' Further on down the
>
> Like this?
>
> $ cat > bad.c
> struct foo
>
> #include <limits.h>
>
> $ gcc bad.c
> bad.c:3:0: error: expected identifier or ‘(’ at end of input
> #include <limits.h>
>
> Are you sure you're not doing something silly around the header files?

I logged in (it's a work machine) and did a little more testing. There
is definitely something strange going on. A simple example compiles
without a problem. The real code is quite a bit more complex, with a
number of additional flags. I'll deal with it Monday.

There is an intermediate step where ecpg converts a file with embedded
sql into a straight C file and adds some headers.

Re: Incomplete Struct

<87leppm06a.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23461&group=comp.lang.c++#23461

  copy link   Newsgroups: comp.lang.c
 by: Ben Bacarisse - Sun, 9 Oct 2022 16:28 UTC

"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:

> On 10/8/2022 4:38 PM, Richard Damon wrote:

>> Actually, I would say that in C it is more common to have a pointer
>> INTO an array than TO the array itself, so the pointer can be used to
>> walk through the array.
>
> I have to be missing your point...

It seems so.

> #include <stdio.h>
>
> static int g_array[] = { 0, 1, 2, 3 };
>
> int main()
> {
> int* array_0 = g_array;
> int* array_1 = &g_array[0];

Neither pointer is to an array. Both point (as it usual in C) to the
first element of the array.

A pointer TO the array itself would be

int (*array_2)[4] = &g_array;

This is a different type of pointer.

> array_0 will always equal array_1.

Yes, and array_0 and array_1 will always equal array_2 when suitably
converted. Pointers combine an address and a type.

--
Ben.

Re: Incomplete Struct

<thv3i2$i3kl$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23462&group=comp.lang.c++#23462

  copy link   Newsgroups: comp.lang.c
 by: David Brown - Sun, 9 Oct 2022 18:22 UTC

On 08/10/2022 19:43, Bart wrote:
> Can anyone explain why this isn't liked by gcc and clang:
>
>
>     struct tag {
>         int a,b,c,d;
>         struct tag (*e)[];
>     };
>
> The last member is a pointer to unbounded array of 'struct tag'.
>
> gcc complains of an incomplete type, and clang says something about the
> struct not being complete until the closing }.
>

That is correct. A type "array of something" can't be declared unless
the size of that something is known at the time. The size of "struct
tag" is not known when "e" is declared, so the type of "e" doesn't make
sense at that point in the code.

You know, and I know, what the size of "struct tag" is going to be. But
the language does not support it.

A more lenient compiler could say that it doesn't actually need the size
of "struct tag" at this point, and let you get away with it. A quick
test on godbolt.org suggests MSVC is happy with it. (Perhaps it is
treating it as C++, where this is allowed.) I also tried ICC, but that
crashed on this input, which is even less helpful!

I don't think it would be an unreasonable extension to C to allow cases
like this (as long as you don't have a flexible array member in the
struct itself). But it is not allowed in C at the moment.

> Yet, a last member of 'struct tag *e;', or even as a first member, is
> fine, even though the } is some way off.
>
> Neither tcc nor bcc compilers have a problem with it, and report a size
> of 24 bytes.
>
> Also, what is the workaround here?

Well, the usual C workaround for complicated types is to use "void *" in
the declaration and cast when you use it :-)

I'd say just use "struct tag * e;".

Re: Incomplete Struct

<thvbm7$ilmh$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23464&group=comp.lang.c++#23464

  copy link   Newsgroups: comp.lang.c
 by: Chris M. Thomasson - Sun, 9 Oct 2022 20:41 UTC

On 10/9/2022 9:28 AM, Ben Bacarisse wrote:
> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>
>> On 10/8/2022 4:38 PM, Richard Damon wrote:
>
>>> Actually, I would say that in C it is more common to have a pointer
>>> INTO an array than TO the array itself, so the pointer can be used to
>>> walk through the array.
>>
>> I have to be missing your point...
>
> It seems so.
>
>> #include <stdio.h>
>>
>> static int g_array[] = { 0, 1, 2, 3 };
>>
>> int main()
>> {
>> int* array_0 = g_array;
>> int* array_1 = &g_array[0];
>
> Neither pointer is to an array. Both point (as it usual in C) to the
> first element of the array.
>
> A pointer TO the array itself would be
>
> int (*array_2)[4] = &g_array;
>
> This is a different type of pointer.
>
>> array_0 will always equal array_1.
>
> Yes, and array_0 and array_1 will always equal array_2 when suitably
> converted. Pointers combine an address and a type.
>

For some reason, I like to encapsulate a fixed array in a struct, to
make things easier, in a sense...
__________________________
#include <stdio.h>

#define FOO_ARRAY_N 4

struct foo_array
{ int data[FOO_ARRAY_N];
};

static struct foo_array g_foo_array = { { 0, 1, 2, 3 } };

void
foo_array_printf(
struct foo_array const* const self
) {
for (unsigned long i = 0; i < FOO_ARRAY_N; ++i)
{
printf(
"(%p)::foo_array::data[%lu] = %d\n",
(void*)self,
i,
self->data[i]
);
}
}

int main()
{ struct foo_array* ptr_0 = &g_foo_array;

struct foo_array ptr_1 = *ptr_0;
ptr_1.data[0] += 1;
ptr_1.data[1] += 1;
ptr_1.data[2] += 1;
ptr_1.data[3] += 1;

foo_array_printf(ptr_0);
putchar('\n');
foo_array_printf(&ptr_1);

return 0;
} __________________________

;^)

Re: Incomplete Struct

<thvbt8$ilmh$2@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23466&group=comp.lang.c++#23466

  copy link   Newsgroups: comp.lang.c
 by: Chris M. Thomasson - Sun, 9 Oct 2022 20:45 UTC

On 10/9/2022 1:41 PM, Chris M. Thomasson wrote:
> On 10/9/2022 9:28 AM, Ben Bacarisse wrote:
>> "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> writes:
>>
>>> On 10/8/2022 4:38 PM, Richard Damon wrote:
>>
>>>> Actually, I would say that in C it is more common to have a pointer
>>>> INTO an array than TO the array itself, so the pointer can be used to
>>>> walk through the array.
>>>
>>> I have to be missing your point...
>>
>> It seems so.
>>
>>> #include <stdio.h>
>>>
>>> static int g_array[] = { 0, 1, 2, 3 };
>>>
>>> int main()
>>> {
>>>      int* array_0 = g_array;
>>>      int* array_1 = &g_array[0];
>>
>> Neither pointer is to an array.  Both point (as it usual in C) to the
>> first element of the array.
>>
>> A pointer TO the array itself would be
>>
>>        int (*array_2)[4] = &g_array;
>>
>> This is a different type of pointer.
>>
>>> array_0 will always equal array_1.
>>
>> Yes, and array_0 and array_1 will always equal array_2 when suitably
>> converted.  Pointers combine an address and a type.
>>
>
>
> For some reason, I like to encapsulate a fixed array in a struct, to
> make things easier, in a sense...
> __________________________
> #include <stdio.h>
>
>
> #define FOO_ARRAY_N 4
>
>
> struct foo_array
> {
>     int data[FOO_ARRAY_N];
> };
>
>
> static struct foo_array g_foo_array = { { 0, 1, 2, 3 } };
>
>
> void
> foo_array_printf(
>     struct foo_array const* const self
> ) {
>     for (unsigned long i = 0; i < FOO_ARRAY_N; ++i)
>     {
>         printf(
>             "(%p)::foo_array::data[%lu] = %d\n",
>             (void*)self,
>             i,
>             self->data[i]
>         );
>     }
> }
>
>
> int main()
> {
>     struct foo_array* ptr_0 = &g_foo_array;
>
>     struct foo_array ptr_1 = *ptr_0;

^^^^^^^^^^^^^^^^^

Humm... Using the name ptr_1 is not quite Kosher here. Perhaps, copy_0? ;^)

>     ptr_1.data[0] += 1;
>     ptr_1.data[1] += 1;
>     ptr_1.data[2] += 1;
>     ptr_1.data[3] += 1;
>
>     foo_array_printf(ptr_0);
>     putchar('\n');
>     foo_array_printf(&ptr_1);
>
>     return 0;
> }
> __________________________
>
> ;^)

Re: Incomplete Struct

<thvh45$1kfv$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23467&group=comp.lang.c++#23467

  copy link   Newsgroups: comp.lang.c
 by: Bart - Sun, 9 Oct 2022 22:14 UTC

On 09/10/2022 19:22, David Brown wrote:
> On 08/10/2022 19:43, Bart wrote:
>> Can anyone explain why this isn't liked by gcc and clang:
>>
>>
>>      struct tag {
>>          int a,b,c,d;
>>          struct tag (*e)[];
>>      };
>>
>> The last member is a pointer to unbounded array of 'struct tag'.
>>
>> gcc complains of an incomplete type, and clang says something about
>> the struct not being complete until the closing }.
>>
>
> That is correct.  A type "array of something" can't be declared unless
> the size of that something is known at the time.  The size of "struct
> tag" is not known when "e" is declared, so the type of "e" doesn't make
> sense at that point in the code.
>
> You know, and I know, what the size of "struct tag" is going to be.  But
> the language does not support it.
>
> A more lenient compiler could say that it doesn't actually need the size
> of "struct tag" at this point, and let you get away with it.  A quick
> test on godbolt.org suggests MSVC is happy with it.  (Perhaps it is
> treating it as C++, where this is allowed.)  I also tried ICC, but that
> crashed on this input, which is even less helpful!
>
> I don't think it would be an unreasonable extension to C to allow cases
> like this (as long as you don't have a flexible array member in the
> struct itself).  But it is not allowed in C at the moment.
>
>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>> fine, even though the } is some way off.
>>
>> Neither tcc nor bcc compilers have a problem with it, and report a
>> size of 24 bytes.
>>
>> Also, what is the workaround here?
>
> Well, the usual C workaround for complicated types is to use "void *" in
> the declaration and cast when you use it :-)
>
> I'd say just use "struct tag * e;".

I take it there isn't a proper way to do it then, with forward
references and such?

This is part of a project that reinstates a C backend from one of my
compilers from a few years ago. It's quite a lot of work even without
rewriting it.

A rewrite would probably use void* pointers and explicit casts
everywhere, but it's too big a job right now.

So I'll have to change the original source of this specific program to
try and avoid this issue.

--

My example in original language:

record scene =
int a,b,c,d
ref[]scene e
end

Output of C backend:

struct scene;

struct scene {
i64 a;
i64 b;
i64 c;
i64 d;
struct scene (*e)[];
};

(All struct tags have a forward reference, since they can be referenced
out of order in the original.)

Re: Incomplete Struct

<thvrcr$180r$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23468&group=comp.lang.c++#23468

  copy link   Newsgroups: comp.lang.c
 by: Manfred - Mon, 10 Oct 2022 01:09 UTC

On 10/10/2022 12:14 AM, Bart wrote:
> On 09/10/2022 19:22, David Brown wrote:
>> On 08/10/2022 19:43, Bart wrote:
>>> Can anyone explain why this isn't liked by gcc and clang:
>>>
>>>
>>>      struct tag {
>>>          int a,b,c,d;
>>>          struct tag (*e)[];
>>>      };
>>>
>>> The last member is a pointer to unbounded array of 'struct tag'.
>>>
>>> gcc complains of an incomplete type, and clang says something about
>>> the struct not being complete until the closing }.
>>>
>>
>> That is correct.  A type "array of something" can't be declared unless
>> the size of that something is known at the time.  The size of "struct
>> tag" is not known when "e" is declared, so the type of "e" doesn't
>> make sense at that point in the code.
>>
>> You know, and I know, what the size of "struct tag" is going to be.
>> But the language does not support it.
>>
>> A more lenient compiler could say that it doesn't actually need the
>> size of "struct tag" at this point, and let you get away with it.  A
>> quick test on godbolt.org suggests MSVC is happy with it.  (Perhaps it
>> is treating it as C++, where this is allowed.)  I also tried ICC, but
>> that crashed on this input, which is even less helpful!
>>
>> I don't think it would be an unreasonable extension to C to allow
>> cases like this (as long as you don't have a flexible array member in
>> the struct itself).  But it is not allowed in C at the moment.
>>
>>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>>> fine, even though the } is some way off.
>>>
>>> Neither tcc nor bcc compilers have a problem with it, and report a
>>> size of 24 bytes.
>>>
>>> Also, what is the workaround here?
>>
>> Well, the usual C workaround for complicated types is to use "void *"
>> in the declaration and cast when you use it :-)
>>
>> I'd say just use "struct tag * e;".
>
> I take it there isn't a proper way to do it then, with forward
> references and such?

It depends on what you mean by 'proper' - forward references appear to
not be an option, however a solution that looks proper to me has been
proposed:

struct tag {
int a,b,c,d;
struct tag *e;
};

Since you have an unbounded array e[] in the original, I don't see how
this simple rewrite limits you in any way - for sure it looks better
than void* to me.

The complication arises from the fact that there is a code generator
involved, so I understand it's not as trivial as just rewriting one line
of code, but that's a different topic than complex source per se.

That said, I agree that, at the language level, C could allow for what
you need here - I guess it has not been enough of a common case for the
committee to handle it properly.

>
> This is part of a project that reinstates a C backend from one of my
> compilers from a few years ago. It's quite a lot of work even without
> rewriting it.
>
> A rewrite would probably use void* pointers and explicit casts
> everywhere, but it's too big a job right now.
>
> So I'll have to change the original source of this specific program to
> try and avoid this issue.
>
>
> --
>
> My example in original language:
>
>     record scene =
>         int a,b,c,d
>         ref[]scene e
>     end
>
> Output of C backend:
>
>     struct scene;
>
>     struct scene {
>         i64 a;
>         i64 b;
>         i64 c;
>         i64 d;
>         struct scene (*e)[];
>     };
>
> (All struct tags have a forward reference, since they can be referenced
> out of order in the original.)

Re: Incomplete Struct

<ti40go$j4g$1@gioia.aioe.org>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23473&group=comp.lang.c++#23473

  copy link   Newsgroups: comp.lang.c
 by: Bart - Tue, 11 Oct 2022 15:01 UTC

On 08/10/2022 18:43, Bart wrote:
> Can anyone explain why this isn't liked by gcc and clang:
>
>
>     struct tag {
>         int a,b,c,d;
>         struct tag (*e)[];
>     };
>
> The last member is a pointer to unbounded array of 'struct tag'.
>
> gcc complains of an incomplete type, and clang says something about the
> struct not being complete until the closing }.
>
> Yet, a last member of 'struct tag *e;', or even as a first member, is
> fine, even though the } is some way off.
>
> Neither tcc nor bcc compilers have a problem with it, and report a size
> of 24 bytes.
>
> Also, what is the workaround here?

Apparently there is no workaround. However a member like this works:

struct tag *e[5];

So the original source was changed to use 'array 5 of pointer to struct'
instead of 'pointer array of struct'.

This is not a solution, it means changing the code in another language
to avoid the limitation in C. However there are other limitations
involving features I need to avoid.

So that this transpiler was never going to generate valid C for all
possible programs in the source language.

Re: Incomplete Struct

<20221011091135.687@kylheku.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=23474&group=comp.lang.c++#23474

  copy link   Newsgroups: comp.lang.c
 by: Kaz Kylheku - Tue, 11 Oct 2022 16:18 UTC

On 2022-10-11, Bart <bc@freeuk.com> wrote:
> On 08/10/2022 18:43, Bart wrote:
>> Can anyone explain why this isn't liked by gcc and clang:
>>
>>
>>     struct tag {
>>         int a,b,c,d;
>>         struct tag (*e)[];
>>     };
>>
>> The last member is a pointer to unbounded array of 'struct tag'.
>>
>> gcc complains of an incomplete type, and clang says something about the
>> struct not being complete until the closing }.
>>
>> Yet, a last member of 'struct tag *e;', or even as a first member, is
>> fine, even though the } is some way off.
>>
>> Neither tcc nor bcc compilers have a problem with it, and report a size
>> of 24 bytes.
>>
>> Also, what is the workaround here?
>
> Apparently there is no workaround. However a member like this works:
>
> struct tag *e[5];
>
> So the original source was changed to use 'array 5 of pointer to struct'
> instead of 'pointer array of struct'.

That wastefully puts five pointers into your structure where you
previously just had one. Why would you make it [5] rather than just [1]?

struct tag *e[1];

stores just one pointer, and its use requires the extra
dereference that the generated code needs without modifying
the generator in that regard:

struct tag *ptr = *inst.e

You have to modify how the assignments to the pointer are generated;
you can't assign inst.e, only *inst.e.

--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

Pages:12
server_pubkey.txt

rocksolid light 0.9.8
clearnet tor