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