[kiv@kiv-hp15r161nr ~]$ cat test.c
#include <stdarg.h>
#include <stdbool.h>
void func(va_list arg) {
bool value = va_arg(arg, bool);
(void)value; // Нужно, чтобы оптимизатор не выпилил предыдущую строчку,
// в реальном коде value используется нормально.
}
[kiv@kiv-hp15r161nr ~]$ gcc -O2 -c -o test.o test.c
[kiv@kiv-hp15r161nr ~]$ objdump -d test.o
test.o: формат файла elf64-x86-64
Дизассемблирование раздела .text:
0000000000000000 <func>:
0: 0f 0b ud2
Если заменить bool на int во втором аргументе va_arg, то код получается валидный. Версия GCC 5.3.0. Аналогичная ситуация на arm-none-eabi-gcc той же версии (собственно, всё началось с того что я искал несуществующую ошибку в своём коде для STM32).
Что это? Я где-то нарушил стандарт? Почему компилятор не выдал ни одного предупреждения? Да ладно бы он просто сгенерировал кривой код - почему он вообще вставляет просто недопустимую инструкцию (то есть портит код абсолютно осознанно)? WTF?
P. S. Добавление опций -Wpedantic -Wextra ничего не меняет (компилятор не ругается ни на что). Невалидная инструкция генерируется при любом уровне оптимизаций (разве что с -O0 добавляются ещё инструкции для создания стекового фрейма).