diff options
author | Jason Merrill <jason@redhat.com> | 2023-12-20 21:34:49 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2023-12-21 22:18:00 -0500 |
commit | 2488771b6dc6b05bfdc68dbd6b7bbe0489c8dad0 (patch) | |
tree | fe6e93dc97a5ff9e5586ee1db567bb1d4723ffcd /gcc/cp | |
parent | 5cb79aa2bdb2f6713b595b43637296a2cbdd6521 (diff) | |
download | gcc-2488771b6dc6b05bfdc68dbd6b7bbe0489c8dad0.zip gcc-2488771b6dc6b05bfdc68dbd6b7bbe0489c8dad0.tar.gz gcc-2488771b6dc6b05bfdc68dbd6b7bbe0489c8dad0.tar.bz2 |
c++: computed goto from catch block [PR81438]
As with 37722, we don't clean up the exception object if a computed goto
leaves a catch block, but we can warn about that.
PR c++/81438
gcc/cp/ChangeLog:
* decl.cc (poplevel_named_label_1): Handle leaving catch.
(check_previous_goto_1): Likewise.
(check_goto_1): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/ext/label15.C: Require indirect_jumps.
* g++.dg/ext/label16.C: New test.
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/decl.cc | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc index e044bfa..6b4d89e 100644 --- a/gcc/cp/decl.cc +++ b/gcc/cp/decl.cc @@ -571,10 +571,14 @@ poplevel_named_label_1 (named_label_entry **slot, cp_binding_level *bl) if (use->binding_level == bl) { if (auto &cg = use->computed_goto) - for (tree d = use->names_in_scope; d; d = DECL_CHAIN (d)) - if (TREE_CODE (d) == VAR_DECL && !TREE_STATIC (d) - && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (d))) - vec_safe_push (cg, d); + { + if (bl->kind == sk_catch) + vec_safe_push (cg, get_identifier ("catch")); + for (tree d = use->names_in_scope; d; d = DECL_CHAIN (d)) + if (TREE_CODE (d) == VAR_DECL && !TREE_STATIC (d) + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (d))) + vec_safe_push (cg, d); + } use->binding_level = obl; use->names_in_scope = obl->names; @@ -3820,7 +3824,12 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names, identified = 2; if (complained) for (tree d : computed) - inform (DECL_SOURCE_LOCATION (d), " does not destroy %qD", d); + { + if (DECL_P (d)) + inform (DECL_SOURCE_LOCATION (d), " does not destroy %qD", d); + else if (d == get_identifier ("catch")) + inform (*locus, " does not clean up handled exception"); + } } return !identified; @@ -3963,15 +3972,32 @@ check_goto_1 (named_label_entry *ent, bool computed) auto names = ent->names_in_scope; for (auto b = current_binding_level; ; b = b->level_chain) { + if (b->kind == sk_catch) + { + if (!identified) + { + complained + = identify_goto (decl, DECL_SOURCE_LOCATION (decl), + &input_location, DK_ERROR, computed); + identified = 2; + } + if (complained) + inform (input_location, + " does not clean up handled exception"); + } tree end = b == level ? names : NULL_TREE; for (tree d = b->names; d != end; d = DECL_CHAIN (d)) { if (TREE_CODE (d) == VAR_DECL && !TREE_STATIC (d) && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (d))) { - complained = identify_goto (decl, DECL_SOURCE_LOCATION (decl), - &input_location, DK_ERROR, - computed); + if (!identified) + { + complained + = identify_goto (decl, DECL_SOURCE_LOCATION (decl), + &input_location, DK_ERROR, computed); + identified = 2; + } if (complained) inform (DECL_SOURCE_LOCATION (d), " does not destroy %qD", d); |