This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] PR c++/79133
- From: Ville Voutilainen <ville dot voutilainen at gmail dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>, Nathan Sidwell <nathan at acm dot org>
- Date: Sat, 7 Jul 2018 02:50:19 +0300
- Subject: [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" }
+ };
+}