]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/6527 (g++ 3.1: class member dtor order wrong (regression in past week))
authorMark Mitchell <mark@codesourcery.com>
Thu, 2 May 2002 05:13:30 +0000 (05:13 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 2 May 2002 05:13:30 +0000 (05:13 +0000)
PR c++/6527
* init.c (perform_base_cleanups): Emit cleanups in reverse order
of construction.

From-SVN: r53032

gcc/cp/ChangeLog
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/dtor1.C [new file with mode: 0644]

index 74502d7de664aecdf9d711f88bf5702e81ce3a83..0e930a37ef1b49a2b598d3650bd6a5b4962e4f9a 100644 (file)
@@ -1,3 +1,9 @@
+2002-05-01  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/6527
+       * init.c (perform_base_cleanups): Emit cleanups in reverse order
+       of construction.
+
 2002-05-01  Gabriel Dos Reis  <gdr@codesourcery.com>
 
        * error.c (dump_type): Be careful about implicit typenames.
index d60965dc8028ddbf4ad2c8a2328b5492fe4543fa..9f840beb543ac35eaac0cf5a04ad63e1aee9cde5 100644 (file)
@@ -3229,6 +3229,52 @@ perform_base_cleanups ()
   int i, n_baseclasses;
   tree member;
   tree expr;
+  tree member_destructions = NULL;
+
+  for (member = TYPE_FIELDS (current_class_type); member;
+       member = TREE_CHAIN (member))
+    {
+      if (TREE_CODE (member) != FIELD_DECL)
+       continue;
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+       {
+         tree this_member = (build_component_ref
+                             (current_class_ref, member,
+                              NULL_TREE, 0));
+         tree this_type = TREE_TYPE (member);
+         expr = build_delete (this_type, this_member,
+                              sfk_complete_destructor,
+                              LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+                              0);
+         if (!member_destructions)
+           member_destructions = expr;
+         else
+           member_destructions = build (COMPOUND_EXPR, 
+                                        TREE_TYPE (member_destructions),
+                                        expr,
+                                        member_destructions);
+       }
+    }
+  if (member_destructions)
+    finish_expr_stmt (member_destructions);
+
+  binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
+  n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
+
+  /* Take care of the remaining baseclasses.  */
+  for (i = 0; i < n_baseclasses; i++)
+    {
+      tree base_binfo = TREE_VEC_ELT (binfos, i);
+      if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
+         || TREE_VIA_VIRTUAL (base_binfo))
+       continue;
+
+      expr = build_scoped_method_call (current_class_ref, base_binfo,
+                                      base_dtor_identifier,
+                                      NULL_TREE);
+
+      finish_expr_stmt (expr);
+    }
 
   /* Run destructors for all virtual baseclasses.  */
   if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
@@ -3271,43 +3317,6 @@ perform_base_cleanups ()
            }
        }
     }
-
-  binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
-  n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
-
-  /* Take care of the remaining baseclasses.  */
-  for (i = 0; i < n_baseclasses; i++)
-    {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
-         || TREE_VIA_VIRTUAL (base_binfo))
-       continue;
-
-      expr = build_scoped_method_call (current_class_ref, base_binfo,
-                                      base_dtor_identifier,
-                                      NULL_TREE);
-
-      finish_expr_stmt (expr);
-    }
-
-  for (member = TYPE_FIELDS (current_class_type); member;
-       member = TREE_CHAIN (member))
-    {
-      if (TREE_CODE (member) != FIELD_DECL)
-       continue;
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
-       {
-         tree this_member = (build_component_ref
-                             (current_class_ref, DECL_NAME (member),
-                              NULL_TREE, 0));
-         tree this_type = TREE_TYPE (member);
-         expr = build_delete (this_type, this_member,
-                              sfk_complete_destructor,
-                              LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
-                              0);
-         finish_expr_stmt (expr);
-       }
-    }
 }
 
 /* For type TYPE, delete the virtual baseclass objects of DECL.  */
index cb39753429370bfc465c566dbdc8f03d196100a4..be646681d086fb9689e5b1130ee48007a8cc3037 100644 (file)
@@ -1,3 +1,7 @@
+2002-05-01  Mark Mitchell  <mark@codesourcery.com>
+
+       * g++.dg/init/dtor1.C: New test.
+
 2002-04-29  Jakub Jelinek  <jakub@redhat.com>
 
        * g++.dg/parse/typedef1.C: New test.
diff --git a/gcc/testsuite/g++.dg/init/dtor1.C b/gcc/testsuite/g++.dg/init/dtor1.C
new file mode 100644 (file)
index 0000000..3a48bcd
--- /dev/null
@@ -0,0 +1,27 @@
+// { dg-do run }
+
+extern "C" void abort ();
+
+int d = 2;
+
+struct B
+{
+  int x;
+  B (int i) : x (i) { }
+  ~B () { if (d-- != x) abort (); }
+};
+
+struct A
+  : public B
+{
+  A () : B (0), x1(1), x2(2) {}
+  B x1;
+  B x2;
+};
+
+
+int main ()
+{
+  A a;
+  return 0;
+}