Это ошибка GCC? Инициализация структур с помощью объединений

Возможно, я обнаружил ошибку с GCC v4.8.2, но сначала хочу проверить, прежде чем я отправлю ее, так как может быть, я что-то делаю неправильно!

Следующий код:

#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 компилирует этот штраф. Однако g++ выводит это:

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.

Я отправлю это как ошибку, если никто не имеет никаких идей, хотя по моему опыту проблема программистов почти никогда не является ошибкой компилятора и почти всегда является его собственной ошибкой!

Ответ 1

Как указано в комментариях выше: Любое сообщение об ошибке, которое вы получаете от GCC, которое содержит фразы internal compiler error и Please submit a full bug report, определенно является ошибкой компилятора, а не вашей собственной ошибкой! В этом случае ошибка, похоже, связана с GCC-анализом {{ ... }} в режиме С++, где "..." включает назначенный инициализатор. @Sam сообщила об этом как GCC ошибка 59832.

Однако, как заметил @Angew, эта строка -

messages_.push_back({{ .byte = 'a' }});

- недействителен С++. Стандартный С++ не позволяет назначать инициализаторы; что функция C99, которая не была принята в С++ (ни С++ 11, ни С++ 14).

Что касается того, почему назначенные инициализаторы были проблематичными для добавления в С++, см. здесь, где Дуг Грегор спрашивает, как компилятор должен интерпретировать такие вещи, как

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});
}

Для записи GCC 4.8 рассматривает все шесть в качестве вызовов f(initializer_list<int>). Clang 3.5 рассматривает первые три в качестве вызовов f(initializer_list<int>), а следующие два - в качестве вызовов f(Foo), а последний - неправильно сформированный. В принципе, это нестандартная конструкция: разные компиляторы находятся в пределах своих прав, чтобы относиться к ней по-другому, и они это делают.