I may have found a bug with GCC v4.8.2, but I want to check first before I submit it as it could be me doing something wrong!
The following code:
#include <vector>
struct Message
{
  typedef union {
    char byte;
    const char *str;
  } Parameter;
  Parameter p1;
  Parameter p2;
};
int main()
{
  std::vector<Message> messages_;
  messages_.push_back({{ .byte = 'a' }});
  Message message = {{ .byte = 'a' }, { .str = "Hello World" }};
  messages_.push_back(message);
  messages_.push_back({{ .byte = 'a' }, { .str = "Hello World" }});
}
clang++ -std=c++11 main.cpp compiles this fine. However g++ outputs this:
main.cpp: In function ‘int main()’:
main.cpp:23:66: internal compiler error: in reshape_init_class, at cp/decl.c:5216
   messages_.push_back({{ .byte = 'a' }, { .str = "Hello World" }});
                                                                  ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://bugzilla.redhat.com/bugzilla> for instructions.
Preprocessed source stored into /tmp/ccrf5vwr.out file, please attach this to your bugreport.
I'll submit this as a bug if nobody has any ideas, although in my experience a programmers problem is almost never a compiler bug and almost always a fault of his own!
As answered in the comments above: Any error message you get from GCC that includes the phrases internal compiler error and Please submit a full bug report is definitely a compiler bug, not your own fault! In this case, the bug appears to be something to do with GCC's parsing of {{ ... }} in C++ mode where the "..." includes a designated initializer. @Sam has reported it as GCC bug 59832.
However, as @Angew pointed out, this line —
messages_.push_back({{ .byte = 'a' }});
— is not valid C++. Standard C++ doesn't allow designated initializers; that's a C99 feature that was not adopted into C++ (neither C++11 nor C++14).
As for why designated initializers have been problematic to add to C++, see here, where Doug Gregor asks how the compiler should interpret things like
struct Foo {int x,y; };
void f(Foo);
void f(std::initializer_list<int>);
int main(){
    f({1});
    f({1,2});
    f({1,2,3});
    f({.x=1});
    f({.x=1,2});
    f({.x=1,2,3});
}
For the record, GCC 4.8 treats all six as calls to f(initializer_list<int>). Clang 3.5 treats the first three as calls to f(initializer_list<int>), the next two as calls to f(Foo), and the last one as ill-formed. Basically, it's a non-standard construct: different compilers are within their rights to treat it differently, and they do.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With