Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

-Wshadow=global considers enum class entry shadowing a global. Why?

When compiling with -Wshadow=global on GCC 7.3 and 8.2, the compiler warns that the following code snippet shadows.

constexpr int A = 0;

class Bar {
public:
    enum Bars {
        A = 0
    };
};

enum class Foo {
    A = 0     // warns this entry shadows global declaration of A
};

int main() {
    return 0;
}

<source>:11:9: warning: declaration of 'A' shadows a global declaration [-Wshadow]
     A = 0
         ^
<source>:1:15: note: shadowed declaration is here
 constexpr int A = 0;
               ^

Because enum classes require the enum class name when referenced, my understanding is that all three declarations of A are separate: ::A, ::Bar::A, and ::Foo::A.

Clang 7 doesn't emit a warning with -Wshadow.

Is this a valid shadow warning, and if so, why?

like image 896
Stewart Smith Avatar asked Dec 18 '18 21:12

Stewart Smith


2 Answers

There has been a bug that has been already filed about this issue titled "-Wshadow generates an incorrect warning with enum classes" . However, it is not confirmed that this is a bug.

Jonathan Wakely argues that this is not a bug and gives the following example.

typedef unsigned char foo;
enum class myenum
{
  foo,
  bar = (foo)-1
};

Is the value -1L or 255?

If I rename myenum::foo to myenum::Foo the code silently changes meaning.

It also changes meaning if I reorder the declarations of myenum::foo and myenum::bar, which is exactly the sort of fragile code that deserves a warning.

This is true for the example posted in the question as well. If the global int A is declared after the enum class Foo, there is no longer a warning.

Another user agrees on that thread:

In an ideal world we would only warn when ambiguity exists (in the user mind), that is, at "bar = (foo) -1". However, that is probably much more difficult and expensive than the current warning.

like image 167
P.W Avatar answered Nov 15 '22 01:11

P.W


I guess you can consider a silly scenario,

enum class Foo {
    A = 0,    // warns this entry shadows global declaration of A
    B = A
};

So the reference to A in the definition of B can be from global A and local A.

like image 38
CS Pei Avatar answered Nov 14 '22 23:11

CS Pei