Skip to content

Commit

Permalink
c++: computed goto from catch block [PR81438]
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jicama committed Dec 22, 2023
1 parent 5cb79aa commit 2488771
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 8 deletions.
42 changes: 34 additions & 8 deletions gcc/cp/decl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions gcc/testsuite/g++.dg/ext/label15.C
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// PR c++/37722
// { dg-do compile { target indirect_jumps } }
// { dg-options "" }

extern "C" int printf (const char *, ...);
Expand Down
34 changes: 34 additions & 0 deletions gcc/testsuite/g++.dg/ext/label16.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// PR c++/81438
// { dg-do compile { target indirect_jumps } }
// { dg-options "" }

bool b;
int main()
{
try
{
try { throw 3; }
catch(...) {
h:; // { dg-warning "jump to label" }
try { throw 7; }
catch(...) {
if (b)
goto *&&h; // { dg-message "computed goto" }
// { dg-message "handled exception" "" { target *-*-* } .-1 }
else
goto *&&g; // { dg-message "computed goto" }
// { dg-message "handled exception" "" { target *-*-* } .-1 }
}
g:; // { dg-warning "jump to label" }
throw;
}
}
catch(int v)
{
__builtin_printf("%d\n", v);
if(v != 3) // 7 because we don't clean up the catch on
__builtin_abort(); // computed goto
}

return 0;
}

0 comments on commit 2488771

Please sign in to comment.