Подтвердить что ты не робот

Clang не может вызывать ошибку при инициализаторах без константы в режиме C89

Это ошибка в Clang? Следующий код:

#include <stdio.h>

int main(void)
{
    int foo = 42;
    int bar[1] = { foo };
    printf("%d\n", bar[0]);
    return 0;
}

Скомпилируется с использованием:

clang -Wall -Wextra -Werror -pedantic -pedantic-errors -std=c89 -o foo foo.c

Я не думаю, что он должен скомпилироваться, так как список инициализаторов bar[] содержит выражение, foo, которое не является константой времени компиляции. Действительно, если я использую gcc вместо clang, я получаю ожидаемые результаты:

$ gcc -Wall -Wextra -Werror -pedantic -pedantic-errors -std=c89 -o foo foo.c
foo.c: In function ‘main’:
foo.c:6: error: initializer element is not computable at load time

Этот вопрос и его принятый ответ, а также выдержки из это описание C89 предположим, что GCC прав, а Clang ошибочен:

Выражения в инициализаторе для статического объекта или для агрегата или объединения должны быть постоянными выражениями.

Моя версия clang:

$ clang -v
Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin11.4.2

Одна вещь, которую я заметил, это то, что последняя ревизия clang присутствует на opensource.apple.com, т.е. е. clang 425.0.24, является только 4-ю субминионными версиями старше моего clang, и у него есть модульные тесты для инициализаторов массива. Однако, если я что-то не упускаю, нет теста на инициализацию автоматических массивов с объемной областью с неконстантными выражениями (проверяются только статические массивы с объемной областью и глобальные массивы). Здесь тестовый файл, который я нашел.

Итак, что сделка?

4b9b3361

Ответ 1

Это выглядит как ошибка в старой версии clang, так как version 3.5 дает мне следующее предупреждение для этого кода:

warning: initializer for aggregate is not a compile-time constant [-Wc99-extensions]
int bar[1] = { foo };
             ^~~~~~~

и ошибка с вашими параметрами компиляции (видеть в прямом эфире).

Отсутствие публичного проекта C89, я обнаружил, что gcc имеет раздел Non-Constant Initializers, который гласит:

Как и в стандартных С++ и ISO C99, элементам агрегатного инициализатора для автоматической переменной не требуется быть постоянными выражениями в GNU C.

который подтверждает, что они должны были быть постоянными выражениями до C99.

Как сообщает нам вкладка, соответствующая цитата из стандарта C89 находится в разделе sectioon 3.5.7 и говорит:

Все выражения в инициализаторе для объекта с длительностью статического хранения или в списке инициализаций для объекта, который имеет тип aggregate или union, должны быть постоянными выражениями.