Hi!

Before Paolo's changes, e.g. identify_goto always used permerror, and then
depending on the severity of the issue either issued another permerror
describing in detail the issue, or error.
In particular, entering scope of a decl with non-trivial dtor has been
a permerror, pretty much everything else has been a hard error.
The PR Paolo has been fixing was a request to allow with -fpermissive
crossing initialization (i.e. just warn in that case, instead of hard
error), but the patch for consistency turned all the permerror; error
cases to if (permerror ()) inform, which means also other kinds of goto
errors can now be ignored with -fpermissive.  But, as the testcase shows,
in certain cases we ICE on it later on; e.g. the OpenMP SESE violations
definitely should be hard errors, because of the ICEs also the entering of
try or catch blocks through goto, TM violations etc.

The following patch arranges for using error instead of permerror
in the case of the more severe violations; if a single goto violates both
something less severe (first) and then something more severe, we can emit
e.g. the jump to label ... diagnostics twice, for non-permissive once
with [-fpermissive] after it, once without, for -fpermissive once as a
warning, once as an error.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/5.3?

2015-11-18  Jakub Jelinek  <ja...@redhat.com>

        PR c++/67409
        * decl.c (identify_goto): Add harderr argument, call error instead of
        permerror if it is true.
        (check_previous_goto_1): Adjust identify_goto callers, treat all cases
        but crossing initialization and entering scope of decl with non-trivial
        dtor as unconditional hard errors.
        (check_goto): Treat all cases but crossing initialization and entering
        scope of decl with non-trivial dtor as unconditional hard errors.

        * g++.dg/eh/goto3.C: New test.

--- gcc/cp/decl.c.jj    2015-11-14 19:35:53.000000000 +0100
+++ gcc/cp/decl.c       2015-11-18 12:30:40.085342627 +0100
@@ -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");
--- gcc/testsuite/g++.dg/eh/goto3.C.jj  2015-11-18 12:24:17.313744588 +0100
+++ gcc/testsuite/g++.dg/eh/goto3.C     2015-11-18 12:25:28.940733749 +0100
@@ -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" }
+  }

        Jakub

Reply via email to