This is an archive of the discontinued LLVM Phabricator instance.

Fix -Wshadow false positives with function-local classes.
ClosedPublic

Authored by alexfh on Jul 27 2017, 6:43 AM.

Details

Summary

Fixes http://llvm.org/PR33947.

https://godbolt.org/g/54XRMT

void f(int a) {

struct A {
  void g(int a) {}
  A() { int a; }
};

}

3 : <source>:3:16: warning: declaration shadows a local variable [-Wshadow]

void g(int a) {}
           ^

1 : <source>:1:12: note: previous declaration is here
void f(int a) {

^

4 : <source>:4:15: warning: declaration shadows a local variable [-Wshadow]

A() { int a; }
          ^

1 : <source>:1:12: note: previous declaration is here
void f(int a) {

^

2 warnings generated.

The local variable a of the function f can't be accessed from a method of
the function-local class A, thus no shadowing occurs and no diagnostic is
needed.

Diff Detail

Repository
rL LLVM

Event Timeline

alexfh created this revision.Jul 27 2017, 6:43 AM
rnk edited edge metadata.Jul 27 2017, 11:03 AM

I'm not really sure this is a bug. The point of -Wshadow is to warn on valid but possibly confusing code. Shadowing a variable is perfectly legal, but people think it's confusing, so we implemented this warning. Are we concerned that people might get confused between the different local variables here?

In D35941#823020, @rnk wrote:

I'm not really sure this is a bug. The point of -Wshadow is to warn on valid but possibly confusing code. Shadowing a variable is perfectly legal, but people think it's confusing, so we implemented this warning. Are we concerned that people might get confused between the different local variables here?

IIUC, most cases where -Wshadow warnings are issued is when a declaration from an enclosing scope would be accessible if there was no declaration that shadows it. In this case the the local variable of a function would not be accessible inside the local class anyway, so the inner variable with the same name is not confusing (at least, much less confusing than if it would prevent access to the variable of an outer scope). This is close to shadowing of uncaptured locals in lambdas, but it seems to have even less potential for being misleading. We had a few of requests internally to mute -Wshadow for this case. Another data point is that GCC doesn't warn in this case.

But if I'm overseeing reasons to issue a warning in this case, we could add an analogue of -Wshadow-uncaptured-local for this case. WDYT?

rnk accepted this revision.Jul 28 2017, 8:52 AM

Another data point is that GCC doesn't warn in this case.

That seems like a reasonable tie breaker when implementing these kinds of style-enforcement warnings. :)

This revision is now accepted and ready to land.Jul 28 2017, 8:52 AM
Quuxplusone accepted this revision.Jul 28 2017, 9:55 AM
Quuxplusone added a subscriber: Quuxplusone.

But if I'm overseeing reasons to issue a warning in this case, we could add an analogue of -Wshadow-uncaptured-local for this case. WDYT?

I still think "any warning" is a marginally better UX than "no warning" on the particular code in question; but of course I defer to Reid/Richard/GCC on the practicalities. Adding a new warning option might not be worth the trouble. :)

This revision was automatically updated to reflect the committed changes.
rsmith edited edge metadata.Aug 10 2017, 4:52 PM

IIUC, most cases where -Wshadow warnings are issued is when a declaration from an enclosing scope would be accessible if there was no declaration that shadows it. In this case the the local variable of a function would not be accessible inside the local class anyway

That's not strictly true; the variable can be accessed in unevaluated operands, and in code doing so, a -Wshadow warning might (theoretically) be useful:

void f(SomeComplexType val) {
  struct A {
    decltype(val) &ref;
    void g(int val) {
      decltype(val) *p = &ref;
    }
  } a = {val};
}

That said, suppressing the warning seems like a good thing in the common case. We've discussed the idea of deferring some -Wshadow warnings until we see a use; if someone cares about this case, we could consider warning only if the shadowed variable is actually used in an unevaluated operand.

IIUC, most cases where -Wshadow warnings are issued is when a declaration from an enclosing scope would be accessible if there was no declaration that shadows it. In this case the the local variable of a function would not be accessible inside the local class anyway

That's not strictly true; the variable can be accessed in unevaluated operands, and in code doing so, a -Wshadow warning might (theoretically) be useful:

void f(SomeComplexType val) {
  struct A {
    decltype(val) &ref;
    void g(int val) {
      decltype(val) *p = &ref;
    }
  } a = {val};
}

Good to know!

That said, suppressing the warning seems like a good thing in the common case. We've discussed the idea of deferring some -Wshadow warnings until we see a use; if someone cares about this case, we could consider warning only if the shadowed variable is actually used in an unevaluated operand.

Sounds reasonable.