On 8 July 2018 at 02:08, Ville Voutilainen <ville.voutilai...@gmail.com> wrote: > On 8 July 2018 at 01:54, Paolo Carlini <paolo.carl...@oracle.com> 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 <ville.voutilai...@gmail.com> 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" } + }; +}