This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: c++/2478: false g++ error: incompatible types in assignment of `int* (*)[]' to `int *[0]'


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





Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]