Bug 46325 - [4.6 Regression] gfortran.dg/char_initialiser_actual.f90 FAILs with -fstack-protector
Summary: [4.6 Regression] gfortran.dg/char_initialiser_actual.f90 FAILs with -fstack-p...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.0
: P4 normal
Target Milestone: 4.6.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2010-11-05 23:54 UTC by Zdenek Sojka
Modified: 2010-11-11 23:03 UTC (History)
3 users (show)

See Also:
Host: x86_64-pc-linux-gnu
Target: x86_64-pc-linux-gnu
Build:
Known to work: 4.4.6, 4.5.2
Known to fail: 4.6.0
Last reconfirmed: 2010-11-06 03:30:06


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Zdenek Sojka 2010-11-05 23:54:27 UTC
Output:
$ gfortran char_initialiser_actual.f90 -fstack-protector
$ ./a.out 
Aborted

Tested revisions:
r166306 - fail
r165699 - fail
r163636 - OK
4.5 r165781 - OK
Comment 1 H.J. Lu 2010-11-06 03:30:06 UTC
It is caused by revision 165240:

http://gcc.gnu.org/ml/gcc-cvs/2010-10/msg00423.html
Comment 2 Jakub Jelinek 2010-11-10 16:07:32 UTC
The problem is that we choose to put A.19 and parm.22 into the same partition:

;; Function char_initialiser (MAIN__)
                
Partition 0: size 15 align 16
        x, offset 0
Partition 5: size 48 align 16
        parm.22, offset 0
        A.19, offset 0
Partition 3: size 48 align 16
        atmp.18, offset 0
Partition 4: size 48 align 16
        ptrtemp.16, offset 0
Partition 1: size 48 align 16
        y, offset 0

But A.19 is live until the end of function:
  D.1613_7 = (void * restrict) &A.19[0][1]{lb: 1 sz: 1};
  atmp.18.data = D.1613_7;
...
  D.1596_13 = &atmp.18;
...
  pfoo (&ptrtemp.16, 5, D.1596_13, 5);
  y = ptrtemp.16;
  parm.22.dtype = 369;
  parm.22.dim[0].lbound = 1;
  parm.22.dim[0].ubound = 3;
  parm.22.dim[0].stride = 1;
  parm.22.data = &x[0];
  parm.22.offset = -1;
  afoo (&y, &parm.22, 5, 5);
  return;
and thus when it is shared with parm.22 it is overwritten.

I'm using a reduced testcase:
program char_initialiser
  character*5, dimension(3) :: x
  character*5, dimension(:), pointer :: y
  x=(/"is Ja","ne Fo","nda  "/)
  y => pfoo ((/"is Ja","ne Fo","nda  "/))
  call afoo (y, x)
contains
  subroutine afoo(ch1, ch2)
     character*(*), dimension(:) :: ch1, ch2
     if (any(ch1 /= ch2)) call abort ()
  end subroutine afoo
  function pfoo(ch2)
     character*5, dimension(:), target  :: ch2
     character*5, dimension(:), pointer :: pfoo
     pfoo => ch2
  end function pfoo
end program

