GCC -Wshadow遗漏了一些案例?

时间:2014-02-27 17:41:19

标签: c++ gcc

我看到另一篇关于GCC -Wshadow过于严格的帖子。我的问题恰恰相反。

我重新访问了一些我写过的代码,并注意到-Wshadow无法正常工作:

void free(double* x) {
    free(x);
}

或者:

#include <string.h>
// other code here
int memset = 0;

使用-Wshadow编译时都没有警告。我相信通常的方法是:

::free(x) // for 1st example
::log(x) // when in doubt if it's my function or the log from math.h

但是,理想情况下我想让-Wshadow抓住这些。我不认为我正确理解GCC或c ++。有人可以解释为什么它这样工作,应该吗?谢谢。

我用以下代码编译了所有代码:

GCC-4.8.2 -static-libstdc++ -std=c++11 -pedantic -Werror -Wall -Wextra -Wshadow -Wold-style-cast

编辑回复下面的评论关于重载:我也可以编译

void free(void* x) {
    // blah
}

现在看起来不像重载,匹配C库的精确签名。但我认为在这种情况下编译器需要警告(-Wshadow)。关于memset:我实际上并没有像memset那样编写明显的代码,但我将它作为一个例子。

Edit2 示例链接:https://groups.google.com/forum/#!topic/android-ndk/8v2M1i1-Dls 在这个链接的帖子中,你不能用-Wshadow声明像“abs”这样的符号。然而,我可以声明像“memset”,“free”等符号.GCC网站说-Wshadow应该在内置插件被遮蔽时发出警告。

1 个答案:

答案 0 :(得分:3)

阴影警告针对以下情况:1)名称隐藏发生,即一个名称被稍后声明的另一个名称或更局部范围隐藏,2)代码仍然是格式良好的。

如果你的free,如果声明是在全局命名空间中进行的,那么你有重载,而不是阴影。 (我不能马上说这种“扩展”标准库的尝试是否合法。)如果你的memset,如果声明是在全局命名空间中进行的,那么声明就是非法的,即代码无效。

至于实际发生真正名称隐藏的上下文...你看,-Wshadow旨在成为警告 - 旨在捕捉正式隐藏的潜在危险名称< em>完全合法的代码。正如警告一样,为了避免让它过于热心和烦恼,开发人员必须以某种方式将所有名称隐藏情况分成那些看起来非常可疑的情况和那些可能是故意的。对于这个特定的警告,我会说当隐藏在类似性质的实体之间发生警告是有意义的:一个类型隐藏另一个类型,一个函数隐藏另一个函数,一个变量隐藏另一个变量。当相同性质的实体相互隐藏时,存在很大的错误可能性:用户可能会使用一个实体,而相信他们使用另一个实体,并且代码仍然会安静地编译。但是当不同性质的实体彼此隐藏时,警告的需要大大减少,因为不同性质的实体具有完全不同的使用上下文/模式/语法。例如,变量使用语法通常与函数使用语法不同(当然,如果我们考虑函数对象,这仍然不完全准确,但仍然很大程度上是正确的)。任何意外误用都可能被编译器捕获为错误。出于这个原因,当一个变量隐藏一个函数或一个函数隐藏一个类型时,发出一个阴影警告可能是一个好主意 not 。当本地-Wshadow 变量隐藏全局memset 功能时,这可能是memset未收到警告的原因。如果您不小心错过或忘记了本地int memset;声明并继续使用memset,就好像它是一个函数(memset(dst, src, n)),代码将无法编译。这里不需要任何额外的警告,因为无论如何你的错误肯定会被抓住并报告。

更新:在free声明为void free(void *)的其他情况下,即完全匹配标准函数签名,您正在处理gcc“features”之一。您实际上是在提供自己的标准库函数定义,替换“标准”定义。特别是为了给你机会,GCC库实现中的所有标准库函数都被声明为所谓的弱符号。在某些情况下这是一个有用的功能(作为调试辅助工具等),但我们必须付出的代价是意外替换标准功能。

-Wshadow是否应该警告这是一个不同的问题......再次引入-Wshadow来警告危险的名字隐藏。在这种情况下,没有名称隐藏,并且正式地,代码是非法的。但GCC允许它用于上述目的。