【问题标题】:Using #pragma to remove clang warnings based on clang check使用 #pragma 去除基于 clang 检查的 clang 警告
【发布时间】:2021-09-07 23:42:15
【问题描述】:

我想删除/忽略一段代码的 clang 警告,并找到了多个关于如何为此使用 pragamas 的示例。例如,如果警告是 unused-variable,您可以使用以下命令禁用它:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"

int a;

#pragma clang diagnostic pop

但是问题是我在构建存储库时没有在输出中收到警告,我只知道发出警告的是哪个 clang 检查...而且我找不到任何其他问题或文档就是这样。这是我的输出的样子:

warning: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete]

我已经尝试了数百种不同的组合来忽略这一点,但没有任何效果(使用// NOLINT 不是一个可行的选择)。在我尝试过的事情中,有一些:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Winline-new-delete"
#pragma clang diagnostic ignored "-Wmost"
#pragma clang diagnostic ignored "-Weverything"
#pragma clang diagnostic ignored "clang-analyzer-cplusplus.NewDelete"
#pragma clang diagnostic ignored "-Wclang-analyzer-cplusplus.NewDelete"
#pragma clang diagnostic ignored "-clang-analyzer-cplusplus.NewDelete"
#pragma clang diagnostic ignored "-W-NewDelete"
#pragma clang diagnostic ignored "-W-new-delete"

// code

#pragma clang diagnostic pop

注意,“修复”代码也不是一种选择,因为它是第三方代码。

【问题讨论】:

  • 附带说明,这是一个危险的警告,即使对于单个变量也要禁用,您确定吗?
  • @Afshin 确定它......但这不是我的代码,我无意更改它......我也从来没有遇到过问题,并且查看源代码似乎无论如何,警告永远不会发生。我是 clang 的新手,但关于实际可能发生的事件似乎并不总是完全合乎逻辑的。
  • 你的构建系统是什么?CMake?
  • @Afshin 我正在使用 CMake 和 Ninja

标签: c++ clang clang++ clang-static-analyzer clang-tidy


【解决方案1】:

如 cmets 中所述,#pragma clang diagnostic 方法只能用于抑制 编译器 警告。您提到的警告来自 clang-static-analyzer,它现在是 clang-tidy 的一部分。

通过代码禁用特定clang-tidy检查的唯一两个选项是//NOLINT//NOLINTNEXTLINE 宏。

正如您提到的,有问题的代码是第三方的,我假设您根本对分析它不感兴趣。由于您使用的是 CMake,因此可以通过 .clang-tidy 文件轻松完成。您可以在项目的根目录中放置一个.clang-tidy 文件,并在那里列出/配置所需的检查,如下所示:

Checks: '-*,cppcoreguidelines-*'

(这将启用所有 Cpp 核心指南检查)。

然后在放置第三方代码的目录中,您可以通过放置在该目录中的.clang-tidy 文件禁用clang-tidy 分析。由于.clang-tidy 文件不能为空或不指定任何检查,您可以通过“错误配置”这样的检查来做到这一点:

Checks: '-*,misc-definitions-in-headers'
CheckOptions:
  - { key: HeaderFileExtensions,          value: "x" }

有关此方法的更多详细信息,请参阅this answer

您也可以使用第三方目录中的.clang-tidy 文件仅禁用某些检查。

【讨论】:

    【解决方案2】:

    我想到的最佳方法在某种程度上取决于您的构建系统。假设您有这样的示例代码:

    主文件:

    int main()
    {
        // ...
        int *a = new int;
        *a = 10;
        delete a;
    
        if (::rand() < 10) {
            std::cout  << *a; //<-- clang tidy warning here
        }
        //...
    }
    

    这会在上述行中创建 clang tidy 警告。现在你能做什么?将您的代码分成 2 个文件:

    文件 A:

    void foo() {
        int *a = new int;
        *a = 10;
        delete a;
    
        if (::rand() < 10) {
            std::cout  << *a; //<-- clang tidy warning here
        }
    }
    

    主文件:

    int main()
    {
        // ...
        foo();
        //...
    }
    

    现在为 文件 A 禁用 cland-tidy。这是一个示例,但我想您了解我的总体想法。您不能禁用 clang-tidy,因为它在另一个库中,并且由于多种原因您不能触摸该代码。 //NOLINT 也不适用于功能。因此,只需在单个文件中创建一个包装器以使用该库并在该包装器文件中为整个文件禁用 clang-tidy

    【讨论】:

    • 那么有没有办法使用#pragma 方法来删​​除我得到的警告类型?我非常希望不改变大部分结构,#pragma 似乎是完美的解决方案,但我不明白何时使用它,因为我从未收到任何警告,如 #pragma 示例中所示.....
    • @JakobVinkas 我认为你误解了一些东西。您收到的警告来自clang-tidy,而不是clang(在启用clang-tidy 之前我没有收到您的警告)。另一方面,#pragma clang diagnostic 禁用clang 的警告,而不是clang-tidy。禁用clang-tidy 警告的唯一方法是//NOLINT cmets,因此您不能使用#pragma
    • 那么当警告来自对第三方代码库的函数调用时,代码重构和文件忽略是唯一可行的吗?
    • @JakobVinkas 这是我想到的唯一方法。更具体地说,我自己没有测试过,但理论上它应该可以工作。在应用于整个项目之前,您可以在一个小示例(例如我的第一个)上对其进行测试。另一种方法是为整个项目或使用库的文件禁用 clang-tidy。但是如果你这样做,你可能会错过其他整洁的警告。但如果它现在已经启用,你可能想要它:D
    • 如何从检查中只禁用一个文件?正如你所知道的,我是 clang-tidy 的新手;)我有一个带有 set(CLANG_TIDY_ARGS --checks=clang-analyzer-cplusplus.*) 的 cmake 文件,但它是一个相当大的项目,我找不到在哪里选择应该检查哪些文件......
    【解决方案3】:

    根据this,对于 Clang 静态分析器,您必须使用:

    #ifndef __clang_analyzer__
    // code
    #endif
    

    【讨论】:

    • 这似乎完全“删除”了代码,我现在从其他检查([clang-analyzer-deadcode.DeadStores])中得到警告,声称代码块上方的代码现在有未使用的变量.这是应该做的还是我执行错了?
    猜你喜欢
    • 1970-01-01
    • 2022-09-30
    • 2018-07-16
    • 2011-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-10
    • 2015-04-24
    相关资源
    最近更新 更多