aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2023-12-20 21:34:49 -0500
committerJason Merrill <jason@redhat.com>2023-12-21 22:18:00 -0500
commit2488771b6dc6b05bfdc68dbd6b7bbe0489c8dad0 (patch)
treefe6e93dc97a5ff9e5586ee1db567bb1d4723ffcd
parent5cb79aa2bdb2f6713b595b43637296a2cbdd6521 (diff)
downloadgcc-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.
-rw-r--r--gcc/cp/decl.cc42
-rw-r--r--gcc/testsuite/g++.dg/ext/label15.C1
-rw-r--r--gcc/testsuite/g++.dg/ext/label16.C34
3 files changed, 69 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);
diff --git a/gcc/testsuite/g++.dg/ext/label15.C b/gcc/testsuite/g++.dg/ext/label15.C
index f9d6a0d..5a23895 100644
--- a/gcc/testsuite/g++.dg/ext/label15.C
+++ b/gcc/testsuite/g++.dg/ext/label15.C
@@ -1,4 +1,5 @@
// PR c++/37722
+// { dg-do compile { target indirect_jumps } }
// { dg-options "" }
extern "C" int printf (const char *, ...);
diff --git a/gcc/testsuite/g++.dg/ext/label16.C b/gcc/testsuite/g++.dg/ext/label16.C
new file mode 100644
index 0000000..ea79b6e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/label16.C
@@ -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;
+}