c - 未使用的“静态内联”函数使用“clang”生成警告
问题描述
使用gcc
orclang
时,通常最好启用多个警告,第一批警告通常由-Wall
. 这批非常大,并且包括特定的警告-Wunused-function
。
现在,-Wunused-function
对于检测static
不再调用的函数很有用,这意味着它们是无用的,因此最好从源代码中删除。当应用“零警告”政策时,它不再是“可取的”,而是完全强制性的。
出于性能原因,一些函数可以直接定义到头文件*.h
中,以便它们可以在编译时内联(忽略任何类型的 LTO 魔法)。此类函数通常被声明和定义为static inline
. 在过去,这些函数可能会被定义为宏,但static inline
在适用的情况下,最好将它们设为函数(没有有趣的类型问题)。
好的,现在我们有一堆函数直接定义到头文件中,出于性能原因。包含此类头文件的单元没有义务使用其所有声明的符号。因此,static inline
可能合理地不调用头文件中定义的函数。
对于gcc
,那很好。gcc
将标记一个未使用的static
函数,但不是inline static
一个。clang
但是,结果是不同的:如果单个单元不调用它们,则在static inline
标头中声明的函数会触发警告。-Wunused-function
到达那里不需要很多标志:-Wall
就足够了。
一种解决方法是引入一个特定于编译器的扩展,例如__attribute__((unused))
,它向编译器明确声明头文件中定义的函数不一定会被其所有单元调用。好的,但是现在,过去很干净的代码C99
包含某种形式的特定编译器扩展,增加了可移植性和维护的重量。
因此,问题更多的是关于这种选择的逻辑:为什么选择在未调用标题中定义clang
的函数时触发警告?static inline
在哪种情况下这是个好主意?
什么clang
建议涵盖头文件中定义的内联函数的相对常见情况,而不要求使用编译器扩展?
编辑:经过进一步调查,问题似乎不正确。使用 linter应用选定的列表编译标志(等)在编辑器(VSCode)中触发警告。但是,当源代码实际上是用完全相同的标志列表编译时,“未使用函数”警告不存在。clang
-Wall
clang
到目前为止,在编辑器中可见的结果与编译时的结果完全相同。这是我第一次看到不同之处。
所以这个问题似乎与 linter 用来clang
生成警告列表的方式有关。这是一个更加复杂和具体的问题。
注意评论:
好的,对不起,这实际上与预期不同。看来警告是在编辑器中使用
clang
带有选定编译标志(-Wall
等)的 linter 触发的。但是当使用完全相同的标志编译源代码时,实际上不存在“未使用函数”警告。到目前为止,编辑器中可见的结果与编译时的结果完全相同;这是我第一次看到不同之处。所以这个问题似乎与 linter 用来clang
生成警告列表的方式有关。这似乎是一个比我意识到的更复杂的问题。
解决方案
我不确定你会找到任何“为什么”。我认为这是一个错误,可能是他们不想修复的错误。正如您在问题中暗示的那样,它确实鼓励了非常糟糕的做法(在不需要注释的情况下使用编译器扩展进行注释),并且不应该这样做;相反,除非/直到修复错误,否则应该关闭警告。
如果您还没有,您应该在他们的跟踪器中搜索现有的错误报告,如果不存在则打开一个。
跟进:我收到的报告尚未证实这种行为仅发生在源文件中直接定义的函数上,而不是来自包含的头文件。如果这是真的,它远没有那么糟糕,而且可能是你可以忽略的。
推荐阅读
- python - 使用 String.split() 设计 Python
- string - strcpy() 函数的第二个参数中没有空字符会返回意外结果。为什么?
- python - 如何制作一个字典/ collections.counter 考虑到 Python 中的索引?
- database - 如何从搜索查询中搜索子项?
- spring - Spring WebFlux 安全自定义 AccessDeniedHandler
- codesys - Codesys CAA_File 和 SysFile 库的区别
- linux - 我可以使用命令行或 perl 更改我的终端位置吗?
- wso2 - WSO2 EI (ESB) 与 WSO2 IS 通信
- java - 在 Java 中识别两个随机序列
- java - 在Android错误中通过长按从列表视图中删除项目