Bug 60357 - [F08] structure constructor with unspecified values for allocatable components
Summary: [F08] structure constructor with unspecified values for allocatable components
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: rejects-valid
Depends on:
Blocks: 39627
  Show dependency treegraph
 
Reported: 2014-02-27 14:56 UTC by Antony Lewis
Modified: 2015-01-26 10:57 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-02-27 00:00:00


Attachments
test_pr60357.f08.003t.original (688 bytes, application/octet-stream)
2014-12-29 17:37 UTC, Andre Vehreschild
Details
test_pr60357.f08 (167 bytes, application/octet-stream)
2014-12-29 17:37 UTC, Andre Vehreschild
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Antony Lewis 2014-02-27 14:56:36 UTC
This valid F2008 code is rejected:


    module testmod
    Type A
        integer :: X = 1
        integer, allocatable :: y 
    end type A
    end module

    program testerprog
    use testmod
    Type(A) :: Me = A(X=1)

    end program


Compiler error is:

Type(A) :: Me = A(X=1)
               1
Error: No initializer for component 'y' given in the structure constructor at (1)!

However initialization statements are not required for allocatable components.
Comment 1 janus 2014-02-27 21:03:49 UTC
This seems to be allowed only since Fortran 2008. The F03 standard has:

C485 (R457) A component-spec shall be provided for a component unless it has default initialization or is inheritance associated with another component for which a component-spec is provided or that has default initialization.

While in F08 this sounds like:

C492 (R455) A component-spec shall be provided for a nonallocatable component unless it has default initialization or is inheritance associated with a subcomponent of another component for which a component-spec is provided.

Note in particular the addition of 'nonallocatable'.
Comment 2 janus 2014-02-27 22:19:45 UTC
Draft patch:

