如何解决clang-tidy:如何抑制 C 头文件中的 C++ 警告?
我有一个包含在 C 和 C++ 源文件中的 .h 文件。它的内容被包裹在
#ifdef __cplusplus
extern "C" {
#endif
...
#ifdef __cplusplus
}
#endif
然而,当我将它包含在 .cpp 文件中时,clang-tidy 会发出 C++ 特定的消息,例如
- 警告:包括'stdbool.h'在C++中没有作用;考虑删除它 [hicpp-deprecated-headers,modernize-deprecated-headers]
- 警告:包含已弃用的 C++ 头文件“stdlib.h”;考虑使用“cstdlib”代替 [hicpp-deprecated-headers,modernize-deprecated-headers]
- 警告:使用 'using' 而不是 'typedef' [modernize-use-using]
我喜欢这些检查并且我想让它们在我的叮当整洁的配置中保持活动状态,但当然仅适用于 C++ 代码。我无法将头文件更改为使用 using
而不是 typedef
或 <cstdlib>
而不是 <stdlib.h>
因为它也包含在 C 源中,因此 extern "C"
.
有没有办法告诉 clang-tidy 将 extern "C"
中的代码视为 C 而不是 C++,即使包含在 .cpp 文件中?
clang-tidy 版本是 12.0.0。
解决方法
Clang-Tidy 可以使用特殊的 NOLINT
或 NOLINTNEXTLINE
注释来抑制特定行的警告。它完全适用于您的用例:
- 某些行包含遗留或不是非常好的 C++ 代码
- 这样做是有充分理由的 - 此处代码必须可由 C 编译器解析。
使用它的更高风险是滥用它并在可以改进编码的地方静音警告。但是,当您需要从 C 和 C++ 源代码中使用标头时,并且您仔细阅读了 NOLINTed 行两次,这完全没问题,至少恕我直言。此外,甚至可以指示静音警告:
#ifdef __cplusplus
extern "C" {
#endif
// NOLINTNEXTLINE(hicpp-deprecated-headers,modernize-deprecated-headers) C compatible code
#include <stdbool.h>
#include <stdlib.h> // NOLINT C code requires that header
...
#ifdef __cplusplus
}
#endif
,
那些 C 和 C++ 头文件严格来说并不等同于 C++。这些警告是合法的,表示代码不符合 C++ 标准。
extern "C"
仅将声明的函数和变量的链接类型声明为全局且不进行修改,名称以 C 格式使用。它不能影响使用 C++ 功能声明的对象和函数。它与语言的生态系统无关。更重要的是,如果 C++ 标头出现在这些括号内,那么如果在那里声明的函数最初是在 C++ 链接中声明的,则可能会出现链接错误。
对于 C++,你必须使用 #ifdef __cplusplus
来包含 C++ 的替代品,否则包括 C 的替代品。
代替:
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdlib.h>
// your declarations
#ifdef __cplusplus
}
#endif
您将有一个具有以下结构的标题
// headers that are universally compatible (3rd party)
#ifdef __cplusplus
# include <cstdlib>
// other C++ headers
// Your C++ - only declarations (incompatible with C rules)
extern "C" {
#else
# include <stdbool.h>
# include <stdlib.h>
// other C headers
// C-only declarations (incompatible with C++ rules)
#endif
// your compatible declarations available for both
#ifdef __cplusplus
} // extern "C"
#endif
在某些情况下,由于标头包含或声明的依赖性所需的顺序,需要调整此结构。盲目更改库标头中未编写的声明链接,并且无法保证这些使用的命名约定和链接类型是失职,可能导致 ODR 违规或链接失败。
typedef 问题很烦人,您可以使用 NOLINT 或命令行 option 来抑制 modernize-use-using
作为临时措施。一般来说,对于可移植的头文件,至少对于结构类型,这将通过宏定义来完成。在某些情况下,typedef 和别名声明无法通过标准方式进行转换,例如考虑函数指针类型的声明。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。