[clang] 0fb84bc - [clang] Diagnose shadowing of lambda's template parameter by a capture

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 28 04:27:05 PDT 2023


Author: Mariya Podchishchaeva
Date: 2023-04-28T07:26:30-04:00
New Revision: 0fb84bc7fdec1c20c2461e54d5c994939fe5b47f

URL: https://github.com/llvm/llvm-project/commit/0fb84bc7fdec1c20c2461e54d5c994939fe5b47f
DIFF: https://github.com/llvm/llvm-project/commit/0fb84bc7fdec1c20c2461e54d5c994939fe5b47f.diff

LOG: [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 https://github.com/llvm/llvm-project/issues/61105

Reviewed By: shafik, cor3ntin

Differential Revision: https://reviews.llvm.org/D148712

Added: 
    clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaLambda.cpp
    clang/test/SemaCXX/warn-shadow-in-lambdas.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 8082e9d9f323e..a61e6615b9371 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -233,6 +233,8 @@ Improvements to Clang's diagnostics
 - ``-Wformat`` now recognizes ``%lb`` for the ``printf``/``scanf`` family of
   functions.
   (`#62247: <https://github.com/llvm/llvm-project/issues/62247>`_).
+- Clang now diagnoses shadowing of lambda's template parameter by a capture.
+  (`#61105: <https://github.com/llvm/llvm-project/issues/61105>`_).
 
 Bug Fixes in This Version
 -------------------------

diff  --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp
index 7f9bec2f7627e..730f70e732579 100644
--- a/clang/lib/Sema/SemaLambda.cpp
+++ b/clang/lib/Sema/SemaLambda.cpp
@@ -1365,6 +1365,26 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
     PushOnScopeChains(P, CurScope);
   }
 
+  // C++23 [expr.prim.lambda.capture]p5:
+  // 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.
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(LSI, *this);
+  if (TemplateParams) {
+    for (const auto *TP : TemplateParams->asArray()) {
+      if (!TP->getIdentifier())
+        continue;
+      for (const auto &Capture : Intro.Captures) {
+        if (Capture.Id == TP->getIdentifier()) {
+          Diag(Capture.Loc, diag::err_template_param_shadow) << Capture.Id;
+          Diag(TP->getLocation(), diag::note_template_param_here);
+        }
+      }
+    }
+  }
+
   // C++20: dcl.decl.general p4:
   // The optional requires-clause ([temp.pre]) in an init-declarator or
   // member-declarator shall be present only if the declarator declares a

diff  --git a/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
new file mode 100644
index 0000000000000..f0d337e5dd565
--- /dev/null
+++ b/clang/test/CXX/expr/expr.prim/expr.prim.lambda/expr.prim.lambda.capture/p5.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+
+void f() {
+  int x = 0;
+  auto g = [x](int x) { return 0; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}} \
+                                     // expected-note {{variable 'x' is explicitly captured here}}
+  auto h = [y = 0]<typename y>(y) { return 0; };  // expected-error {{declaration of 'y' shadows template parameter}} \
+                                                  // expected-note {{template parameter is declared here}}
+
+}

diff  --git a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
index 9dddbf8b5f3b7..e5d4c69dcee06 100644
--- a/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ b/clang/test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -2,6 +2,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
 // RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++20 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -146,3 +147,22 @@ void avoidWarningWhenRedefining() {
     int b = 0; // expected-error {{redefinition of 'b'}}
   };
 }
+
+namespace GH61105 {
+void f() {
+  int y = 0;
+  int x = 0;
+#if __cplusplus >= 202002L
+  auto l1 = [y]<typename y>(y) { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
+                                              // expected-note {{template parameter is declared here}}
+  auto l2 = [=]<typename y>() { int a = y; return 0; }; // expected-error {{'y' does not refer to a value}} \
+                                                        // expected-note {{declared here}}
+  auto l3 = [&, y]<typename y, typename>(y) { int a = x; return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
+                                                                      // expected-note {{template parameter is declared here}}
+  auto l4 = [x, y]<typename y, int x>() { return 0; }; // expected-error {{declaration of 'y' shadows template parameter}} \
+                                                       // expected-error {{declaration of 'x' shadows template parameter}} \
+                                                       // expected-note 2{{template parameter is declared here}}
+  auto l5 = []<typename y>(y) { return 0; }; // No diagnostic
+#endif
+}
+}


        


More information about the cfe-commits mailing list