3

我正在尝试在 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 结合起来是天生的 janky 还是我做错了什么?

编辑:我是个白痴。

问题是宏扩展_declspec(noreturn)在 Windows SDK 标头内部中断。解决方案很明显:

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

哪个构建得很好,因为宏是在使用的 Windows SDK 标头之后定义的declspec(noreturn)

4

1 回答 1

2

我已经在我的编辑中发布了答案,但为了结束这个问题,我将在这里发布一个扩展版本。

问题来自 C11 标准和特定于 Windows 的 C/C++ 扩展之间的冲突。Windows 使用C11 之前的declspec 语法扩展存储类。它为不返回的函数提供了一个存储类__declspec(noreturn)

noreturn不幸的是,这与C11中的关键字宏冲突。微软可能不认为这是一个问题,因为他们没有声称对 C11 有任何支持。noreturn如果您尝试使用定义了宏的 Windows SDK 标头,您的编译器将通过原始问题中列出的有点神秘的错误消息(扩展为_NoreturnC11 中添加的实际关键字)抱怨在 declspec 中使用关键字。

答案很简单:只要您的代码不尝试混合__declspec(noreturn)and noreturn,这将是多余的,只需<stdnoreturn.h>在其他系统标头之后包含标头即可。预处理器不会noreturn在 Windows SDK 标头中扩展,并且一切都将是无用的。

于 2019-08-05T22:47:59.983 回答