@@ -2970,11 +2970,24 @@ decl_jump_unsafe (tree decl)
/* A subroutine of check_previous_goto_1 to identify a branch to the user. */
static bool
-identify_goto (tree decl, const location_t *locus)
+identify_goto (tree decl, const location_t *locus, bool harderr)
{
- bool complained = (decl
- ? permerror (input_location, "jump to label %qD", decl)
- : permerror (input_location, "jump to case label"));
+ bool complained;
+ if (!harderr)
+ {
+ if (decl)
+ complained = permerror (input_location, "jump to label %qD", decl);
+ else
+ complained = permerror (input_location, "jump to case label");
+ }
+ else
+ {
+ if (decl)
+ error ("jump to label %qD", decl);
+ else
+ error ("jump to case label");
+ complained = true;
+ }
if (complained && locus)
inform (*locus, " from here");
return complained;
@@ -2991,15 +3004,16 @@ check_previous_goto_1 (tree decl, cp_bin
bool exited_omp, const location_t *locus)
{
cp_binding_level *b;
- bool identified = false, complained = false;
+ bool complained = false;
+ int identified = 0;
bool saw_eh = false, saw_omp = false, saw_tm = false;
if (exited_omp)
{
- complained = identify_goto (decl, locus);
+ complained = identify_goto (decl, locus, true);
if (complained)
inform (input_location, " exits OpenMP structured block");
- identified = saw_omp = true;
+ identified = (saw_omp = true) ? 2 : 0;
}
for (b = current_binding_level; b ; b = b->level_chain)
@@ -3016,8 +3030,8 @@ check_previous_goto_1 (tree decl, cp_bin
if (!identified)
{
- complained = identify_goto (decl, locus);
- identified = true;
+ complained = identify_goto (decl, locus, false);
+ identified = 1;
}
if (complained)
{
@@ -3035,10 +3049,10 @@ check_previous_goto_1 (tree decl, cp_bin
break;
if ((b->kind == sk_try || b->kind == sk_catch) && !saw_eh)
{
- if (!identified)
+ if (identified < 2)
{
- complained = identify_goto (decl, locus);
- identified = true;
+ complained = identify_goto (decl, locus, true);
+ identified = 2;
}
if (complained)
{
@@ -3051,10 +3065,10 @@ check_previous_goto_1 (tree decl, cp_bin
}
if (b->kind == sk_omp && !saw_omp)
{
- if (!identified)
+ if (identified < 2)
{
- complained = identify_goto (decl, locus);
- identified = true;
+ complained = identify_goto (decl, locus, true);
+ identified = 2;
}
if (complained)
inform (input_location, " enters OpenMP structured block");
@@ -3062,10 +3076,10 @@ check_previous_goto_1 (tree decl, cp_bin
}
if (b->kind == sk_transaction && !saw_tm)
{
- if (!identified)
+ if (identified < 2)
{
- complained = identify_goto (decl, locus);
- identified = true;
+ complained = identify_goto (decl, locus, true);
+ identified = 2;
}
if (complained)
inform (input_location,
@@ -3098,7 +3112,8 @@ void
check_goto (tree decl)
{
struct named_label_entry *ent, dummy;
- bool saw_catch = false, identified = false, complained = false;
+ bool saw_catch = false, complained = false;
+ int identified = 0;
tree bad;
unsigned ix;
@@ -3141,11 +3156,21 @@ check_goto (tree decl)
if (ent->in_try_scope || ent->in_catch_scope || ent->in_transaction_scope
|| ent->in_omp_scope || !vec_safe_is_empty (ent->bad_decls))
{
- complained = permerror (DECL_SOURCE_LOCATION (decl),
- "jump to label %qD", decl);
+ if (ent->in_try_scope || ent->in_catch_scope
+ || ent->in_transaction_scope || ent->in_omp_scope)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl), "jump to label %qD", decl);
+ complained = true;
+ identified = 2;
+ }
+ else
+ {
+ complained = permerror (DECL_SOURCE_LOCATION (decl),
+ "jump to label %qD", decl);
+ identified = 1;
+ }
if (complained)
inform (input_location, " from here");
- identified = true;
}
FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
@@ -3155,6 +3180,14 @@ check_goto (tree decl)
if (u > 1 && DECL_ARTIFICIAL (bad))
{
/* Can't skip init of __exception_info. */
+ if (identified == 1)
+ {
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "jump to label %qD", decl);
+ inform (input_location, " from here");
+ complained = true;
+ identified = 2;
+ }
if (complained)
inform (DECL_SOURCE_LOCATION (bad), " enters catch block");
saw_catch = true;
@@ -3195,13 +3228,13 @@ check_goto (tree decl)
break;
if (b->kind == sk_omp)
{
- if (!identified)
+ if (identified < 2)
{
- complained = permerror (DECL_SOURCE_LOCATION (decl),
- "jump to label %qD", decl);
- if (complained)
- inform (input_location, " from here");
- identified = true;
+ error_at (DECL_SOURCE_LOCATION (decl),
+ "jump to label %qD", decl);
+ inform (input_location, " from here");
+ complained = true;
+ identified = 2;
}
if (complained)
inform (input_location, " exits OpenMP structured block");
@@ -0,0 +1,14 @@
+// PR c++/67409
+// { dg-options "-fpermissive" }
+
+void f()
+try
+ {
+ goto l2; // { dg-message "from here" }
+ l1: ; // { dg-error "jump to label 'l1'" }
+ } catch (...)
+ {
+ l2: ; // { dg-error "jump to label 'l2'" }
+ // { dg-message "enters catch block" "" { target *-*-*} 11 }
+ goto l1; // { dg-message "from here|enters try block" }
+ }