This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: c++/2478: false g++ error: incompatible types in assignment of `int* (*)[]' to `int *[0]'
- To: "Kenneth Gole" <kengole at us dot ibm dot com>,<gcc-gnats at gcc dot gnu dot org>,"gcc" <gcc at gcc dot gnu dot org>
- Subject: Re: c++/2478: false g++ error: incompatible types in assignment of `int* (*)[]' to `int *[0]'
- From: "Dave Korn" <davek-ml at ntlworld dot com>
- Date: Sun, 8 Apr 2001 23:35:28 +0100
- Cc: "Don Pearl" <pearldl at us dot ibm dot com>
- References: <OFB0BC9C97.0C4EE768-ON85256A24.004F0525@pok.ibm.com>
----- Original Message -----
From: "Kenneth Gole" <kengole@us.ibm.com>
Sent: Wednesday, April 04, 2001 6:30 PM
Hi Ken,
I've spent some time looking into this problem, and you have found a bug
(or perhaps 'feature') in 2.95.3's C++ parser.
> If I simplify my example to look like this:
> --------------------------------------------------------------------------
> /* A demonstration of a gcc 2.95.3 problem - KenGole@us.ibm.com */
[Example snipped - see t2.C below]
Ok: this isn't the same as the example in your original mail, I guess you
retyped it rather than cut and paste it. Here is what you actually sent in
your first mail, and the result of compiling it:
8<-------------------------------
dkadmin@UBIK ~/test/gnat
$ cat t1.C
/* A demonstration of a gcc 2.95.3 problem - KenGole@us.ibm.com
<mailto:KenGole@
us.ibm.com> */
#include <stdio.h>
int main(void)
{
int *(*ArryPtr)[]=NULL; /* A pointer to an array of pointers */
int *(*p)[]; /* Same type as ArryPtr */
struct myStruct
{
int *(p)[]; /* Same type as ArryPtr */
} B;
p=ArryPtr; /* This compiles fine... */
B.p=ArryPtr; /* This fails to compile! */
return 0;
}
dkadmin@UBIK ~/test/gnat
$ gcc t1.C -o t1
t1.C: In function `int main()':
t1.C:13: incompatible types in assignment of `int * (*)[]' to `int *[0]'
8<-------------------------------
Please note that you probably meant to have an asterisk inside the
brackets around 'p' in the declaration of struct myStruct. With that
omission, p is an array of unknown size, which in a struct is the same thing
as an array of zero length, of pointers-to-ints. The square braces bind (p)
with higher priority than the *. Thus p is an actual zero length array of
(int *), and the pointer ArryPtr that you are trying to assign to it is a
pointer to an array of unknown size of (int *). p is not a pointer, and the
error message is correct. Note that zero-length array fields in structs are
a Gnu C extension. In standard C this would be treated as an incomplete
type.
In the simplified (and corrected) example you sent me, you had replaced
the asterisk inside the brackets, and hence p was indeed a pointer rather
than an array:
8<-------------------------------
dkadmin@UBIK ~/test/gnat
$ cat t2.C
/* A demonstration of a gcc 2.95.3 problem - KenGole@us.ibm.com
<mailto:KenGole@
us.ibm.com> */
#include <stdio.h>
int main(void)
{
int (*ArryPtr)[]=NULL; /* A pointer to an array of integers */
int (*q)[]; /* Same type as ArryPtr */
struct myStruct
{
int (*p)[]; /* Same type as ArryPtr */
} B;
q=ArryPtr; /* This compiles fine... */
B.p=ArryPtr; /* This fails to compile! */
return 0;
}
dkadmin@UBIK ~/test/gnat
$ gcc t2.C -o t2
t2.C: In function `int main()':
t2.C:13: assignment to `int (*)[0]' from `int (*)[]'
8<-------------------------------
And this is genuinely unexpected, and incorrect: p is not a pointer to a
zero length array, but to an array of unknown length. The parser is perhaps
confused by the struct context, and thinks because we are in a struct (where
an unsized array would be zero length) that this pointer is to a zero length
rather than unsized array. Interestingly enough, the bug does not occur
when we compile the example in C:
8<-------------------------------
dkadmin@UBIK ~/test/gnat
$ mv t2.C t2.c
dkadmin@UBIK ~/test/gnat
$ gcc t2.c -o t2
dkadmin@UBIK ~/test/gnat
$
8<-------------------------------
So you have indeed stumbled across a bug in the C++ parser. It is
misinterpreting the empty square braces as indicating a zero-sized, rather
than unknown sized array; hence the error message. This is because of the
following piece of code in gcc-2.95.3/gcc/cp/decl.c, at lines 10381+
8<-------------------------------
/* VC++ spells a zero-sized array with []. */
if (size == NULL_TREE && decl_context == FIELD && ! staticp
&& ! RIDBIT_SETP (RID_TYPEDEF, specbits))
size = integer_zero_node;
8<-------------------------------
It's clearly been put in as an aid to source compatibility with VC++. If
you remove these lines, your program will be parsed correctly. I'm not sure
if this is the ideal solution, however; I'm not enough of a parsing expert
to be sure this patch won't have unforeseen complications. I'm crossposting
this message to the main gcc list because I think I remember a conversation
here a couple of months back about this very subject in the 3.0 tree.
Removing these lines has the following effects on compiling the two tests
above:
8<-------------------------------
dkadmin@UBIK ~/test/gnat
$ ~/prerelease/2953/gcc/xgcc.exe -B ~/prerelease/2953/gcc/ t1.C -o t1b
t1.C: In function `int main()':
t1.C:10: field `p' has incomplete type
t1.C:11: confused by earlier errors, bailing out
dkadmin@UBIK ~/test/gnat
$ ~/prerelease/2953/gcc/xgcc.exe -B ~/prerelease/2953/gcc/ t2.C -o t2b
dkadmin@UBIK ~/test/gnat
$
8<-------------------------------
so I guess you've lost the Gnu C zero-length-array-in-a-struct extension,
but you get back your proper compatibility.
Can anyone on the main list suggest a better solution ?
DaveK