re PR c++/6316 (trap when compiling file)
authorJakub Jelinek <jakub@redhat.com>
Wed, 17 Apr 2002 17:17:55 +0000 (19:17 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 17 Apr 2002 17:17:55 +0000 (19:17 +0200)
PR c++/6316
* decl2.c (finish_file): Clear DECL_EXTERNAL in a separate loop
before expanding.

* g++.dg/opt/inline1.C: New test.

From-SVN: r52434

gcc/cp/ChangeLog
gcc/cp/decl2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/inline1.C [new file with mode: 0644]

index 4f41e4f58a3409df8aa2f1e890d400ced1650faa..b7e31a4fdc5b69a4d82ded9def2c2f5a7161411b 100644 (file)
@@ -1,3 +1,9 @@
+2002-04-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/6316
+       * decl2.c (finish_file): Clear DECL_EXTERNAL in a separate loop
+       before expanding.
+
 2002-04-16  Mark Mitchell  <mark@codesourcery.com>
 
        * init.c (begin_init_stmts): Remove commented out code.
index 2eece8aed05abf741fef4398f2e95e490aef4012..1b4daa100139889d33edf791a448d37961c9175f 100644 (file)
@@ -3432,7 +3432,11 @@ finish_file ()
         not defined when they really are.  This keeps these functions
         from being put out unnecessarily.  But, we must stop lying
         when the functions are referenced, or if they are not comdat
-        since they need to be put out now.  */
+        since they need to be put out now.
+        This is done in a separate for cycle, because if some deferred
+        function is contained in another deferred function later in
+        deferred_fns varray, rest_of_compilation would skip this
+        function and we really cannot expand the same function twice. */
       for (i = 0; i < deferred_fns_used; ++i)
        {
          tree decl = VARRAY_TREE (deferred_fns, i);
@@ -3441,6 +3445,11 @@ finish_file ()
              && DECL_INITIAL (decl)
              && DECL_NEEDED_P (decl))
            DECL_EXTERNAL (decl) = 0;
+       }
+
+      for (i = 0; i < deferred_fns_used; ++i)
+       {
+         tree decl = VARRAY_TREE (deferred_fns, i);
 
          /* If we're going to need to write this function out, and
             there's already a body for it, create RTL for it now.
index 36ea8b773b27e70ad82e64d8b3996a084ea13310..3fb38ece2d4e05cfd90880b40092b4c911bd2075 100644 (file)
@@ -2,6 +2,8 @@
 
        * gcc.dg/20020416-1.c: New test.
 
+       * g++.dg/opt/inline1.C: New test.
+
 2002-04-16  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.dg/altivec-5.c: New test.
diff --git a/gcc/testsuite/g++.dg/opt/inline1.C b/gcc/testsuite/g++.dg/opt/inline1.C
new file mode 100644 (file)
index 0000000..55b9311
--- /dev/null
@@ -0,0 +1,43 @@
+// PR c++/6316
+// This testcase ICEd because when deferred bar()::F::F() was being
+// expanded, containing bar() was still deferred and had DECL_EXTERNAL set
+// (and DECL_NOT_REALLY_EXTERN too).
+// { dg-do compile }
+// { dg-options "-O3" }
+
+struct A { ~A() throw() {} };
+template<typename T, typename U> struct B { U a; B(const T *); };
+typedef B<char, A> C;
+struct D { D(); };
+struct E { virtual ~E(); };
+
+E *bar ();
+
+void
+foo ()
+{
+  E *a = bar ();
+}
+
+extern char *z [];
+
+E *
+bar ()
+{
+  struct F : public E
+  {
+    F ()
+    {
+      for (int i = 0; i < 2; i++)
+       C e = z[i];
+    }
+    D x, y;
+  };
+  return new F ();
+}
+
+int
+main ()
+{
+  foo ();
+}