Rakete1111 updated this revision to Diff 170748.
Rakete1111 added a comment.

Addressed review comments! :) Thanks


Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===================================================================
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -13081,7 +13081,7 @@
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211</a></td>
     <td>C++17</td>
     <td>Hiding by lambda captures and parameters</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="full" align="center">clang 8.0</td>
   </tr>
   <tr class="open" id="2212">
     <td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212</a></td>
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===================================================================
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // 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
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -78,8 +79,15 @@
     auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
       int var = 1; // expected-warning {{declaration shadows a local variable}}
     };
-    auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
-     (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+    auto f2 = [param] 
+     (int param) { ; };
+#if __cplusplus < 201703L
+    // expected-note@-3{{variable 'param' is explicitly captured here}}
+    // expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+    // expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+    // expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
   }
 
   // Warn for variables defined in the capture list.
@@ -134,8 +142,16 @@
   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
-  auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+  auto g3 = [param]
+   (auto param) { ; };
+#if __cplusplus < 201703L
+    // expected-note@-3{{variable 'param' is explicitly captured here}}
+    // expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+    // expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+    // expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
+
 }
 
 void avoidWarningWhenRedefining() {
@@ -145,3 +161,20 @@
     int b = 0; // expected-error {{redefinition of 'b'}}
   };
 }
+
+void parameterShadowCapture() {
+#if __cplusplus >= 201703L
+  int var = 1; // expected-note{{previous declaration is here}}
+  auto f1 = [var](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+
+  auto f2 = [var = 1](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+  // expected-error@-2{{reference to 'var' is ambiguous}}
+  // expected-note@-3{{candidate found by name lookup is 'var'}}
+  // expected-note@-4{{candidate found by name lookup is 'var'}}
+
+  auto f3 = [=](int var) { return var; };
+  // expected-warning@-1{{declaration shadows a local variable}}
+#endif
+}
Index: lib/Sema/SemaLambda.cpp
===================================================================
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,15 +493,32 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+    const SmallVectorImpl<LambdaIntroducer::LambdaCapture> &Captures,
+    CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
        p < NumParams; ++p) {
     ParmVarDecl *Param = CallOperator->getParamDecl(p);
 
     // If this has an identifier, add it to the scope stack.
     if (CurScope && Param->getIdentifier()) {
-      CheckShadow(CurScope, Param);
+      bool Error = false;
+      // Resolution of CWG 2211 in C++17 renders shadowing ill-formed.
+      for (const auto &Capture : Captures) {
+        if (Capture.Id == Param->getIdentifier()) {
+          Error = true;
+          if (getLangOpts().CPlusPlus17)
+            Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
+          else
+            Diag(Param->getLocation(),
+                 diag::warn_cxx14_compat_parameter_shadow_capture);
+          Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
+              << Capture.Id << true;
+        }
+      }
+      if (!Error)
+        CheckShadow(CurScope, Param);
 
       PushOnScopeChains(Param, CurScope);
     }
@@ -1142,7 +1159,7 @@
   LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
 
   // Add lambda parameters into scope.
-  addLambdaParameters(Method, CurScope);
+  addLambdaParameters(Intro.Captures, Method, CurScope);
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5580,7 +5580,9 @@
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
   /// Introduce the lambda parameters into scope.
-  void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
+  void addLambdaParameters(
+      const SmallVectorImpl<LambdaIntroducer::LambdaCapture> &Captures,
+      CXXMethodDecl *CallOperator, Scope *CurScope);
 
   /// Deduce a block or lambda's return type based on the return
   /// statements present in the body.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6630,6 +6630,13 @@
   def ext_star_this_lambda_capture_cxx17 : ExtWarn<
     "capture of '*this' by copy is a C++17 extension">, InGroup<CXX17>;
 
+  // C++17 parameter shadows capture
+  def err_parameter_shadow_capture : Error<
+    "a lambda parameter cannot shadow an explicitly captured entity">;
+  def warn_cxx14_compat_parameter_shadow_capture : ExtWarn<
+    "a lambda parameter that shadows a capture is incompatible with C++ "
+    "standards before C++17">, InGroup<CXXPre17Compat>;
+
   // C++2a [=, this] captures.
   def warn_cxx17_compat_equals_this_lambda_capture : Warning<
     "explicit capture of 'this' with a capture default of '=' is incompatible "
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to