ошибка declspec при компиляции файла clang ‹noreturn.h› вместе с заголовками Windows

Я пытаюсь получить проект моей сборки на Windows, что для меня впервые. Я новичок в платформе. Я использую clang-cl для поддержки C11. Источник изначально использовал noreturn из <stdnoreturn.h> для аннотации функции, которая никогда не вернется. В итоге я получил целую кучу ошибок declspec при компиляции и сузил их до настолько тривиального файла, насколько мог.

#include <stdnoreturn.h>
#include <stdlib.h>

Либо сами по себе сборки хороши, но вместе они выдают длинный список ошибок, все точно такой же тип:

__declspec attributes must be an identifier or string literal

все они недовольны вариациями одного и того же расширения макросов:

[build] C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.22.27905\include\vcruntime.h(326,20): error: __declspec attributes must be an identifier or string literal
[build]         __declspec(noreturn) void __cdecl __report_gsfailure(_In_ uintptr_t _StackCookie);
[build]                    ^
[build] C:\PROGRA~1\LLVM\lib\clang\8.0.1\include\stdnoreturn.h(27,18): note: expanded from macro 'noreturn'
[build] #define noreturn _Noreturn

Я пытался передать -fms-extensions и -fms-compatibility в clang-cl и не получил ни одной кости. Насколько я понимаю, clang расстроен тем, что Windows помещает ключевое слово в эту спецификацию declspec? Я мало что знаю о каких-либо расширениях MS.

Использование простого старого _Noreturn отлично работает, поэтому я могу компилировать свой код. Но есть ли у кого-нибудь больше информации о том, что здесь происходит и как исправить? Является ли объединение msvc и clang просто дерьмовым по своей сути или я делаю что-то не так?

РЕДАКТИРОВАТЬ: я идиот.

Проблема в том, что расширение макроса нарушает _declspec(noreturn) внутри заголовков Windows SDK. Решение очевидно:

#include <stdlib.h>
#include <stdnoreturn.h>

Который отлично строится, потому что макрос определяется после заголовка Windows SDK, который использует declspec(noreturn)


person nickelpro    schedule 03.08.2019    source источник
comment
Я буду винить Microsoft, сейчас и навсегда :D   -  person Antti Haapala    schedule 04.08.2019
comment
Вы специально хотите использовать стандартную библиотеку MSVC? Использование Clang с libstdc++, предоставляемым MinGW, является хорошей альтернативой.   -  person HolyBlackCat    schedule 04.08.2019
comment
Я предполагаю, что это ошибка clang, они никогда не думали, что noreturn может быть расширено до _Noreturn в __declspec   -  person Antti Haapala    schedule 04.08.2019
comment
Не могли бы вы уточнить, вызывают ли проблему только два включения в вашем первом фрагменте? В заголовке говорится вместе с заголовками Windows, но вы не показали никаких включений заголовков Windows.   -  person M.M    schedule 05.08.2019
comment
Похоже, нужно подать отчет об ошибке и не использовать stdnoreturn, если только вы не хотите изменить компилятор. FWIW msys2 clang и gcc не имеют проблемы   -  person M.M    schedule 05.08.2019
comment
Ваш код включает: <noreturn.h> или <stdnoreturn.h>   -  person user3629249    schedule 05.08.2019
comment
@AnttiHaapala здесь прав, я бы отметил его правильно, если бы это был ответ. Вероятно, clang <stdnoreturn.h> никогда не тестировался с Windows SDK, только с libc++, если вообще. __declspec поддерживает несколько модификаторов. clang расстроен, потому что препроцессор расширяет noreturn до недопустимого модификатора. Я не знаю, как это можно исправить, MS не поддерживает C11, поэтому они могут использовать noreturn в качестве ключевого слова. clang должен был бы выполнить некоторую магию для поддержки этого конкретного макроса.   -  person nickelpro    schedule 06.08.2019
comment
Ну, я идиот, написав этот комментарий, я натолкнулся на решение   -  person nickelpro    schedule 06.08.2019


Ответы (1)


Я разместил ответ в своем редактировании, но, чтобы закрыть вопрос, я опубликую здесь расширенную версию.

Проблема возникает из-за конфликта между стандартом C11 и специфичными для Windows расширениями C/C++. Windows расширяет классы хранилища, используя синтаксис declspec, который предшествует C11. Он предоставляет класс хранения для функций, которые не возвращаются с __declspec(noreturn).

К сожалению, это противоречит макросу ключевого слова noreturn из C11. Microsoft, скорее всего, не считает это проблемой, так как они не заявляют о какой-либо поддержке C11. Если вы попытаетесь использовать заголовки Windows SDK с определенным макросом, ваш компилятор будет жаловаться на использование ключевого слова в declspec через несколько загадочное сообщение об ошибке, указанное в исходном вопросе (noreturn расширяется до _Noreturn, фактическое ключевое слово, добавленное в C11).

Однако ответ довольно прост: пока ваш код не пытается смешивать __declspec(noreturn) и noreturn, что было бы избыточно, просто включайте заголовок <stdnoreturn.h> после других системных заголовков. Препроцессор не будет расширять noreturn внутри заголовков Windows SDK, и все будет совпадать.

person nickelpro    schedule 05.08.2019
comment
Кроме того, вы можете просто пропустить использование #include <stdnoreturn.h> и просто использовать _Noreturn для код, который поддерживает функции C11, а также должен компилироваться в MSVC. Вам, вероятно, понадобится несколько #ifdef в любом случае. - person Andrew Henle; 08.08.2019