]> git.ipfire.org Git - thirdparty/gcc.git/commit
c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]
authorJakub Jelinek <jakub@redhat.com>
Tue, 5 Sep 2023 15:31:12 +0000 (17:31 +0200)
committerJakub Jelinek <jakub@redhat.com>
Tue, 5 Sep 2023 15:31:12 +0000 (17:31 +0200)
commitefafa66c294d261a4d964383674ab9ee51feaf88
treee108ec2330a0e530748c8046d8cc4f97afa14155
parentc24982689b8af19da9a64f2283fb99764a1c5db0
c++: Diagnose [basic.scope.block]/2 violations even for block externs [PR52953]

C++17 had in [basic.block.scope]/2
"A parameter name shall not be redeclared in the outermost block of the function
definition nor in the outermost block of any handler associated with a
function-try-block."
and in [basic.block.scope]/4 similar rule for selection/iteration
statements.  My reading of that is that it applied even for block local
externs in all those spots, while they declare something at namespace scope,
the redeclaration happens in that outermost block etc. and introduces names
into that.
Those wordings seemed to have been moved somewhere else in C++20, but what's
worse, they were moved back and completely rewritten in
P1787R6: Declarations and where to find them
which has been applied as a DR (but admittedly, we don't claim yet to
implement that).
The current wording at https://eel.is/c++draft/basic.scope#block-2
and https://eel.is/c++draft/basic.scope#scope-2.10 seem to imply at least
to me that it doesn't apply to extern block local decls because their
target scope is the namespace scope and [basic.scope.block]/2 says
"and whose target scope is the block scope"...
Now, it is unclear if that is actually the intent or not.

There seems to be quite large implementation divergence on this as well.

Unpatched g++ e.g. on the redeclaration-5.C testcase diagnoses just
lines 55,58,67,70 (i.e. where the previous declaration is in for's
condition).

clang++ trunk diagnoses just lines 8 and 27, i.e. redeclaration in the
function body vs. parameter both in normal fn and lambda (but not e.g.
function-try-block and others, including ctors, but it diagnoses those
for non-extern decls).

ICC 19 diagnoses lines 8,32,38,41,45,52,55,58,61,64,67,70,76.

And MSCV trunk diagnoses 8,27,32,38,41,45,48,52,55,58,67,70,76,87,100,137
although the last 4 are just warnings.

g++ with the patch diagnoses
8,15,27,32,38,41,45,48,52,55,58,61,64,67,70,76,87,100,121,137
as the dg-error directives test.

Jason said:
> Yes, I suspect that should be
>
> If a declaration that is not a name-independent declaration and <del>whose
> target scope is</del><ins>that binds a name in</ins> the block scope S of a
>
> which seems to also be needed to prohibit the already-diagnosed
>
> void f(int i) { union { int i; }; }
> void g(int i) { enum { i }; }

The following patch diagnoses DECL_EXTERNAL in check_local_shadow like
!DECL_EXTERNAL, except that
1) it uses pedwarn instead of errors for those cases
2) it doesn't diagnose shadowing of namespace scope identifiers by block
   local externs, as they could be not actually shadowing but just redeclaring
   the same objects

2023-09-05  Jakub Jelinek  <jakub@redhat.com>

PR c++/52953
* name-lookup.cc (check_local_shadow): Don't punt early for
DECL_EXTERNAL decls, instead just disable the shadowing of namespace
decls check for those and emit a pedwarn rather than error_at or
permerror for those.  Formatting fix.

* g++.dg/diagnostic/redeclaration-4.C: New test.
* g++.dg/diagnostic/redeclaration-5.C: New test.
* g++.dg/warn/Wshadow-19.C: New test.
gcc/cp/name-lookup.cc
gcc/testsuite/g++.dg/diagnostic/redeclaration-4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/diagnostic/redeclaration-5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wshadow-19.C [new file with mode: 0644]