Bug 42121 - g++ should warn or error on internal 0 size array in struct
Summary: g++ should warn or error on internal 0 size array in struct
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.2
: P3 normal
Target Milestone: ---
Assignee: Martin Sebor
URL:
Keywords: accepts-invalid, diagnostic
Depends on:
Blocks: flexmembers
  Show dependency treegraph
 
Reported: 2009-11-20 15:55 UTC by David Resnick
Modified: 2016-02-05 22:37 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-06-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description David Resnick 2009-11-20 15:55:56 UTC
Currently g++ requires the -pedantic flag to give a warning on a zero sized array that is not the last field in a struct.  As far as I can see, this is actually always a significant error if it is not the trailing field in the struct...

Demonstration:
temp(510)$ cat zero-size-array.cpp
#include <iostream>
#include <cstddef>

struct bogus
{
    int a;
    char b[];
    int c;

} bogus;

int main(void)
{
    std::cout << "size of struct bogus =" << sizeof(bogus) << std::endl;
    std::cout << "offset of field b =" << offsetof(struct bogus, b) << std::endl;
    std::cout << "offset of field c =" << offsetof(struct bogus, b) << std::endl;
    return 0;
}
temp(511)$ g++ -Wall -o zero-size-array zero-size-array.cppsize-array.cppe-array.cpp
temp(512)$ zero-size-array        
size of struct bogus =8
offset of field b =4
offset of field c =4
temp(513)$ g++ -Wall  -pedantic -o zero-size-array zero-size-array.cppize-array.cpp
zero-size-array.cpp:7: error: ISO C++ forbids zero-size array 'b'
temp(514)$ g++ --version
g++ (GCC) 4.1.2 20070626 (Red Hat 4.1.2-14)

