This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] PR c++/79133


Tested on Linux-PPC64. Ok for trunk, perhaps with the change
that I move the test under cpp1y, since it's a c++14 test anyway?

I considered pushing the captures into the parameter scope. I don't
know how to do that; changing the pushdecl_outermost_localscope
to a pushdecl doesn't seem to cut it; I guess that I should add
a new function into name-lookup.[ch], but I wonder whether
that makes sense, considering that this is lambda-only functionality.
I also wonder whether it makes more sense than the solution
in this patch, considering that we handle packs here as well
and capturepack/parampack, capturepack/param, capture/parampack
and capture/param clashes.

Guidance welcome. This approach has the benefit that it, well,
seems to work. :)

2018-07-07  Ville Voutilainen  <ville.voutilainen@gmail.com>

    gcc/cp/

    PR c++/79133
    * lambda.c (start_lambda_function): Reject captures and parameters
    with the same name.

    testsuite/

    PR c++/79133
    * g++.dg/cpp0x/lambda/lambda-shadow3.C: New.
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 3776d6b..534434a 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -1424,7 +1424,28 @@ start_lambda_function (tree fco, tree lambda_expr)
   /* Push the proxies for any explicit captures.  */
   for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;
        cap = TREE_CHAIN (cap))
-    build_capture_proxy (TREE_PURPOSE (cap), TREE_VALUE (cap));
+    {
+      /* DR 2211: check that captures and parameters
+	 do not have the same name. */
+      for (tree parms = DECL_ARGUMENTS (fco); parms;
+	   parms = TREE_CHAIN (parms))
+	{
+	  tree real_cap = TREE_VALUE (cap);
+	  tree real_parms = parms;
+	  if (PACK_EXPANSION_P (real_cap))
+	    real_cap = PACK_EXPANSION_PATTERN (real_cap);
+	  if (PACK_EXPANSION_P (parms))
+	    real_parms = PACK_EXPANSION_PATTERN (parms);
+	  if (DECL_P (real_cap)
+	      && DECL_NAME (real_cap) != this_identifier
+	      && DECL_NAME (real_cap) == DECL_NAME (real_parms))
+	    error_at (DECL_SOURCE_LOCATION (parms),
+		      "capture %qE and lambda parameter %qE "
+		      "have the same name",
+		      cap, parms);
+	}
+      build_capture_proxy (TREE_PURPOSE (cap), TREE_VALUE (cap));
+    }
 
   return body;
 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C
new file mode 100644
index 0000000..b006470
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++14 } }
+
+int main() {
+  int x = 42;
+  auto lambda = [x](int x) {}; // { dg-error "have the same name" }
+  auto lambda2 = [x=x](int x) {}; // { dg-error "have the same name" }
+  auto lambda3 = [x](auto... x) {}; // { dg-error "have the same name" }
+  auto lambda4 = [](auto... x) {
+    auto lambda5 = [x...](auto... x) {};  // { dg-error "have the same name" }
+    auto lambda6 = [x...](int x) {};  // { dg-error "have the same name" }
+  };
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]