【问题标题】:declspec error when compiling clang's <noreturn.h> along with Windows headers编译 clang 的 <noreturn.h> 以及 Windows 头文件时出现 declspec 错误
【发布时间】:2019-08-03 11:19:09
【问题描述】:

我正在尝试在 Windows 上构建我的项目,这对我来说是第一次。我是该平台的初学者。我正在使用 clang-cl 来支持 C11。源最初使用&lt;stdnoreturn.h&gt; 中的noreturn 来注释永远不会返回的函数。我在编译时遇到了一大堆 declspec 错误,并尽可能将其缩小到一个微不足道的文件。

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

无论是自己构建都很好,但他们在一起 produce a laundry list of errors,都是完全相同的类型:

__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 还是我做错了什么?

编辑:我是个白痴。

问题在于宏扩展破坏了 Windows SDK 标头内的_declspec(noreturn)。解决办法很明显:

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

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

【问题讨论】:

  • 我会责怪微软,现在和永远:D
  • 您是否特别想使用 MSVC 标准库进行构建?将 Clang 与 MinGW 提供的 libstdc++ 一起使用是一个不错的选择。
  • 我猜这是一个clang错误,他们从未考虑过noreturn可以扩展到__declspec中的_Noreturn
  • 您能否澄清一下是否只有这两个包含在您的第一个 sn-p 中会导致问题?标题说“与 Windows 标头一起”,但您没有显示任何包含 Windows 标头的内容。
  • 看起来要做的事情是提交错误报告并且不要使用stdnoreturn,除非您想更改编译器。 FWIW msys2 clang 和 gcc 都没有问题

标签: c windows clang c11 clang-cl


【解决方案1】:

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

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

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

答案很简单:只要您的代码不尝试混合使用__declspec(noreturn)noreturn,这将是多余的,只需在其他系统标头之后包含&lt;stdnoreturn.h&gt; 标头即可。预处理器不会在 Windows SDK 标头内扩展 noreturn,所有内容都将是 copacci。

【讨论】:

猜你喜欢
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 2013-05-15
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多