-David
Comment 1 Jonathan Wakely 2009-11-20 18:09:16 UTC
Looks like this is for compatibility with GNU C, which allows it, but only in the form char b[0] not char b[]
Comment 2 David Resnick 2009-11-20 18:38:31 UTC
(In reply to comment #1)
> Looks like this is for compatibility with GNU C, which allows it, but only in
> the form char b[0] not char b[]

b[] seems simply broken unless last in an array for the C99 "flexible array member" type stuff, no?  I'm not really convinced about the merits/utility of b[0] as an internal struct field either, it is an odd way to make a union maybe?

In standard C, a size 0 array is forbidden, at least in C99 doc I have handy, per constraint in section 6.7.5.2 indicating:

   Constraints

       [#1] The [ and ] may delimit an expression or *.  If [ and ]
       delimit an  expression  (which  specifies  the  size  of  an
       array), it shall have an integer type.  If the expression is
       a constant expression then it shall  have  a  value  greater
       than  zero.   The element type shall not be an incomplete or
       function type.
Comment 3 Jonathan Wakely 2009-11-20 18:49:40 UTC
(In reply to comment #2)
> In standard C, a size 0 array is forbidden, at least in C99 doc I have handy,

Yes, but it's a long-standing GNU extension:
http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Zero-Length.html#Zero-Length

The C++ front end says:
      /* As an extension we allow zero-sized arrays.  We always allow
         them in system headers because glibc uses them.  */

Maybe the C++ front-end could be made stricter, so that it accepts char b[0] (like the C front end) but not char b[] (which is a C99 flexible array member, and must be the last member)
Comment 4 David Resnick 2009-11-20 18:56:28 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > In standard C, a size 0 array is forbidden, at least in C99 doc I have handy,
> Yes, but it's a long-standing GNU extension:
> http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Zero-Length.html#Zero-Length
> The C++ front end says:
>       /* As an extension we allow zero-sized arrays.  We always allow
>          them in system headers because glibc uses them.  */
> Maybe the C++ front-end could be made stricter, so that it accepts char b[0]
> (like the C front end) but not char b[] (which is a C99 flexible array member,
> and must be the last member)

OK, but if you read that link the whole rationale is to do with it being the last field in a struct, not an internal member, right?  Seems like there is no possible use in an internal member, and not diagnosing this as warnable means you don't notice if, say, someone accidentally adds something after the flexible array member.  Which happened to us, which is why I noticed this issue.  If this will break existing usage, I see the reason not to change.  But I'm curious what possible use a non-terminal zero sized array in a struct might have.

-David
Comment 5 jsm-csl@polyomino.org.uk 2009-11-20 20:57:40 UTC
Subject: Re:  g++ should warn or error on internal 0 size
 array in struct

On Fri, 20 Nov 2009, david dot resnick at comverse dot com wrote:

> (In reply to comment #3)
> > (In reply to comment #2)
> > > In standard C, a size 0 array is forbidden, at least in C99 doc I have handy,
> > Yes, but it's a long-standing GNU extension:
> > http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Zero-Length.html#Zero-Length
> > The C++ front end says:
> >       /* As an extension we allow zero-sized arrays.  We always allow
> >          them in system headers because glibc uses them.  */
> > Maybe the C++ front-end could be made stricter, so that it accepts char b[0]
> > (like the C front end) but not char b[] (which is a C99 flexible array member,
> > and must be the last member)
> 
> OK, but if you read that link the whole rationale is to do with it being the
> last field in a struct, not an internal member, right?  Seems like there is no
> possible use in an internal member, and not diagnosing this as warnable means
> you don't notice if, say, someone accidentally adds something after the
> flexible array member.  Which happened to us, which is why I noticed this
> issue.  If this will break existing usage, I see the reason not to change.  But
> I'm curious what possible use a non-terminal zero sized array in a struct might
> have.

Several cases of C99 flexible array members that C99 does not permit are 
only diagnosed as pedwarns-if-pedantic for C because of glibc using them.  
(I gave an example in 
<http://gcc.gnu.org/ml/gcc-patches/2002-08/msg01149.html>.)  I haven't 
looked into why it does this.

Comment 6 David Resnick 2009-11-23 14:15:04 UTC
(In reply to comment #5)
> Subject: Re:  g++ should warn or error on internal 0 size
>  array in struct
> On Fri, 20 Nov 2009, david dot resnick at comverse dot com wrote:
> > (In reply to comment #3)
> > > (In reply to comment #2)
> > > > In standard C, a size 0 array is forbidden, at least in C99 doc I have handy,
> > > Yes, but it's a long-standing GNU extension:
> > > http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Zero-Length.html#Zero-Length
> > > The C++ front end says:
> > >       /* As an extension we allow zero-sized arrays.  We always allow
> > >          them in system headers because glibc uses them.  */
> > > Maybe the C++ front-end could be made stricter, so that it accepts char b[0]
> > > (like the C front end) but not char b[] (which is a C99 flexible array member,
> > > and must be the last member)
> > 
> > OK, but if you read that link the whole rationale is to do with it being the
> > last field in a struct, not an internal member, right?  Seems like there is no
> > possible use in an internal member, and not diagnosing this as warnable means
> > you don't notice if, say, someone accidentally adds something after the
> > flexible array member.  Which happened to us, which is why I noticed this
> > issue.  If this will break existing usage, I see the reason not to change.  But
> > I'm curious what possible use a non-terminal zero sized array in a struct might
> > have.
> Several cases of C99 flexible array members that C99 does not permit are 
> only diagnosed as pedwarns-if-pedantic for C because of glibc using them.  
> (I gave an example in 
> <http://gcc.gnu.org/ml/gcc-patches/2002-08/msg01149.html>.)  I haven't 
> looked into why it does this.

(In reply to comment #5)
> Subject: Re:  g++ should warn or error on internal 0 size
>  array in struct
> On Fri, 20 Nov 2009, david dot resnick at comverse dot com wrote:
> > (In reply to comment #3)
> > > (In reply to comment #2)
> > > > In standard C, a size 0 array is forbidden, at least in C99 doc I have handy,
> > > Yes, but it's a long-standing GNU extension:
> > > http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Zero-Length.html#Zero-Length
> > > The C++ front end says:
> > >       /* As an extension we allow zero-sized arrays.  We always allow
> > >          them in system headers because glibc uses them.  */
> > > Maybe the C++ front-end could be made stricter, so that it accepts char b[0]
> > > (like the C front end) but not char b[] (which is a C99 flexible array member,
> > > and must be the last member)
> > 
> > OK, but if you read that link the whole rationale is to do with it being the
> > last field in a struct, not an internal member, right?  Seems like there is no
> > possible use in an internal member, and not diagnosing this as warnable means
> > you don't notice if, say, someone accidentally adds something after the
> > flexible array member.  Which happened to us, which is why I noticed this
> > issue.  If this will break existing usage, I see the reason not to change.  But
> > I'm curious what possible use a non-terminal zero sized array in a struct might
> > have.
> Several cases of C99 flexible array members that C99 does not permit are 
> only diagnosed as pedwarns-if-pedantic for C because of glibc using them.  
> (I gave an example in 
> <http://gcc.gnu.org/ml/gcc-patches/2002-08/msg01149.html>.)  I haven't 
> looked into why it does this.

OK, can't argue with not breaking existing headers I suppose.  But this is to me clearly a bogus usage.  What are the semantics of using internal zero sized arrays in a struct?  They have the same offset as the following field and impose alignment restrictions on it.  Do they have the same nominal requirements as unions for usage (can't write one, read the other?)?  Or is the idea that if they are 0 sized and internal they are not to be used for any purpose whatsoever, and they are only not warnable because of existing usage in glibc headers?

Comment 7 Jonathan Wakely 2009-11-23 14:53:06 UTC
(In reply to comment #6)
> 
> OK, can't argue with not breaking existing headers I suppose.  But this is to
> me clearly a bogus usage.  What are the semantics of using internal zero sized
> arrays in a struct?  They have the same offset as the following field and
> impose alignment restrictions on it.  Do they have the same nominal
> requirements as unions for usage (can't write one, read the other?)?  Or is the
> idea that if they are 0 sized and internal they are not to be used for any
> purpose whatsoever, and they are only not warnable because of existing usage in
> glibc headers?

All good questions!

It should be possible to make the C++ front end stricter about these so that outside of system headers they are an error, downgradeable to a warning with -fpermissive. I might try that.



Comment 8 Jonathan Wakely 2010-10-27 21:31:30 UTC
The C++ front end is far too permissive, the comments below show what should change for compatibility with the C front end:

struct bogus
{
    int a;
    char b[];   // should be rejected, b[0] is ok
    int c;
};

struct bogus2 {
  int x[];      // should be rejected, x[0] is ok
};

struct ok {
  int a;
  int x[];
};

struct gnu_extension
{
  struct ok a;
};

If bogus::b and bogus2::x are declared as zero-length arrays, rather than flexible array members, then they are accepted by the C front end.
Comment 9 Martin Sebor 2015-11-16 20:15:36 UTC
Working on a patch.
Comment 10 Martin Sebor 2015-11-23 00:59:48 UTC
Patch posted for review:
https://gcc.gnu.org/ml/gcc-patches/2015-11/msg02595.html
Comment 11 Martin Sebor 2015-12-17 01:39:10 UTC
Author: msebor
Date: Thu Dec 17 01:38:35 2015
New Revision: 231734

URL: https://gcc.gnu.org/viewcvs?rev=231734&root=gcc&view=rev
Log:
Correct ChangeLogs for PR c++/42121 and related.

Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/testsuite/ChangeLog
Comment 12 Martin Sebor 2015-12-17 01:40:12 UTC
Fixed in r231665.