未使用的“static inline”函数会生成带有“clang”的警告

Cya*_*yan 6 c c99 clang

使用gcc或时clang,启用多个警告通常是一个好主意,第一批警告通常由 提供-Wall。该批次相当大,并且包含特定警告-Wunused-function

现在,-Wunused-function可用于检测static不再调用的函数,这意味着它们无用,因此最好从源代码中删除。当实行“零警告”政策时,它不再是“可取的”,而是彻头彻尾的强制性。

出于性能原因,某些函数可能会直接定义到头文件中*.h,以便可以在编译时内联它们(忽略任何类型的 LTO 魔法)。此类函数通常声明和定义为static inlinestatic inline在过去,此类函数可能会被定义为宏,但只要适用,最好将它们改为函数(没有有趣的类型问题)。

好的,出于性能原因,现在我们将一堆函数直接定义到头文件中。包含此类头文件的单元没有义务使用其所有声明的符号。因此,static inline头文件中定义的函数可能不会被调用。

对于gcc,那很好。gcc会标记一个未使用的static函数,但不会标记一个inline static。但clang结果是不同的:如果单个单元不调用static inline标头中声明的函数,则会触发警告。-Wunused-function而且不需要很多标志就可以到达那里:-Wall就足够了。

解决方法是引入特定于编译器的扩展,例如__attribute__((unused)),它向编译器明确声明标头中定义的函数不一定会被其所有单元调用。好的,但是现在,曾经干净的代码C99包含某种形式的特定编译器扩展,增加了可移植性和维护的重量。

因此,问题更多地是关于这种选择的逻辑:为什么当未调用标头中定义的函数clang时 selects 会触发警告?static inline在什么情况下这是一个好主意?

什么clang建议涵盖头文件中定义的内联函数的相对常见情况,而不要求使用编译器扩展?

编辑:经过进一步调查,问题似乎不正确。使用应用选定列表编译标志(等)的 linter在编辑器(VSCode)中触发警告。但是,当实际使用完全相同的标志列表编译源代码时,不会出现“未使用的函数”警告。clang-Wallclang

到目前为止,编辑器中可见的结果与编译时找到的结果完全相同。这是我第一次目睹差异。

因此,问题似乎与 linter 用于clang生成警告列表的方式有关。这是一个更加复杂和具体的问题。


请注意评论

好吧,抱歉,这其实和想象的不一样。看来警告是在编辑器中使用clang带有选定编译标志(-Wall等)的 linter 触发的。但是,当使用完全相同的标志编译源代码时,“未使用的函数”警告实际上不存在。到目前为止,编辑器中可见的结果与编译时找到的结果完全相同;这是我第一次目睹差异。因此,问题似乎与 linter 用于clang生成警告列表的方式有关。这似乎是一个更复杂的问题[比我意识到的]。

R..*_*R.. 1

我不确定你会找到任何“为什么”。我认为这是一个错误,可能是他们不想修复的错误。正如您在问题中暗示的那样,它确实鼓励了非常糟糕的做法(在不需要注释的情况下使用编译器扩展进行注释),并且不应该这样做;相反,应该关闭警告,除非/直到错误得到修复。

如果您还没有这样做,您应该在他们的跟踪器中搜索现有的错误报告,如果不存在则打开一个。

后续:我收到的报告尚未验证这种行为仅发生在直接在源文件中定义的函数,而不是来自包含的头文件。如果这是真的,那么情况远没有那么糟糕,而且您可能可以忽略它。

  • @Cyan:我怀疑编辑器/linter 正在将预处理器作为单独的步骤运行,以获取要传递给 clang 的平面预处理文件,这会触发 clang 现在警告未使用的函数“在源文件中而不是标头中” ”。 (2认同)