Skip to content

Commit 0fb84bc

Browse files
committed
[clang] Diagnose shadowing of lambda's template parameter by a capture
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 #61105 Reviewed By: shafik, cor3ntin Differential Revision: https://reviews.llvm.org/D148712
1 parent cf59f64 commit 0fb84bc

File tree

4 files changed

+52
-0
lines changed

4 files changed

+52
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,8 @@ Improvements to Clang's diagnostics
233233
- ``-Wformat`` now recognizes ``%lb`` for the ``printf``/``scanf`` family of
234234
functions.
235235
(`#62247: <https://github.com/llvm/llvm-project/issues/62247>`_).
236+
- Clang now diagnoses shadowing of lambda's template parameter by a capture.
237+
(`#61105: <https://github.com/llvm/llvm-project/issues/61105>`_).
236238

237239
Bug Fixes in This Version
238240
-------------------------

clang/lib/Sema/SemaLambda.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,6 +1365,26 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
13651365
PushOnScopeChains(P, CurScope);
13661366
}
13671367

1368+
// C++23 [expr.prim.lambda.capture]p5:
1369+
// If an identifier in a capture appears as the declarator-id of a parameter
1370+
// of the lambda-declarator's parameter-declaration-clause or as the name of a
1371+
// template parameter of the lambda-expression's template-parameter-list, the
1372+
// program is ill-formed.
1373+
TemplateParameterList *TemplateParams =
1374+
getGenericLambdaTemplateParameterList(LSI, *this);
1375+
if (TemplateParams) {
1376+
for (const auto *TP : TemplateParams->asArray()) {
1377+
if (!TP->getIdentifier())
1378+
continue;
1379+
for (const auto &Capture : Intro.Captures) {
1380+
if (Capture.Id == TP->getIdentifier()) {
1381+
Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id;
1382+
Diag(TP->getLocation(), diag::note_template_param_here);
1383+
}
1384+
}
1385+
}
1386+
}
1387+
13681388
// C++20: dcl.decl.general p4:
13691389
// The optional requires-clause ([temp.pre]) in an init-declarator or
13701390
// member-declarator shall be present only if the declarator declares a
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
3+
void f() {
4+
int x = 0;
5+
auto g = [x](int x) { return 0; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} \
6+
// expected-note {{variable 'x' is explicitly captured here}}
7+
auto h = [y = 0]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
8+
// expected-note {{template parameter is declared here}}
9+
10+
}

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
33
// RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
44
// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
5+
// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s
56

67
void foo(int param) { // expected-note 1+ {{previous declaration is here}}
78
int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -146,3 +147,22 @@ void avoidWarningWhenRedefining() {
146147
int b = 0; // expected-error {{redefinition of 'b'}}
147148
};
148149
}
150+
151+
namespace GH61105 {
152+
void f() {
153+
int y = 0;
154+
int x = 0;
155+
#if __cplusplus >= 202002L
156+
auto l1 = [y]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
157+
// expected-note {{template parameter is declared here}}
158+
auto l2 = [=]<typename y>() { int a = y; return 0; }; // expected-error {{'y' does not refer to a value}} \
159+
// expected-note {{declared here}}
160+
auto l3 = [&, y]<typename y, typename>(y) { int a = x; return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
161+
// expected-note {{template parameter is declared here}}
162+
auto l4 = [x, y]<typename y, int x>() { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
163+
// expected-error {{declaration of 'x' shadows template parameter}} \
164+
// expected-note 2{{template parameter is declared here}}
165+
auto l5 = []<typename y>(y) { return 0; }; // No diagnostic
166+
#endif
167+
}
168+
}

0 commit comments

Comments
 (0)