On 8 July 2018 at 02:08, Ville Voutilainen <[email protected]> wrote:
> On 8 July 2018 at 01:54, Paolo Carlini <[email protected]> wrote:
>>> That would make this more consistent with such a shadow warning, but I
>>> don't want
>>> to use the shadowing wording (which would be easy to do; just set
>>> 'shadowed' and do
>>> a 'goto inform'), because this isn't shadowing in the precise sense;
>>> the shadowing cases
>>> are warnings, whereas this is more like the redeclaration errors in
>>> the same function.
>>
>> ... indeed and that annoys me a bit. Not having studied at all c++/79133 so
>> far (sorry) it seems a little weird to me that according to the standard we
>> have to handle the two types of "shadowing" in different ways, one more
>> strict, one less. Thus I would suggest double checking the details of that,
>> eventually with Jason too in terms of the actual patch you would like to
>> apply.
>
> Well. The PR is about DR 2211 which, in simple terms, says that lambda
> parameters
> and captures cannot have the same name. See
> http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#2211
>
> That's stricter than -Wshadow, but otherwise equally strict as the
> other error cases already handled
> in check_local_shadow. So I'll make this error case more consistent
> with the others. We already
> handle redeclaration errors slightly differently from shadowing
> warnings in that function.
Here's an updated patch. Tested on Linux-PPC64, OK for trunk?
Backports?
2018-08-06 Ville Voutilainen <[email protected]>
gcc/cp/
PR c++/79133
* name-lookup.c (check_local_shadow): Reject captures and parameters
with the same name.
testsuite/
PR c++/79133
* g++.dg/cpp0x/lambda/lambda-shadow3.C: New.
* g++.dg/cpp1y/lambda-generic-variadic18.C: Likewise.
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 3aafb0f..72d87b3 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -2640,6 +2640,7 @@ check_local_shadow (tree decl)
|| TREE_CODE (decl) == TYPE_DECL)))
&& DECL_FUNCTION_SCOPE_P (old)
&& (!DECL_ARTIFICIAL (decl)
+ || is_capture_proxy (decl)
|| DECL_IMPLICIT_TYPEDEF_P (decl)
|| (VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl))))
{
@@ -2648,7 +2649,8 @@ check_local_shadow (tree decl)
/* Don't complain if it's from an enclosing function. */
if (DECL_CONTEXT (old) == current_function_decl
&& TREE_CODE (decl) != PARM_DECL
- && TREE_CODE (old) == PARM_DECL)
+ && TREE_CODE (old) == PARM_DECL
+ && !is_capture_proxy (decl))
{
/* Go to where the parms should be and see if we find
them there. */
@@ -2665,6 +2667,21 @@ check_local_shadow (tree decl)
return;
}
}
+ /* DR 2211: check that captures and parameters
+ do not have the same name. */
+ else if (is_capture_proxy (decl))
+ {
+ if (current_lambda_expr ()
+ && DECL_CONTEXT (old) == lambda_function (current_lambda_expr ())
+ && TREE_CODE (old) == PARM_DECL
+ && DECL_NAME (decl) != this_identifier)
+ {
+ error_at (DECL_SOURCE_LOCATION (old),
+ "lambda parameter %qD "
+ "previously declared as a capture", old);
+ }
+ return;
+ }
/* The local structure or class can't use parameters of
the containing function anyway. */
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..8364321
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-shadow3.C
@@ -0,0 +1,6 @@
+// { dg-do compile { target c++11 } }
+
+int main() {
+ int x = 42;
+ auto lambda = [x](int x) {}; // { dg-error "previously declared as a capture" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C
new file mode 100644
index 0000000..1eb9cce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic18.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++14 } }
+
+int main() {
+ int x = 42;
+ auto lambda2 = [x=x](int x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda3 = [x](auto... x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda4 = [](auto... x) {
+ auto lambda5 = [x...](auto... x) {}; // { dg-error "previously declared as a capture" }
+ auto lambda6 = [x...](int x) {}; // { dg-error "previously declared as a capture" }
+ };
+}