Bug 71912 - [6 regression] flexible array in struct in union rejected
Summary: [6 regression] flexible array in struct in union rejected
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 7.0
: P3 minor
Target Milestone: 6.3
Assignee: Martin Sebor
URL:
Keywords: rejects-valid
Depends on:
Blocks: flexmembers
  Show dependency treegraph
 
Reported: 2016-07-17 15:48 UTC by Ulrich Drepper
Modified: 2018-02-28 06:03 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 5.4.0
Known to fail: 6.1.0
Last reconfirmed: 2016-07-18 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ulrich Drepper 2016-07-17 15:48:53 UTC
I haven't researched in detail what the accepted wisdom about this code is but at the very least it is completely unnecessary to reject it, as the code shows.  Code like this is actually from an actual project of mine.

Take the code below.  gcc 6.1 and also the current trunk reject the code because:

v.cc:22:14: error: flexible array member ‘xyyzy::<anonymous union>::<anonymous struct>::s’ not at end of ‘struct xyyzy’
       char s[];
              ^
v.cc:25:14: note: next member ‘double xyyzy::<anonymous union>::<anonymous struct>::a’ declared here
       double d;
              ^
v.cc:18:8: note: in the definition of ‘struct xyyzy’
 struct xyyzy {
        ^~~~~


Clearly, the array 's' is not followed by 'a' in anything but a syntactic way.  The compiler does not reject the use of flexible arrays like this when the types are defined separately, as exampled of type 'baz' shows.

If the rejection is done deliberately at the very least the message must be fixed but I would also like to see a justification.

NB: the same code compiles fine in C.  This is why I added all the unnecessary 'struct'.


struct foo {
  int a;
  char s[];
};

struct bar {
  double d;
  char t[];
};

struct baz {
  union {
    struct foo f;
    struct bar b;
  } u;
};

struct xyyzy {
  union {
    struct {
      int a;
      char s[];
    } f;
    struct {
      double d;
      char t[];
    } b;
  } u;
};

struct baz b;
struct xyyzy x;
Comment 1 Manuel López-Ibáñez 2016-07-17 16:28:29 UTC
For what is worth, Clang does accept it in C++.
Comment 2 Ulrich Drepper 2016-07-18 11:15:59 UTC
If it is accepted that this code should work (as I also expect) then this bug should also be marked as a regression to 5.x.  6.1 at least is broken, I don't know when it stopped working.
Comment 3 Jakub Jelinek 2016-07-18 11:23:16 UTC
This changed with r231665.  I'll let Martin argue whether this is intentional or not and why.
Comment 4 Martin Sebor 2016-07-18 16:57:35 UTC
I confirm the code in the test case is meant to be accepted by G++ for compatibility with GCC but is rejected due to a bug in the find_flexarrays function in class.c.

That said, it's not completely clear that the code is valid according to the C definition of a flexible array member:

  As a special case, the last element of a structure with more than one named member may have an incomplete array type; this is called a /flexible array member/.

Although C doesn't define the term element, I think it means the last declared subobject of an object.

In the test case, neither of the two flexible array members is the last element of struct xyyzy (the last element is the subobject u).  Within the member u of struct xyyzy, the flexible array member f.s is not the last element of the structure xyyzy (b.t is the last element).

Even though GCC with -Wpedantic silently accepts the equivalent definition of struct xyyzy, it issues a diagnostic for baz supporting the interpretation above:

  warning: invalid use of structure with flexible array member

Since the struct definitions are equivalent, it seems that either they both should be diagnosed or neither should be.
Comment 5 Martin Sebor 2016-07-19 19:48:08 UTC
(In reply to Martin Sebor from comment #4)
> Even though GCC with -Wpedantic silently accepts the equivalent definition
> of struct xyyzy, it issues a diagnostic for baz supporting the
> interpretation above:
> 
>   warning: invalid use of structure with flexible array member
> 
> Since the struct definitions are equivalent, it seems that either they both
> should be diagnosed or neither should be.

Let me correct the above.  GCC does give a pedantic warning in both cases confirming that the test case is, strictly speaking, invalid.  (I must have missed it somehow.)  Clang too diagnoses it with -Wflexible-array-extensions:

  warning: 'u' may not be nested in a struct due to flexible array

I'm lowering the Severity to Minor but I will fix the C++ error for compatibility with GCC.
Comment 6 Martin Sebor 2016-07-22 19:15:25 UTC
Patch posted for review:
  https://gcc.gnu.org/ml/gcc-patches/2016-07/msg01505.html
Comment 7 Martin Sebor 2016-10-13 22:27:07 UTC
Author: msebor
Date: Thu Oct 13 22:26:36 2016
New Revision: 241143

URL: https://gcc.gnu.org/viewcvs?rev=241143&root=gcc&view=rev
Log:
PR c++/71912 - [6/7 regression] flexible array in struct in union rejected

gcc/cp/ChangeLog:

	PR c++/71912
	* class.c (struct flexmems_t):  Add members.
	(find_flexarrays): Add arguments.  Correct handling of anonymous
	structs.
	(diagnose_flexarrays): Adjust to issue warnings in addition to errors.
	(check_flexarrays): Add argument.
	(diagnose_invalid_flexarray): New functions.

gcc/testsuite/ChangeLog:

	PR c++/71912
	* g++.dg/ext/flexary4.C: Adjust.
	* g++.dg/ext/flexary5.C: Same.
	* g++.dg/ext/flexary9.C: Same.
	* g++.dg/ext/flexary19.C: New test.
	* g++.dg/ext/flexary18.C: New test.
	* g++.dg/torture/pr64312.C: Add a dg-error directive to an ill-formed
	regression test.
        * g++.dg/compat/struct-layout-1_generate.c (subfield): Add argument.
        Avoid generating a flexible array member in an array.


Added:
    trunk/gcc/testsuite/g++.dg/ext/flexary18.C
    trunk/gcc/testsuite/g++.dg/ext/flexary19.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/class.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
    trunk/gcc/testsuite/g++.dg/ext/flexary4.C
    trunk/gcc/testsuite/g++.dg/ext/flexary5.C
    trunk/gcc/testsuite/g++.dg/ext/flexary9.C
    trunk/gcc/testsuite/g++.dg/torture/pr64312.C
Comment 8 Martin Sebor 2016-10-13 22:28:01 UTC
Fixed on trunk in r241143.
Comment 9 Martin Sebor 2016-10-14 15:38:26 UTC
Author: msebor
Date: Fri Oct 14 15:37:54 2016
New Revision: 241168

URL: https://gcc.gnu.org/viewcvs?rev=241168&root=gcc&view=rev
Log:
PR c++/71912 - [6/7 regression] flexible array in struct in union rejected

gcc/cp/ChangeLog:
	* class.c (struct flexmems_t):  Add members.
	(find_flexarrays): Add arguments.  Correct handling of anonymous
	structs.
	(diagnose_flexarrays): Adjust to issue warnings in addition to errors.
	(check_flexarrays): Add argument.
	(diagnose_invalid_flexarray): New functions.

gcc/testsuite/ChangeLog:
	* g++.dg/ext/flexary4.C: Adjust.
	* g++.dg/ext/flexary5.C: Same.
	* g++.dg/ext/flexary9.C: Same.
	* g++.dg/ext/flexary19.C: New test.
	* g++.dg/ext/flexary18.C: New test.
	* g++.dg/torture/pr64312.C: Add a dg-error directive to an ill-formed
	regression test.
        * g++.dg/compat/struct-layout-1_generate.c (subfield): Add argument.
        Avoid generating a flexible array member in an array.


Modified:
    branches/gcc-6-branch/gcc/cp/ChangeLog
    branches/gcc-6-branch/gcc/cp/class.c
    branches/gcc-6-branch/gcc/testsuite/ChangeLog
    branches/gcc-6-branch/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c
    branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary4.C
    branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary5.C
    branches/gcc-6-branch/gcc/testsuite/g++.dg/ext/flexary9.C
    branches/gcc-6-branch/gcc/testsuite/g++.dg/torture/pr64312.C
Comment 10 Martin Sebor 2016-10-14 15:39:11 UTC
Backported to 6-branch in r241168.