Index: gcc/fortran/array.c
===================================================================
--- gcc/fortran/array.c	(revision 208207)
+++ gcc/fortran/array.c	(working copy)
@@ -1307,6 +1307,9 @@ check_constructor (gfc_constructor_base ctor, bool
   for (c = gfc_constructor_first (ctor); c; c = gfc_constructor_next (c))
     {
       e = c->expr;
+      
+      if (!e)
+	continue;
 
       if (e->expr_type != EXPR_ARRAY)
 	{
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c	(revision 208207)
+++ gcc/fortran/expr.c	(working copy)
@@ -2200,7 +2200,7 @@ check_alloc_comp_init (gfc_expr *e)
        ctor = gfc_constructor_first (e->value.constructor);
        comp; comp = comp->next, ctor = gfc_constructor_next (ctor))
     {
-      if (comp->attr.allocatable
+      if (comp->attr.allocatable && ctor->expr
           && ctor->expr->expr_type != EXPR_NULL)
         {
 	  gfc_error("Invalid initialization expression for ALLOCATABLE "
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(revision 208207)
+++ gcc/fortran/primary.c	(working copy)
@@ -2365,6 +2365,13 @@ build_actual_constructor (gfc_structure_ctor_compo
 		return false;
 	      value = gfc_copy_expr (comp->initializer);
 	    }
+	  else if (comp->attr.allocatable)
+	    {
+	      if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
+		  "allocatable component '%s' given in the structure "
+		  "constructor at %C", comp->name))
+		return false;
+	    }
 	  else
 	    {
 	      gfc_error ("No initializer for component '%s' given in the"
Comment 3 janus 2014-02-28 17:35:45 UTC
(In reply to janus from comment #2)
> Draft patch:

... regtests cleanly!
Comment 4 Dominique d'Humieres 2014-08-12 15:15:18 UTC
Note that while

    program testerprog
    use testmod
    Type(A) :: Me
    Me%y=2
    print *, Me%x, Me%y

    end program

gives at run time

           1           2

    program testerprog
    use testmod
    Type(A) :: Me
    allocate(Me%y)
    Me = A(X=1, y=2)
    print *, Me%y

    end program

gives

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Comment 5 Dominique d'Humieres 2014-12-21 14:14:43 UTC
The patch in comment 2 needs to be update to

--- ../_clean/gcc/fortran/primary.c	2014-12-16 22:27:14.000000000 +0100
+++ gcc/fortran/primary.c	2014-12-21 14:50:53.000000000 +0100
@@ -2367,6 +2367,13 @@ build_actual_constructor (gfc_structure_
 		return false;
 	      value = gfc_copy_expr (comp->initializer);
 	    }
+	  else if (comp->attr.allocatable)
+	    {
+	      if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
+		  "allocatable component '%s' given in the structure "
+		  "constructor at %C", comp->name))
+		return false;
+	    }
 	  else if (!comp->attr.deferred_parameter)
 	    {
 	      gfc_error ("No initializer for component %qs given in the"

Note that while

    program testerprog
    use testmod
    Type(A) :: Me
    allocate(Me%y)
    Me = A(X=1, y=2)
    print *, Me%y

    end program

gives

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

    program testerprog
    use testmod
    Type(A) :: Me
    Me = A(X=1, y=2)
    print *, Me%x, Me%y

    end program

gives

           1           2

i.e., 'allocate(Me%y)' conflicts with Me = A(X=1, y=2). May be this expected.
Comment 6 janus 2014-12-23 23:46:40 UTC
(In reply to Dominique d'Humieres from comment #4)
>     program testerprog
>     use testmod
>     Type(A) :: Me
>     allocate(Me%y)
>     Me = A(X=1, y=2)
>     print *, Me%y
> 
>     end program
> 
> gives
> 
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.

Confirmed. However, this segfault is not related to the original bug (nor to the patch I posted). It's a separate issue.
Comment 7 janus 2014-12-29 10:45:54 UTC
Author: janus
Date: Mon Dec 29 10:45:21 2014
New Revision: 219098

URL: https://gcc.gnu.org/viewcvs?rev=219098&root=gcc&view=rev
Log:
2014-12-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/60357
	* array.c (check_constructor): Ignore empty expressions.
	* expr.c (check_alloc_comp_init): Check if constructor expression
	exists.
	* primary.c (build_actual_constructor): Warn for absent alloc-comp
	initializers in pre-2008 standards.

2014-12-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/60357
	* gfortran.dg/alloc_comp_constructor_7.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_constructor_7.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/array.c
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/primary.c
    trunk/gcc/testsuite/ChangeLog
Comment 8 janus 2014-12-29 10:55:29 UTC
The original problem in comment 0 is fixed with r219098. Thanks to Anthony for reporting this!

TODO: The segfault reported by Dominique in comment 4 and 5.
Comment 9 Andre Vehreschild 2014-12-29 14:59:42 UTC
Hi Janus,

be careful with the code in comment #4 and #5. When I remember correctly then it was me who added the allocate trying to understand how Fortran worked there. Meaning: That must not be valid Fortran. In fact, does my current work on this pr and on #61275 report that Me%y is already allocated and must not be reallocated again. 

That is, I may already have a patch that touches the issue. I just need to figure, if allocating the component explicitly is valid in Fortran. Do you know something about that? I am still reading the Fortran standards, but haven't found the location that answers my question.

Andre
Comment 10 janus 2014-12-29 16:42:01 UTC
(In reply to Andre Vehreschild from comment #9)
> I just need to
> figure, if allocating the component explicitly is valid in Fortran.

For sure. I think both the examples in comment 4 and 5 are actually valid Fortran code.

In order to make sure we're talking about the same thing, let's have a look at the following code:

Type A
  integer :: X = 1
  integer, allocatable :: y
end type
Type(A) :: Me
allocate(Me%y)
print *,"A"
Me = A(X=1, y=2)
print *,"B"
print *, Me%y
end

This is a variant of the example above that produced the segfault. I inserted some print statements in order to debug it. It prints at runtime:

 A
 B

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.


This shows clearly that the segfault occurs when we try to access Me%y in the last print statement, meaning that it is probably unallocated although it clearly should be.

-fdump-tree-original shows that the problem is in the translation of the structure constructor assignment, which apparently leaves the y-component unallocated.
Comment 11 Andre Vehreschild 2014-12-29 17:37:19 UTC
Created attachment 34352 [details]
test_pr60357.f08.003t.original

Hi Janus,

before you invest too much time into that: My current patch level produces
intermediate code as attached (for a slightly different program, also attached).
I was solving the (re-)alloc on assign issue like in PR61275. I now run into the
runtime error: 

At line 15 of file test_pr60357.f08: Attempting to allocate
already allocated variable 'de'.

Obviously I have over fullfilled the needed allocs:

(1) a.5.y is allocated
(2) a.4.y is allocated
(3) a.0.y is allocated
(4) de.y is allocated
(5) a.2.y is allocated

I am wondering which allocs should really be done, and which one are accidently
added. I doubt that (1) and (2) should be there. (3) and (5) are ok imho. Now
my client (the reporter of the bug, Antony) tells me, that (4) is valid Fortran
("valid" by ifort), but the allocate(De%y) is useless there, as it is freed
before the constructor assign with implicit alloc is done. With my current
patch level, your program would be running fine, because I would auto alloc y
on the assignment.

To summarize my questions: 

Which allocs should be done? 

Given the too allocs in (1) and (2) are removed, would the intermediate code be
correct for the fortran?

Can you help me on this.

Regards,
	Andre


On Mon, 29 Dec 2014 16:42:01 +0000
"janus at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org> wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60357
> 
> --- Comment #10 from janus at gcc dot gnu.org ---
> (In reply to Andre Vehreschild from comment #9)
> > I just need to
> > figure, if allocating the component explicitly is valid in Fortran.
> 
> For sure. I think both the examples in comment 4 and 5 are actually valid
> Fortran code.
> 
> In order to make sure we're talking about the same thing, let's have a look at
> the following code:
> 
> Type A
>   integer :: X = 1
>   integer, allocatable :: y
> end type
> Type(A) :: Me
> allocate(Me%y)
> print *,"A"
> Me = A(X=1, y=2)
> print *,"B"
> print *, Me%y
> end
> 
> This is a variant of the example above that produced the segfault. I inserted
> some print statements in order to debug it. It prints at runtime:
> 
>  A
>  B
> 
> Program received signal SIGSEGV: Segmentation fault - invalid memory
> reference.
> 
> 
> This shows clearly that the segfault occurs when we try to access Me%y in the
> last print statement, meaning that it is probably unallocated although it
> clearly should be.
> 
> -fdump-tree-original shows that the problem is in the translation of the
> structure constructor assignment, which apparently leaves the y-component
> unallocated.
>
Comment 12 Andre Vehreschild 2014-12-29 17:37:24 UTC
Created attachment 34353 [details]
test_pr60357.f08
Comment 13 Paul Thomas 2015-01-17 18:09:11 UTC
Author: pault
Date: Sat Jan 17 18:08:38 2015
New Revision: 219801

URL: https://gcc.gnu.org/viewcvs?rev=219801&root=gcc&view=rev
Log:
2015-01-17  Andre Vehreschild  <vehre@gmx.de>

	PR fortran/60357
	* primary.c (build_actual_constructor): Prevent warning.
	* trans-expr.c (alloc_scalar_allocatable_for_subcomponent_
	assignment): New function encapsulates treatment of allocatable
	components.
	(gfc_trans_subcomponent_assign): Needed to distinguish between
	regular assignment and initilization.
	(gfc_trans_structure_assign): Same.
	(gfc_conv_structure): Same.

	PR fortran/61275
	* gfortran.h: deferred_parameter is not needed, because
	it artificial does the trick completely.
	* primary.c (build_actual_constructor): Same.
	(gfc_convert_to_structure_constructor): Same.
	* resolve.c (resolve_fl_derived0): Same.
	* trans-expr.c (gfc_conv_component_ref): Prevent treating
	allocatable deferred length char arrays here.
	(gfc_trans_subcomponent_assign): Same as above.
	* trans-types.c (gfc_sym_type): This is done in
	gfc_get_derived_type already.

2015-01-17  Andre Vehreschild  <vehre@gmx.de>

	PR fortran/60357
	* gfortran.dg/alloc_comp_assign_13.f08: New test.

	PR fortran/61275
	* gfortran.dg/alloc_comp_assign_14.f08: New test.

	PR fortran/55932
	* gfortran.dg/alloc_comp_initializer_4.f03: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_assign_13.f08
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_assign_14.f08
    trunk/gcc/testsuite/gfortran.dg/alloc_comp_initializer_4.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/primary.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-types.c
    trunk/gcc/testsuite/ChangeLog
Comment 14 vehre 2015-01-26 10:57:28 UTC
IMHO does the supplied patch fix all issues discussed in this pr. I therefore close it. 

Feel free to reopen and assign it to me, when you find some issue not addressed.