]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: goto entering scope of obj w/ non-trivial dtor [PR103091]
authorPatrick Palka <ppalka@redhat.com>
Sun, 7 May 2023 16:09:03 +0000 (12:09 -0400)
committerPatrick Palka <ppalka@redhat.com>
Sun, 7 May 2023 16:09:03 +0000 (12:09 -0400)
It seems ever since DR 2256 goto is permitted to cross the initialization
of a trivially initialized object with a non-trivial destructor.  We
already supported this as an -fpermissive extension, so this patch just
makes us unconditionally support this.

DR 2256
PR c++/103091

gcc/cp/ChangeLog:

* decl.cc (decl_jump_unsafe): Return bool instead of int.
Don't consider TYPE_HAS_NONTRIVIAL_DESTRUCTOR.
(check_previous_goto_1): Simplify now that decl_jump_unsafe
returns bool instead of int.
(check_goto): Likewise.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.other/init9.C: Don't expect diagnostics for
goto made valid by DR 2256.
* g++.dg/init/goto4.C: New test.

gcc/cp/decl.cc
gcc/testsuite/g++.dg/init/goto4.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/init9.C

index 71d33d2b7a4d266b1e91bb335fdbe5594ed14c70..23a2b2fef0bc88ed127214c5a911138fc82860d7 100644 (file)
@@ -69,7 +69,7 @@ enum bad_spec_place {
 
 static const char *redeclaration_error_message (tree, tree);
 
-static int decl_jump_unsafe (tree);
+static bool decl_jump_unsafe (tree);
 static void require_complete_types_for_parms (tree);
 static tree grok_reference_init (tree, tree, tree, int);
 static tree grokvardecl (tree, tree, tree, const cp_decl_specifier_seq *,
@@ -3548,10 +3548,9 @@ declare_local_label (tree id)
   return ent ? ent->label_decl : NULL_TREE;
 }
 
-/* Returns nonzero if it is ill-formed to jump past the declaration of
-   DECL.  Returns 2 if it's also a real problem.  */
+/* Returns true if it is ill-formed to jump past the declaration of DECL.  */
 
-static int
+static bool
 decl_jump_unsafe (tree decl)
 {
   /* [stmt.dcl]/3: A program that jumps from a point where a local variable
@@ -3562,18 +3561,11 @@ decl_jump_unsafe (tree decl)
      preceding types and is declared without an initializer (8.5).  */
   tree type = TREE_TYPE (decl);
 
-  if (!VAR_P (decl) || TREE_STATIC (decl)
-      || type == error_mark_node)
-    return 0;
-
-  if (DECL_NONTRIVIALLY_INITIALIZED_P (decl)
-      || variably_modified_type_p (type, NULL_TREE))
-    return 2;
-
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
-    return 1;
-
-  return 0;
+  return (type != error_mark_node
+         && VAR_P (decl)
+         && !TREE_STATIC (decl)
+         && (DECL_NONTRIVIALLY_INITIALIZED_P (decl)
+             || variably_modified_type_p (type, NULL_TREE)));
 }
 
 /* A subroutine of check_previous_goto_1 and check_goto to identify a branch
@@ -3625,27 +3617,18 @@ check_previous_goto_1 (tree decl, cp_binding_level* level, tree names,
           new_decls = (DECL_P (new_decls) ? DECL_CHAIN (new_decls)
                        : TREE_CHAIN (new_decls)))
        {
-         int problem = decl_jump_unsafe (new_decls);
+         bool problem = decl_jump_unsafe (new_decls);
          if (! problem)
            continue;
 
          if (!identified)
            {
-             complained = identify_goto (decl, input_location, locus,
-                                         problem > 1
-                                         ? DK_ERROR : DK_PERMERROR);
+             complained = identify_goto (decl, input_location, locus, DK_ERROR);
              identified = 1;
            }
          if (complained)
-           {
-             if (problem > 1)
-               inform (DECL_SOURCE_LOCATION (new_decls),
-                       "  crosses initialization of %q#D", new_decls);
-             else
-               inform (DECL_SOURCE_LOCATION (new_decls),
-                       "  enters scope of %q#D, which has "
-                       "non-trivial destructor", new_decls);
-           }
+           inform (DECL_SOURCE_LOCATION (new_decls),
+                   "  crosses initialization of %q#D", new_decls);
        }
 
       if (b == level)
@@ -3790,9 +3773,9 @@ check_goto (tree decl)
 
   FOR_EACH_VEC_SAFE_ELT (ent->bad_decls, ix, bad)
     {
-      int u = decl_jump_unsafe (bad);
+      bool problem = decl_jump_unsafe (bad);
 
-      if (u > 1 && DECL_ARTIFICIAL (bad))
+      if (problem && DECL_ARTIFICIAL (bad))
        {
          /* Can't skip init of __exception_info.  */
          if (identified == 1)
@@ -3806,15 +3789,8 @@ check_goto (tree decl)
          saw_catch = true;
        }
       else if (complained)
-       {
-         if (u > 1)
-           inform (DECL_SOURCE_LOCATION (bad),
-                   "  skips initialization of %q#D", bad);
-         else
-           inform (DECL_SOURCE_LOCATION (bad),
-                   "  enters scope of %q#D which has "
-                   "non-trivial destructor", bad);
-       }
+       inform (DECL_SOURCE_LOCATION (bad),
+               "  skips initialization of %q#D", bad);
     }
 
   if (complained)
diff --git a/gcc/testsuite/g++.dg/init/goto4.C b/gcc/testsuite/g++.dg/init/goto4.C
new file mode 100644 (file)
index 0000000..90ae52e
--- /dev/null
@@ -0,0 +1,22 @@
+// DR 2256
+// PR c++/103091
+// { dg-do run }
+
+static int i;
+
+struct A {
+  ~A() { ++i;}
+};
+
+void f() {
+  goto L;
+  A a;
+L:
+  return;
+}
+
+int main() {
+  f();
+  if (i != 1)
+    __builtin_abort();
+}
index 46d99028bdd61e2edcef0a82e79e8255fc33241e..0194cd1b49a9474ab2e824540787e3351336bb60 100644 (file)
@@ -24,9 +24,10 @@ struct X {
 };
 
 void b() {
-  goto bar; // { dg-message "" } jump from here
-  X x; // { dg-message "" } jump crosses initialization
- bar: // { dg-error "" } jump to here
+  // This was ill-formed until DR 2256.
+  goto bar;
+  X x;
+ bar:
   ;
 }