Fortran: Correct missing structure constructor comps. [PR97612].
authorPaul Thomas <pault@gcc.gnu.org>
Tue, 29 Dec 2020 17:44:48 +0000 (17:44 +0000)
committerPaul Thomas <pault@gcc.gnu.org>
Tue, 29 Dec 2020 17:44:48 +0000 (17:44 +0000)
2020-12-29  Paul Thomas  <pault@gcc.gnu.org>

gcc/fortran
PR fortran/97612
* primary.c (build_actual_constructor): Missing allocatable
components are set unallocated using EXPR_NULL. Then missing
components are tested for a default initializer.

gcc/testsuite/
PR fortran/97612
* gfortran.dg/structure_constructor_17.f90: New test.

gcc/fortran/primary.c
gcc/testsuite/gfortran.dg/structure_constructor_17.f90 [new file with mode: 0644]

index a58a25924daf1112ce9c70f52ba091257d4875fc..93d74737284b9bc7a89acab7ad91cbecf72569d8 100644 (file)
@@ -3003,26 +3003,36 @@ build_actual_constructor (gfc_structure_ctor_component **comp_head,
          continue;
        }
 
-      /* If it was not found, try the default initializer if there's any;
+      /* If it was not found, apply NULL expression to set the component as
+        unallocated. Then try the default initializer if there's any;
         otherwise, it's an error unless this is a deferred parameter.  */
       if (!comp_iter)
        {
-         if (comp->initializer)
-           {
-             if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
-                                  "with missing optional arguments at %C"))
-               return false;
-             value = gfc_copy_expr (comp->initializer);
-           }
-         else if (comp->attr.allocatable
-                  || (comp->ts.type == BT_CLASS
-                      && CLASS_DATA (comp)->attr.allocatable))
+         /* F2018 7.5.10: If an allocatable component has no corresponding
+            component-data-source, then that component has an allocation
+            status of unallocated....  */
+         if (comp->attr.allocatable
+             || (comp->ts.type == BT_CLASS
+                 && CLASS_DATA (comp)->attr.allocatable))
            {
              if (!gfc_notify_std (GFC_STD_F2008, "No initializer for "
                                   "allocatable component %qs given in the "
                                   "structure constructor at %C", comp->name))
                return false;
+             value = gfc_get_null_expr (&gfc_current_locus);
+           }
+         /* ....(Preceeding sentence) If a component with default
+            initialization has no corresponding component-data-source, then
+            the default initialization is applied to that component.  */
+         else if (comp->initializer)
+           {
+             if (!gfc_notify_std (GFC_STD_F2003, "Structure constructor "
+                                  "with missing optional arguments at %C"))
+               return false;
+             value = gfc_copy_expr (comp->initializer);
            }
+         /* Do not trap components such as the string length for deferred
+            length character components.  */
          else if (!comp->attr.artificial)
            {
              gfc_error ("No initializer for component %qs given in the"
diff --git a/gcc/testsuite/gfortran.dg/structure_constructor_17.f90 b/gcc/testsuite/gfortran.dg/structure_constructor_17.f90
new file mode 100644 (file)
index 0000000..8b8230c
--- /dev/null
@@ -0,0 +1,21 @@
+! { dg-do compile }
+!
+! Test the fix for PR97612.
+!
+! Contributed by Martin Stein  <mscfd@gmx.net>
+!
+program constructor_allocatable
+  implicit none
+
+  type :: s
+    integer, dimension(:), allocatable :: u
+  end type s
+
+  type :: t
+    type(s), dimension(:), allocatable :: x
+  end type t
+
+  type(t) :: a = t()
+  if (allocated (a%x)) stop 1
+
+end program constructor_allocatable