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, и у него есть модульные тесты для инициализаторов массива. Однако, если я что-то не упускаю, нет теста на инициализацию автоматических массивов с объемной областью с неконстантными выражениями (проверяются только статические массивы с объемной областью и глобальные массивы). Здесь тестовый файл, который я нашел.
Итак, что сделка?
Ответы
Ответ 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, должны быть постоянными выражениями.