Am 12.04.2013 08:41, schrieb Janus Weil:
2013/4/12 Tobias Burnus <bur...@net-b.de>:
I think there was a test-suite failure when I tried it. In any case,
variables might be in static memory even if attr.save is not set:

- Module variables
- Variables of the main program
- Local variables of constant size (instead of allocating them on the
stack), depending on their size
- All local variables with -fno-automatic, which implies SAVE
- If "SAVE" has been specified for the scoping unit
Yes, but for most of them one should have attr.save=SAVE_IMPLICIT (at
least for #1, #4 and #5?).

(see below)

And for those that do not have attr.save set, gfc_trans_deferred_vars
should take care of initializing the vptr already, right? Do we have a
double initlialization for these cases now?

Well, the new code looks as follows - thus, there should be not a double initialization:

      if (sym->ts.type == BT_CLASS && TREE_STATIC (sym->backend_decl)
          && CLASS_DATA (sym)->attr.allocatable)
...
      else if (sym->attr.dimension || sym->attr.codimension)
      else if ((!sym->attr.dummy || sym->ts.deferred)
                && (sym->ts.type == BT_CLASS
                && CLASS_DATA (sym)->attr.class_pointer))
        continue;
      else if ((!sym->attr.dummy || sym->ts.deferred)
                && (sym->attr.allocatable
                    || (sym->ts.type == BT_CLASS
                        && CLASS_DATA (sym)->attr.allocatable)))
        {
          if (!sym->attr.save && gfc_option.flag_max_stack_var_size != 0)

and a bunch of more "else if".


 * * *

Actually, after committing the patch, I realized that the code above not only disables the double assignment but also the deallocate. Thus, for -fmax-stack-var-size=1 one has no deallocation - and, thus, the vptr might be wrong (it would be set by deallocate, which is not called).

I have now moved to the proposed
   sym->attr.save || gfc_option.flag_max_stack_var_size == 0
instead of
  TREE_STATIC (sym->backend_decl)

Thus, you were on the right track!


[Pointers]
Ok, I guess one could argue that it could not hurt to do the initialization for pointers, too. But since the standard does not seems to require it, let's forget about it.

At some point, I'd like to have some pointer-is-uninitialized check; for that one initializes the pointer with a bogus value and checks at run-time whether it has that value, which implies that it is uninitialized. Otherwise, static variables have data == NULL by default (.bss section of the assembler file, not needed for Fortran but still used).

Thanks for the review - and for asking the right questions.

Committed as Rev. 197844 and the attached follow-up patch as Rev. 197848.

Tobias
2013-04-12  Tobias Burnus  <bur...@net-b.de>

	PR fortran/56845
	* trans-decl.c (gfc_trans_deferred_vars): Restrict
	static CLASS init to SAVE and -fno-automatic.

2013-04-12  Tobias Burnus  <bur...@net-b.de>

	PR fortran/56845
	* gfortran.dg/class_allocate_15.f90: New.

	Revert:
	2013-04-12  Tobias Burnus  <bur...@net-b.de>

	* gfortran.dg/coarray_lib_alloc_2.f90: Update
	scan-tree-dump-times.

diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 779df16..f2cf2de 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -3649,7 +3649,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
 				NULL_TREE);
 	}
 
-      if (sym->ts.type == BT_CLASS && TREE_STATIC (sym->backend_decl)
+      if (sym->ts.type == BT_CLASS
+	  && (sym->attr.save || gfc_option.flag_max_stack_var_size == 0)
 	  && CLASS_DATA (sym)->attr.allocatable)
 	{
 	  tree vptr;
diff --git a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_2.f90 b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_2.f90
index a41be79..3aaff1e 100644
--- a/gcc/testsuite/gfortran.dg/coarray_lib_alloc_2.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_lib_alloc_2.f90
@@ -18,6 +18,6 @@
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_register .1, 1, &yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, &stat.., &errmsg, 200.;" 1 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, 0B, 0B, 0.;" 0 "original" } }
-! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx._data.token, 0B, 0B, 0.;" 0 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&yy._data.token, 0B, 0B, 0.;" 1 "original" } }
+! { dg-final { scan-tree-dump-times "_gfortran_caf_deregister .&xx._data.token, 0B, 0B, 0.;" 1 "original" } }
 ! { dg-final { cleanup-tree-dump "original" } }
--- /dev/null	2013-04-12 09:16:45.096038934 +0200
+++ gcc/gcc/testsuite/gfortran.dg/class_allocate_15.f90	2013-04-12 10:34:38.982753620 +0200
@@ -0,0 +1,28 @@
+! { dg-do run }
+! { dg-options "-fdump-tree-original -fdump-tree-original -fmax-stack-var-size=1" }
+!
+! PR fortran/56845
+!
+type t
+end type t
+type, extends(t) :: t2
+end type t2
+type(t) :: y
+call foo()
+call bar()
+contains
+  subroutine foo()
+    class(t), allocatable :: x
+    if(allocated(x)) call abort()
+    if(.not.same_type_as(x,y)) call abort()
+    allocate (t2 :: x)
+  end
+  subroutine bar()
+    class(t), allocatable :: x(:)
+    if(allocated(x)) call abort()
+    if(.not.same_type_as(x,y)) call abort()
+    allocate (t2 :: x(4))
+  end
+end
+! { dg-final { scan-tree-dump-times "__builtin_free" 2 "original" } }
+! { dg-final { cleanup-tree-dump "original" } }

Reply via email to