Bug 36132

Summary: _gfortran_internal_pack on optional arguments
Product: gcc Reporter: Joost VandeVondele <Joost.VandeVondele>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: burnus, gcc-bugs, tkoenig
Priority: P3 Keywords: wrong-code
Version: 4.4.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2008-05-20 15:18:15
Bug Depends on:    
Bug Blocks: 29975    

Description Joost VandeVondele 2008-05-05 13:24:32 UTC
the following testcase, derived from CP2K, illustrates an issue with _gfortran_internal_pack. In CP2K this causes crashes such as:

Operating system error: Cannot allocate memory
Memory allocation failed

while this testcase shows under valgrind:

> gfortran -g -O0 test.f90

> valgrind --tool=memcheck ./a.out
==21339== Memcheck, a memory error detector.
==21339== Copyright (C) 2002-2007, and GNU GPL'd, by Julian Seward et al.
==21339== Using LibVEX rev 1732, a library for dynamic binary translation.
==21339== Copyright (C) 2004-2007, and GNU GPL'd, by OpenWorks LLP.
==21339== Using valgrind-3.2.3, a dynamic binary instrumentation framework.
==21339== Copyright (C) 2000-2007, and GNU GPL'd, by Julian Seward et al.
==21339== For more details, rerun with: -v
==21339==
==21339== Conditional jump or move depends on uninitialised value(s)
==21339==    at 0x4BF449B: _gfortran_internal_pack (in_pack_generic.c:56)
==21339==    by 0x4008BC: __m1_MOD_s2 (test.f90:12)
==21339==    by 0x400967: MAIN__ (test.f90:17)
==21339==    by 0x40099B: main (fmain.c:21)
==21339==
==21339== Conditional jump or move depends on uninitialised value(s)
==21339==    at 0x4008FA: __m1_MOD_s2 (test.f90:12)
==21339==    by 0x400967: MAIN__ (test.f90:17)
==21339==    by 0x40099B: main (fmain.c:21)
Comment 1 Joost VandeVondele 2008-05-05 13:25:05 UTC
testcase:

MODULE M1
  INTEGER, PARAMETER :: dp=KIND(0.0D0)
CONTAINS
  SUBROUTINE S1(a)
         REAL(dp), DIMENSION(45), INTENT(OUT), &
      OPTIONAL                               :: a
      IF (PRESENT(a)) a=0.0_dp
  END SUBROUTINE S1
  SUBROUTINE S2(a)
          REAL(dp), DIMENSION(:, :), INTENT(OUT), &
      OPTIONAL                               :: a
      CALL S1(a)
  END SUBROUTINE
END MODULE M1
USE M1
REAL(dp) :: a(5,9)
CALL S2()
END
Comment 2 Tobias Burnus 2008-05-05 13:46:11 UTC
I have probably a too old gfortran 4.4.0 (namely 20080424), but it does not crash here. I see the same valgrind output using gfortran 4.1, 4.2, 4.3 and 4.4.
Comment 3 Joost VandeVondele 2008-05-05 15:28:44 UTC
right, it is actually new CP2K code since I checked 4.3. No regression thus.
Comment 4 Thomas Koenig 2008-05-05 18:57:28 UTC
The problem isn't specific to in_pack, it's the
fact that we don't initialize the array descriptor
correctly.

s2 shows

  if (a != 0B)
    {
      {
        integer(kind=4) D.638;

        D.638 = a->dim[0].stride;
        stride.1 = D.638 != 0 ? D.638 : 1;
   
        ...
      }
    }
so we set stride.1 only if a is present.  So far, so good.

Later, unconditionally, we have

    struct array2_real(kind=8) parm.6;

...

    D.633 = stride.1;
    parm.6.dim[0].lbound = 1;
    parm.6.dim[0].ubound = ubound.0;
    parm.6.dim[0].stride = NON_LVALUE_EXPR <D.633>;
    parm.6.data = (void *) &(*a.0)[0];
    parm.6.offset = NON_LVALUE_EXPR <D.632>;
    D.635 = _gfortran_internal_pack (&parm.6);

