This is the mail archive of the gcc-bugs@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]
Other format: [Raw text]

[Bug c++/68710] New: flexible array member of a base class accepted in a non-empty derived class


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68710

            Bug ID: 68710
           Summary: flexible array member of a base class accepted in a
                    non-empty derived class
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: msebor at gcc dot gnu.org
  Target Milestone: ---

G++ accepts definitions of non-empty derived classes whose base class contains
a flexible array member.  While such base classes are valid on their own (for
compatibility with C), they cannot be derived from by non-empty classes that
contain data members of their own since accessing elements of the base class
would make it possible to access the derived class.  The following example
shows why such constructs need to be rejected.  The output shows that modifying
elements of the flexible array member modifies other members of the object. 
The abort implies that GCC itself assumes that flexible array members do not
alias other members of the same object.

$ cat z.cpp && /build/gcc-trunk-svn/gcc/xgcc -B /build/gcc-trunk-svn/gcc -O2
-Wall -Wextra -Wpedantic -L ~/bin/gcc-5.1.0/lib64 -xc++ z.cpp && ./a.out
struct A {
    const char *a;
    const char *b[];
};

struct B: A {
    const char *c;
};

extern "C" {
    void free (void*);
    void* malloc (__SIZE_TYPE__);
    int printf (const char*, ...);
}

void foo (B *b)
{
    const char* const s = "";

    b->c = s;

    b->b [0] = 0;

    if (b->c != s)
        __builtin_abort (); 
}

int main ()
{
    B *b = (B*)malloc (sizeof *b + 2 * sizeof *b->b);
    b->a = "a";
    b->c = "c";
    b->b [0] = "b[0]";
    b->b [1] = "b[1]";
    b->b [2] = "b[2]";
    b->b [3] = "b[3]";

    printf ("{ { a = %s, b = { %s, %s, %s, %s } }, c = %s }\n",
            b->a, b->b[0], b->b[1], b->b[2], b->b[3], b->c);

    foo (b);

    free (b);
}
z.cpp:3:19: warning: ISO C++ forbids zero-size array âbâ [-Wpedantic]
     const char *b[];
                   ^

{ { a = a, b = { b[0], b[1], b[2], b[3] } }, c = b[0] }
Aborted (core dumped)

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