This is an archive of the discontinued LLVM Phabricator instance.

[clang] Diagnose shadowing of lambda's template parameter by a capture
ClosedPublic

Authored by Fznamznon on Apr 19 2023, 6:29 AM.

Details

Summary

expr.prim.lambda.capture p5 says:
If an identifier in a capture appears as the declarator-id of a parameter of
the lambda-declarator's parameter-declaration-clause or as the name of a
template parameter of the lambda-expression's template-parameter-list,
the program is ill-formed.
and also has the following example:

auto h = [y = 0]<typename y>(y) { return 0; };

which now results in

error: declaration of 'y' shadows template parameter
  auto l1 = [y = 0]<typename y>(y) { return 0; };
             ^
note: template parameter is declared here
  auto l1 = [y = 0]<typename y>(y) { return 0; };
                             ^

Fixes https://github.com/llvm/llvm-project/issues/61105

Diff Detail

Event Timeline

Fznamznon created this revision.Apr 19 2023, 6:29 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 19 2023, 6:29 AM
Fznamznon requested review of this revision.Apr 19 2023, 6:29 AM
Herald added a project: Restricted Project. · View Herald TranscriptApr 19 2023, 6:29 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript
shafik added inline comments.Apr 19 2023, 11:37 AM
clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

I don't know if shadowing is the correct term to use here. The wording simply says they can't have the same name. I think the diagnostic should say something similar.

Fznamznon added inline comments.Apr 19 2023, 11:53 AM
clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

Well, the example with capture and a parameter uses shadowing term, so I just followed the same approach.

If we say something like "explicitly captured entity and template parameter can't have the same name", does it make sense to emit a note "captured here" for the capture with conflicting name?

erichkeane added inline comments.Apr 19 2023, 11:55 AM
clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

I think the 'shadows' is an appropriate as it matches what we do in normal template cases:

template<typename T>
int foo(int T) {
    int T = 5;
}

<source>:3:13: error: declaration of 'T' shadows template parameter
int foo(int T) {
            ^
<source>:2:19: note: template parameter is declared here
template<typename T>
                  ^
<source>:4:9: error: redefinition of 'T'
    int T = 5;
        ^
<source>:3:13: note: previous definition is here
int foo(int T) {
shafik added inline comments.Apr 19 2023, 12:55 PM
clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

So shadowing is synonymous w/ name hiding which is not really the case here. I will concede it is consistent with how we are using elsewhere but this PR is probably not the place to change it. So I will drop the objection and probably file a bug report.

cor3ntin added inline comments.Apr 19 2023, 1:08 PM
clang/lib/Sema/SemaLambda.cpp
1368
clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

Well, if it was allowed, it would shadow and it's not allowed.
I think the message is clear for user - maybe we could ad "which is not allowed" or something, so that it isn't confused with a shadow warning.

shafik added inline comments.Apr 19 2023, 1:48 PM
clang/lib/Sema/SemaLambda.cpp
1381

It is really a shame that this is just different enough that we can't turn CheckRedefinition into a generic lambda and reuse it here. The code duplication is very unfortunate.

clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
8

Also note the example you gave Erich the ordering is different, the template parameter comes before the function parameter but here it is vice versa, so it feels kind of awkward to say it is shadowing a name that comes after it.

clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
160

Can we also get a test that verifies this is ok []<typename y>(y) { return 0; } and we obtain no diagnostic.

Fznamznon updated this revision to Diff 515256.Apr 20 2023, 2:12 AM

Rebase, mention C++23, add a test case

Fznamznon marked 2 inline comments as done.Apr 20 2023, 2:12 AM
Fznamznon added inline comments.
clang/lib/Sema/SemaLambda.cpp
1381

What I could do here is modify err_parameter_shadow_capture message so it says either a lambda parameter cannot shadow an explicitly captured entity or a lambda template parameter cannot shadow an explicitly captured entity and make CheckRedefinition accept a NamedDecl and a flag whether we're diagnosing a template parameter. Then CheckRedefinition can be reused, resolving the concerns about code duplication and the fact that explicit capture comes before the template parameter. That would probably be inconsistent with how the templates are diagnosed now though. WDYT?

Fznamznon updated this revision to Diff 515257.Apr 20 2023, 2:14 AM

Modify comment

cor3ntin accepted this revision.Apr 24 2023, 6:28 AM

Thanks, this looks good to me now!

This revision is now accepted and ready to land.Apr 24 2023, 6:28 AM
shafik accepted this revision.Apr 26 2023, 9:23 AM

LGTM

Fznamznon updated this revision to Diff 517502.Apr 27 2023, 3:03 AM

Rebase to double check that pre-commit fail is unrelated, add a release note