If this is actually valid Fortran (i.e. the lifetime of
(/"is Ja","ne Fo","nda  "/)
when passed as actual argument to pfoo doesn't end with the return from pfoo), then it would be a Fortran FE bug - A.19 which is used as the data area for the
atmp.18 temporary whose address is passed to pfoo, is declared in a BLOCK which starts before atmp.18 definition but doesn't end at the end of function, but right after y = ptrtemp.16; stmt (and parm.22 correctly starts living just for the setup of afoo parameters and lives over the actual afoo call.  Thus there is nothing wrong on the expansion side that it decided to coalesce the two variables, it is either a FE bug or invalid testcase.

-fdump-tree-origin contains:

...
  {
    integer(kind=8) D.1598;
    character(kind=1)[0:][1:5] * ifm.21;
    struct array1_unknown * D.1596;
    character(kind=1) A.19[3][1:5];
    struct array1_unknown atmp.18;
    static character(kind=1)[1:5] * A.17[3] = {&"is Ja"[1]{lb: 1 sz: 1}, &"ne Fo"[1]{lb: 1 sz: 1}, &"nda  "[1]{lb: 1 sz: 1}};
    struct array1_unknown ptrtemp.16;

    atmp.18.dtype = 369;
    atmp.18.dim[0].stride = 1;
    atmp.18.dim[0].lbound = 0;
    atmp.18.dim[0].ubound = 2;
    atmp.18.data = (void * restrict) &A.19;
    atmp.18.offset = 0;
    {
      integer(kind=8) S.20;

      S.20 = 0;
      while (1)
        {
          if (S.20 > 2) goto L.5;
          __builtin_memmove ((void *) &(*(character(kind=1)[3][1:5] * restrict) atmp.18.data)[S.20], (void *) A.17[S.20], 5);
          S.20 = S.20 + 1;
        }
      L.5:;
    }
    D.1596 = &atmp.18;
    ifm.21 = (character(kind=1)[0:][1:5] *) D.1596->data;
    D.1598 = (D.1596->dim[0].ubound - D.1596->dim[0].lbound) + 1;
    pfoo (&ptrtemp.16, 5, D.1596, 5);
    y = ptrtemp.16;
  }
  {
    struct array1_unknown parm.22;

    parm.22.dtype = 369;
    parm.22.dim[0].lbound = 1;
    parm.22.dim[0].ubound = 3;
    parm.22.dim[0].stride = 1;
    parm.22.data = (void *) &x[0];
    parm.22.offset = -1;
    afoo (&y, &parm.22, 5, 5);
  }
Comment 3 Jakub Jelinek 2010-11-10 16:11:21 UTC
BTW, even 4.4 has the character(kind=1) A.20[3][1:5]; var referenced into the actual arg to pfoo in a block which doesn't overlap the block of the afoo call.
Comment 4 Tobias Burnus 2010-11-11 21:58:42 UTC
(In reply to comment #2)
> If this is actually valid Fortran

Short answer: The reduced test program in comment 2 is invalid according to the Fortran standard. Long answer below.


> program char_initialiser
>   character*5, dimension(3) :: x
>   character*5, dimension(:), pointer :: y
>   x=(/"is Ja","ne Fo","nda  "/)

So far so good. "y" is a pointer and "x" is a nonpointer, nontarget which thus may not alias.


>   y => pfoo ((/"is Ja","ne Fo","nda  "/))

By itself, it looks valid.


>   function pfoo(ch2)
>      character*5, dimension(:), target  :: ch2
>      character*5, dimension(:), pointer :: pfoo
>      pfoo => ch2
>   end function pfoo

Also this function looks valid as "ch2" is a target (at least in the scope of "pfoo"). However, as the actual argument associated with "pfoo" (namely "x") is not a target, the pointer "pfoo" has the pointer associations status "undefined" after "pfoo" -- that's still valid. Thus:

  y => pfoo ((/"is Ja","ne Fo","nda  "/))

is equivalent to

  y => <undefined pointer>

However, the following line is invalid:
    call afoo (y, x)
as the dummy arguments of "afoo" are not pointers and "y" has the status undefined.


To put this in some legalize by quoting from Fortran 2008:

"12.5.2.4 Ordinary dummy variables" [...] "If the dummy argument has the TARGET attribute and the effective argument does not have the TARGET attribute or is an array section with a vector subscript, any pointers associated with the dummy argument become undefined when execution of the procedure completes."

And: "7.1.9.2 Type, type parameters, and shape of a primary"
"If the pointer is not associated with a target, it may appear as a primary only as an actual argument in a reference to a procedure whose corresponding
dummy argument is declared to be a pointer, or as the target in a pointer assignment statement."
Comment 5 Jakub Jelinek 2010-11-11 22:18:35 UTC
(In reply to comment #4)
> >   y => pfoo ((/"is Ja","ne Fo","nda  "/))
> 
> However, as the actual argument associated with "pfoo" (namely "x") is
> not a target

Well, the actual argument associated with pfoo here is not x but
(/"is Ja","ne Fo","nda  "/)
but if the same thing applies to it too, then the gfortran.dg/char_initialiser_actual.f90 testcase is invalid too and thus should be nuked.
Comment 6 Tobias Burnus 2010-11-11 22:32:26 UTC
(In reply to comment #5)
> Well, the actual argument associated with pfoo here is not x but
> (/"is Ja","ne Fo","nda  "/)

Well, the effective argument nevertheless does not have the TARGET attribute. Thus I believe the same argument applies and the test case is invalid.

>  y => <undefined pointer>

Actually, already that line is invalid (per 7.1.9.2).

> but if the same thing applies to it too, then the
> gfortran.dg/char_initialiser_actual.f90 testcase is invalid too and thus should
> be nuked.

Well, not nuked but modified:

@@ -26,3 +26,4 @@ contains
      character*5, dimension(:), pointer :: pfoo
-     pfoo => ch2
+     allocate(pfoo(size(ch2)))
+     pfoo = ch2
   end function pfoo
Comment 7 Tobias Burnus 2010-11-11 23:02:10 UTC
Author: burnus
Date: Thu Nov 11 23:02:03 2010
New Revision: 166628

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=166628
Log:
2010-11-11  Jakub Jelinek <jakub@redhat.com>
            Tobias Burnus <burnus@net-b.de>

    PR fortran/46325
    * gfortran.dg/char_initialiser_actual.f90: Make test case valid. 

Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/char_initialiser_actual.f90
Comment 8 Tobias Burnus 2010-11-11 23:03:43 UTC
Close as FIXED.

Thanks Zdenek for the report and thanks Jakub for the analysis.