We need to call _gfortran_internal_pack on optional arguments
only when the optional arguments are present.

Setting subject.
Comment 5 Joost VandeVondele 2008-05-20 06:45:27 UTC
this seems one of the few wrong-code bugs that affects Fortran95 in a system independent way. Any chance to fix this, with a backport to 4.3(.2) ? I believe we could try to code around it for new versions of CP2K, but that would just be CP2K. I would guess that the fix is very localized and 'obvious'.
Comment 6 Francois-Xavier Coudert 2008-05-20 15:18:12 UTC
(In reply to comment #5)
> this seems one of the few wrong-code bugs that affects Fortran95 in a system
> independent way. Any chance to fix this, with a backport to 4.3(.2) ? I believe
> we could try to code around it for new versions of CP2K, but that would just be
> CP2K. I would guess that the fix is very localized and 'obvious'.

This is not a regression, but I guess as you that the fix should be simple, so why not? I'll look into it.
Comment 7 Francois-Xavier Coudert 2008-06-15 15:13:35 UTC
This is an important bug indeed, and I'm swamped with work, so I'd better leave it to someone else.
Comment 8 Tobias Burnus 2008-06-16 18:08:43 UTC
Pointer for myself (or someone else): Should be added in trans-array.c's gfc_conv_array_parameter and maybe also gfc_trans_dummy_array_bias.
Comment 9 Joost VandeVondele 2008-07-25 10:20:15 UTC
Any plans to look into a fix for this for 4.3.X ?  This is variant of the testcase that causes a runtime abort (trunk on x86_64-unknown-linux-gnu):

> gfortran -O2 test.f90 ; ./a.out
Operating system error: Cannot allocate memory
Memory allocation failed

> cat test.f90
MODULE M1
  INTEGER, PARAMETER :: dp=KIND(0.0D0)
CONTAINS
  SUBROUTINE S0()
    REAL(dp) :: a(5,9,3,5)
    CALL S1(a)
  END SUBROUTINE
  SUBROUTINE S1(a)
         REAL(dp), DIMENSION(45), INTENT(OUT), &
      OPTIONAL                               :: a
      IF (PRESENT(a)) CALL RANDOM_NUMBER(a)
  END SUBROUTINE S1
  SUBROUTINE S2(a)
          REAL(dp), DIMENSION(:, :), INTENT(OUT), &
      OPTIONAL                               :: a
      CALL S1(a)
  END SUBROUTINE
END MODULE M1
USE M1

CALL S0()
CALL S2()
END
Comment 10 Tobias Burnus 2008-07-27 10:46:40 UTC
Subject: Bug 36132

Author: burnus
Date: Sun Jul 27 10:45:44 2008
New Revision: 138186

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=138186
Log:
2008-07-27  Tobias Burnus  <burnus@net-b.de>

        PR fortran/36132
        PR fortran/29952
        PR fortran/36909
        * trans.c (gfc_trans_runtime_check): Allow run-time warning
        * besides
        run-time error.
        * trans.h (gfc_trans_runtime_check): Update declaration.
        * trans-array.c
        * (gfc_trans_array_ctor_element,gfc_trans_array_bound_check,
        gfc_conv_array_ref,gfc_conv_ss_startstride,gfc_trans_dummy_array_bias):
        Updated gfc_trans_runtime_check calls.
        (gfc_conv_array_parameter): Implement flag_check_array_temporaries,
        fix packing/unpacking for nonpresent optional actuals to optional
        formals.
        * trans-array.h (gfc_conv_array_parameter): Update declaration.
        * trans-expr.c (gfc_conv_substring,gfc_trans_arrayfunc_assign,
        gfc_conv_function_call): Updated gfc_trans_runtime_check calls.
        (gfc_conv_function_call): Update gfc_conv_array_parameter calls.
        * trans-expr.c (gfc_trans_goto): Updated gfc_trans_runtime_check
        calls.
        * trans-io.c (set_string,gfc_conv_intrinsic_repeat): Ditto.
        (gfc_conv_intrinsic_transfer,gfc_conv_intrinsic_loc): Same for
        gfc_conv_array_parameter.
        * trans-intrinsics.c (gfc_conv_intrinsic_bound): Ditto.
        * trans-decl.c (gfc_build_builtin_function_decls): Add
        gfor_fndecl_runtime_warning_at.
        * lang.opt: New option fcheck-array-temporaries.
        * gfortran.h (gfc_options): New flag_check_array_temporaries.
        * options.c (gfc_init_options, gfc_handle_option): Handle flag.
        * invoke.texi: New option fcheck-array-temporaries.

2008-07-27  Tobias Burnus  <burnus@net-b.de>

        PR fortran/36132
        PR fortran/29952
        PR fortran/36909
        * runtime/error.c: New function runtime_error_at.
        * gfortran.map: Ditto.
        * libgfortran.h: Ditto.

2008-07-27  Tobias Burnus  <burnus@net-b.de>

        PR fortran/36132
        PR fortran/29952
        PR fortran/36909
        gfortran.dg/internal_pack_4.f90: New.
        gfortran.dg/internal_pack_5.f90: New.
        gfortran.dg/array_temporaries_2.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/array_temporaries_2.f90
    trunk/gcc/testsuite/gfortran.dg/internal_pack_4.f90
    trunk/gcc/testsuite/gfortran.dg/internal_pack_5.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/invoke.texi
    trunk/gcc/fortran/lang.opt
    trunk/gcc/fortran/options.c
    trunk/gcc/fortran/trans-array.c
    trunk/gcc/fortran/trans-array.h
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/fortran/trans-intrinsic.c
    trunk/gcc/fortran/trans-io.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/fortran/trans.c
    trunk/gcc/fortran/trans.h
    trunk/gcc/testsuite/ChangeLog
    trunk/libgfortran/ChangeLog
    trunk/libgfortran/gfortran.map
    trunk/libgfortran/libgfortran.h
    trunk/libgfortran/runtime/error.c

Comment 11 Tobias Burnus 2008-07-27 11:42:22 UTC
Subject: Bug 36132

Author: burnus
Date: Sun Jul 27 11:41:35 2008
New Revision: 138187

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=138187
Log:
2008-07-27  Tobias Burnus  <burnus@net-b.de>

       PR fortran/36132
       * trans-array.c (gfc_conv_array_parameter): Fix packing/unpacking
       for nonpresent optional actuals to optional formals.
       * trans-array.h (gfc_conv_array_parameter): Update declaration.
       * trans-expr.c (gfc_conv_function_call,gfc_trans_arrayfunc_assign):
       Update gfc_conv_array_parameter calls.
       * trans-intrinsics (gfc_conv_intrinsic_transfer,
       gfc_conv_intrinsic_loc): Ditto.

2008-07-27  Tobias Burnus  <burnus@net-b.de>

       PR fortran/36132
       * gfortran.dg/internal_pack_4.f90: New.


Added:
    branches/gcc-4_3-branch/gcc/testsuite/gfortran.dg/internal_pack_4.f90
Modified:
    branches/gcc-4_3-branch/gcc/fortran/ChangeLog
    branches/gcc-4_3-branch/gcc/fortran/trans-array.c
    branches/gcc-4_3-branch/gcc/fortran/trans-array.h
    branches/gcc-4_3-branch/gcc/fortran/trans-expr.c
    branches/gcc-4_3-branch/gcc/fortran/trans-intrinsic.c
    branches/gcc-4_3-branch/gcc/testsuite/ChangeLog

Comment 12 Tobias Burnus 2008-07-27 11:47:01 UTC
FIXED on the trunk and on the 4.3 branch. Thanks for the bug report.