Hi! As the following testcase shows, while check_local_shadow diagnoses most of the [basic.scope.block]/2 violations, it doesn't diagnose when parameter's name is redeclared inside of the compound-stmt of a function-try-block.
There is in that case an extra scope (sk_try with parent artificial sk_block with for FUNCTION_NEEDS_BODY_BLOCK another sk_block and only then sk_function_param). The following patch fixes that. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2023-08-31 Jakub Jelinek <ja...@redhat.com> PR c++/52953 * cp-tree.h (struct language_function): Add x_in_function_try_block member. * semantics.cc (begin_function_try_block): Set it. (finish_function_try_block): Clear it. * name-lookup.cc (check_local_shadow): If in_function_try_block and current_binding_level->kind == sk_try, skip another level. * g++.dg/diagnostic/redeclaration-3.C: New test. --- gcc/cp/cp-tree.h.jj 2023-08-30 10:42:53.579169729 +0200 +++ gcc/cp/cp-tree.h 2023-08-30 19:28:20.712246064 +0200 @@ -2110,6 +2110,7 @@ struct GTY(()) language_function { BOOL_BITFIELD returns_null : 1; BOOL_BITFIELD returns_abnormally : 1; BOOL_BITFIELD infinite_loop: 1; + BOOL_BITFIELD in_function_try_block : 1; BOOL_BITFIELD x_in_function_try_handler : 1; BOOL_BITFIELD x_in_base_initializer : 1; --- gcc/cp/semantics.cc.jj 2023-08-28 10:33:11.064187885 +0200 +++ gcc/cp/semantics.cc 2023-08-30 19:28:44.295897427 +0200 @@ -1626,6 +1626,7 @@ begin_function_try_block (tree *compound *compound_stmt = begin_compound_stmt (0); r = begin_try_block (); FN_TRY_BLOCK_P (r) = 1; + cp_function_chain->in_function_try_block = 1; return r; } @@ -1662,6 +1663,7 @@ finish_cleanup (tree cleanup, tree try_b void finish_function_try_block (tree try_block) { + cp_function_chain->in_function_try_block = 0; finish_try_block (try_block); /* FIXME : something queer about CTOR_INITIALIZER somehow following the try block, but moving it inside. */ --- gcc/cp/name-lookup.cc.jj 2023-08-24 15:36:59.272791101 +0200 +++ gcc/cp/name-lookup.cc 2023-08-30 19:40:09.396172794 +0200 @@ -3146,6 +3146,11 @@ check_local_shadow (tree decl) them there. */ cp_binding_level *b = current_binding_level->level_chain; + if (current_binding_level->kind == sk_try + && cp_function_chain->in_function_try_block) + /* Skip the function-try-block level. */ + b = b->level_chain; + if (FUNCTION_NEEDS_BODY_BLOCK (current_function_decl)) /* Skip the ctor/dtor cleanup level. */ b = b->level_chain; --- gcc/testsuite/g++.dg/diagnostic/redeclaration-3.C.jj 2023-08-30 18:51:42.252179367 +0200 +++ gcc/testsuite/g++.dg/diagnostic/redeclaration-3.C 2023-08-30 19:44:06.314933892 +0200 @@ -0,0 +1,204 @@ +// PR c++/52953 +// { dg-do compile } +// { dg-options "-pedantic-errors -Wno-switch-unreachable" } + +void +foo (int x) // { dg-message "'int x' previously declared here" } +{ + int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} + +void +bar (int x) // { dg-message "'int x' previously declared here" } +try +{ + int x; // { dg-error "declaration of 'int x' shadows a parameter" } +} +catch (...) +{ +} + +volatile int v; + +void +baz () +{ +#if __cplusplus >= 201103L + auto f = [] (int x) { int x; }; // { dg-error "declaration of 'int x' shadows a parameter" "" { target c++11 } } + // { dg-message "'int x' previously declared here" "" { target c++11 } .-1 } +#endif + if (int x = 1) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 1) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + if (int x = 0) // { dg-message "'int x' previously declared here" } + ; + else + int x; // { dg-error "redeclaration of 'int x'" } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + default:; + } + switch (int x = 1) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + while (int x = v) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + while (int x = v) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + for (int x = v; x; ++x) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + for (; int x = v; ) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + for (; int x = v; ) // { dg-message "'int x' previously declared here" } + int x; // { dg-error "redeclaration of 'int x'" } + try + { + } + catch (int x) // { dg-message "'int x' previously declared here" } + { + int x; // { dg-error "redeclaration of 'int x'" } + } + if (int x = 1) + if (int x = 1) + ; + if (int x = 0) + ; + else + if (int x = 1) + ; + if (int x = 1) + switch (int x = 1) + ; + if (int x = 0) + while (int x = v) + ; + if (int x = 0) + for (int x = v; x; ++x) + ; + switch (int x = 1) + switch (int x = 1) + { + case 1:; + } + while (int x = 0) + if (int x = 1) + ; + for (int x = v; x; ++x) + for (int x = v; x; ++x) + ; +} + +void +qux (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int x) // { dg-error "redeclaration of 'int x'" } +{ +} + +void +corge (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (...) +{ + int x; // { dg-error "redeclaration of 'int x'" } +} + +void +fred (int x) // { dg-message "'int x' previously declared here" } +try +{ +} +catch (int) +{ +} +catch (long) +{ + int x; // { dg-error "redeclaration of 'int x'" } +} + +void +garply (int x) +{ + try + { + int x; + } + catch (...) + { + int x; + } +} + +struct S +{ + S (int x) // { dg-message "'int x' previously declared here" } + try : s (x) + { + int x; // { dg-error "declaration of 'int x' shadows a parameter" } + } + catch (...) + { + } + int s; +}; + +struct T +{ + T (int x) // { dg-message "'int x' previously declared here" } + try : t (x) + { + } + catch (...) + { + int x; // { dg-error "redeclaration of 'int x'" } + } + int t; +}; + +struct U +{ + U (int x) : u (x) + { + try + { + int x; + } + catch (...) + { + int x; + } + } + int u; +}; + +struct V +{ + V (int x) : v (x) + { + { + int x; + } + } + int v; +}; Jakub