为啥 C++ 已弃用的警告会打印两次?

Posted

技术标签:

【中文标题】为啥 C++ 已弃用的警告会打印两次?【英文标题】:Why do C++ deprecated warnings print twice?为什么 C++ 已弃用的警告会打印两次? 【发布时间】:2019-04-21 15:12:23 【问题描述】:

如果我有

namespace foo 
    inline int bar() 
        return 1119;
    


__attribute__((deprecated)) inline int bar() 
    return 138;

header.h

#include "header.h"
#include <iostream>

int main() 
    int x = bar();
    int y = foo::bar();
    std::cout << x << std::endl;
    std::cout << y << std::endl;

source.cpp,然后

g++ source.cpp -o deprecated-test

结果

source.cpp: In function ‘int main()’:
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
     int x = bar();
                 ^
In file included from source.cpp:1:
header.h:7:40: note: declared here
 __attribute__((deprecated)) int bar() 
                                 ^~~
source.cpp:5:17: warning: ‘int bar()’ is deprecated [-Wdeprecated-declarations]
     int x = bar();
                 ^
In file included from source.cpp:1:
header.h:7:40: note: declared here
 __attribute__((deprecated)) int bar() 

(在带有 g++ 8.2.0 的 Ubuntu 18.10 上)。

为什么不推荐使用的警告会打印两次?

排除一些无用的建议:

[[deprecated]]: 我知道在 C++14 上你可以使用 [[deprecated]] 属性,但我需要使用 C++11。

声明与定义:The docs 似乎暗示它应该与函数声明而不是定义一起使用,但是

    我需要在头文件中定义函数inline,而不是在头文件中声明并在源文件中定义;和 尝试这种方法并没有阻止警告打印两次。

【问题讨论】:

可能是一个错误。 Clang 不会打印两个警告。 [[deprecated]] 产生相同的结果(gcc 中的两个警告,clang 中的一个)。 @tkausl 谢谢,很高兴知道!看到 clang 不会两次打印警告,我可能还需要尝试其他 g++ 版本,看看它是否是最近引入和/或最近修复的错误 gcc 版本高达 5.5 甚至打印 三个 警告...有趣。 godbolt.org/z/383Hl0 @tkausl 哇...另外,感谢您将我指向 godbolt.org 资源。我以前见过它,但忘记了它,没想到去那里尝试其他编译器 @tkausl 看起来只有 gcc 5.x 打印 3 个警告。 gcc 7.x 打印一个警告,所有其他(我检查过的)打印两个警告。获取已弃用函数的地址会在 gcc 5.x 中打印两个警告,对所有其他版本打印一个警告。 【参考方案1】:

根据 GCC 8.2.0 的文档:

不推荐使用的属性会导致警告如果该函数在任何地方使用 在源文件中。这在识别预期功能时很有用 将在程序的未来版本中删除。该警告还包括 弃用函数的声明位置,使用户能够轻松地 查找有关为什么不推荐使用该功能或​​它们是什么的更多信息 应该这样做。请注意,警告仅针对用途...

应该只有一个警告而不是两个。所以这是 GCC 中的一个错误。

Type 属性(而不是 Function 属性)有一个相关的 bug,标题为:C/C++ __attribute__((deprecated)) does not appear to wrap declarations as implied from the doc.

已确认为错误。

【讨论】:

这肯定是 GCC 中的一个错误,而不是您(以及从 cmets 到帖子的其他人)提到的我的代码的问题。您提到的相关错误很有趣,因为它们不会从一种用法中获得多个警告,而是对 not 使用的声明发出警告。看来我需要提交单独的错误报告。谢谢!

以上是关于为啥 C++ 已弃用的警告会打印两次?的主要内容,如果未能解决你的问题,请参考以下文章

在 Symfony 2(.7) 中禁用已弃用的警告

如何在 Flex 3 中禁用已弃用的警告?

Apple 警告 ITMS-90809:收到已弃用的 API 使用情况

ConnectivityManager.TYPE_WIFI 在代码中显示已弃用。我在 M 以上版本中使用了网络功能,想要删除已弃用的警告

winsock 已弃用,没有警告

ITMS-90809:使用 react-native-html-to-pdf 时已弃用 API 使用警告