User account creation filtered due to spam.

Bug 49110 - Deferred-length character result triggers (false positive) error for pure procedures
Summary: Deferred-length character result triggers (false positive) error for pure pro...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.6.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks: 45170
  Show dependency treegraph
 
Reported: 2011-05-22 15:17 UTC by John
Modified: 2012-05-14 16:46 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Test case (264 bytes, text/plain)
2011-05-22 16:13 UTC, John
Details
Test case with main unit (467 bytes, text/plain)
2011-05-22 16:57 UTC, John
Details

Note You need to log in before you can comment on or make changes to this bug.
Description John 2011-05-22 15:17:34 UTC
The use of a deferred-length character variable as a function result triggers a (false positive) error for pure procedures.  For example, the following module:

module mod1
    use iso_c_binding
    implicit none

contains
    pure function c2fstring(cbuffer) result(string)
        character(:), allocatable :: string
        character(KIND = C_CHAR), intent(IN) :: cbuffer(:)
        integer :: i

    continue
        string = REPEAT(' ', SIZE(cbuffer))

        do i = 1, SIZE(cbuffer)
            if (cbuffer(i) == C_NULL_CHAR) exit
            string(i:i) = cbuffer(i)
        enddo

        string = TRIM(string)
    end function
end module mod1


When compiled, the error thrown is:

...:~$ gfortran -c test_gfortran_pure.f90 
test_gfortran_pure.f90:4.4:

    pure function c2fstring(cbuffer) result(string)
    1
Error: CHARACTER(*) function 'c2fstring' at (1) cannot be pure


The module compiles just fine with ifort v12.0.4 (command line: ifort -c -stand test_gfortran_pure.f90).

The version information is:

...:~$ gfortran -v
Using built-in specs.
COLLECT_GCC=gfortran
COLLECT_LTO_WRAPPER=/usr/lib/x86_64-linux-gnu/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.6.0-3~ppa1' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-multiarch --with-multiarch-defaults=x86_64-linux-gnu --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib/x86_64-linux-gnu --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib/x86_64-linux-gnu --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.1 20110409 (prerelease) (Ubuntu 4.6.0-3~ppa1) 


The system information (for Ubuntu 11.04) is:

...:~$ uname -srvmpio
Linux 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
Comment 1 John 2011-05-22 16:13:49 UTC
Created attachment 24327 [details]
Test case
Comment 2 kargl 2011-05-22 16:32:51 UTC
This patch allows your code to compile, but I 
don't know if it works correctly.  Do you have
a complete self-contained small testcase?

Index: resolve.c
===================================================================
--- resolve.c   (revision 173757)
+++ resolve.c   (working copy)
@@ -10305,7 +10305,7 @@ resolve_fl_procedure (gfc_symbol *sym, i
      actual length; (ii) To declare a named constant; or (iii) External
      function - but length must be declared in calling scoping unit.  */
   if (sym->attr.function
-      && sym->ts.type == BT_CHARACTER
+      && sym->ts.type == BT_CHARACTER && !sym->ts.deferred
       && sym->ts.u.cl && sym->ts.u.cl->length == NULL)
     {
       if ((sym->as && sym->as->rank) || (sym->attr.pointer)
Comment 3 John 2011-05-22 16:45:09 UTC
(In reply to comment #2)
> This patch allows your code to compile, but I 
> don't know if it works correctly.  Do you have
> a complete self-contained small testcase?
> 
> Index: resolve.c
> ===================================================================
> --- resolve.c   (revision 173757)
> +++ resolve.c   (working copy)
> @@ -10305,7 +10305,7 @@ resolve_fl_procedure (gfc_symbol *sym, i
>       actual length; (ii) To declare a named constant; or (iii) External
>       function - but length must be declared in calling scoping unit.  */
>    if (sym->attr.function
> -      && sym->ts.type == BT_CHARACTER
> +      && sym->ts.type == BT_CHARACTER && !sym->ts.deferred
>        && sym->ts.u.cl && sym->ts.u.cl->length == NULL)
>      {
>        if ((sym->as && sym->as->rank) || (sym->attr.pointer)

The module shown is self-contained (it only depends on iso_c_binding, which is an intrinsic module).  I've added the corresponding source file to this bug as an attachment.
Comment 4 John 2011-05-22 16:46:32 UTC
(In reply to comment #2)
> This patch allows your code to compile, but I 
> don't know if it works correctly.  Do you have
> a complete self-contained small testcase?
> 
> Index: resolve.c
> ===================================================================
> --- resolve.c   (revision 173757)
> +++ resolve.c   (working copy)
> @@ -10305,7 +10305,7 @@ resolve_fl_procedure (gfc_symbol *sym, i
>       actual length; (ii) To declare a named constant; or (iii) External
>       function - but length must be declared in calling scoping unit.  */
>    if (sym->attr.function
> -      && sym->ts.type == BT_CHARACTER
> +      && sym->ts.type == BT_CHARACTER && !sym->ts.deferred
>        && sym->ts.u.cl && sym->ts.u.cl->length == NULL)
>      {
>        if ((sym->as && sym->as->rank) || (sym->attr.pointer)

The module shown is self-contained (it only depends on iso_c_binding, which is an intrinsic module).  I've added the corresponding source file to this bug as an attachment.
Comment 5 John 2011-05-22 16:57:02 UTC
Created attachment 24331 [details]
Test case with main unit
Comment 6 Steve Kargl 2011-05-22 17:11:03 UTC
On Sun, May 22, 2011 at 04:57:44PM +0000, jwmwalrus at gmail dot com wrote:
> > This patch allows your code to compile, but I 
> > don't know if it works correctly.  Do you have
> > a complete self-contained small testcase?
> > 
> 
> The module shown is self-contained (it only depends on iso_c_binding, which is
> an intrinsic module).  I've added the corresponding source file to this bug as
> an attachment.
> 

That's no what I meant.  Obviously, I already stated
the patch allowed me compile your code.

Do you have a COMPLETE self-contained testcase?  As in

program foo
   use mod1
   DO SOMETHING HERE TO USE c2fstring()
end program foo
Comment 7 John 2011-05-22 17:24:07 UTC
(In reply to comment #6)
> On Sun, May 22, 2011 at 04:57:44PM +0000, jwmwalrus at gmail dot com wrote:
> > > This patch allows your code to compile, but I 
> > > don't know if it works correctly.  Do you have
> > > a complete self-contained small testcase?
> > > 
> > 
> > The module shown is self-contained (it only depends on iso_c_binding, which is
> > an intrinsic module).  I've added the corresponding source file to this bug as
> > an attachment.
> > 
> 
> That's no what I meant.  Obviously, I already stated
> the patch allowed me compile your code.
> 
> Do you have a COMPLETE self-contained testcase?  As in
> 
> program foo
>    use mod1
>    DO SOMETHING HERE TO USE c2fstring()
> end program foo

Sorry for the double post (I now know the effect of the refresh button on Bugzilla).

As I said, the source code is attached (the label is "Test case with main unit", the name of the file is test_gfortran_pure_main.f90).
Comment 8 kargl 2011-05-22 18:35:37 UTC
I think the subject line is incorrect.  The following testcase
that gets rid of the C interop garbage, works for an input
array of characters with an explicit-shape, but fails with
an assumed-shape array.

program foo

   implicit none

   character s(5)

   s = ['a', 'b', 'c', 'd', 'e']
   print *, bar(s)

   contains

      pure function bar(s) result(a)
!         character, intent(in) :: s(5)       ! Compiles and runs
         character, intent(in) :: s(:)        ! Compiles and segfaults
         character(len=:), allocatable :: a
         integer i
         a = repeat('a', size(s))
         do i = 1, size(s)
            a(i:i) = s(i)
         end do
      end function bar

end program foo

The following workaround allows the original code to compile and
run.


   function c2fstring(cbuffer) result(string)

      character(:), allocatable :: string
      character(KIND = C_CHAR), intent(IN) :: cbuffer(255)

      character(len=255) s
      integer :: i

      s = ''
      do i = 1, SIZE(cbuffer)
         if (cbuffer(i) == C_NULL_CHAR) exit
         s(i:i) = cbuffer(i)
      end do
      string = TRIM(s)

    end function
Comment 9 kargl 2011-05-22 19:00:06 UTC
Note the routine need not be pure to invoke the segfault.  Here's
an even  shorter test case.

program foo
   implicit none
   character s(5)
   s = ['a', 'b', 'c', 'd', 'e']
   print *, bar(s)
   contains
      function bar(s) result(a)
!         character, intent(in) :: s(5)       ! Compiles and runs
         character, intent(in) :: s(:)        ! Compiles and segfaults
         character(len=:), allocatable :: a
         a = repeat('a', size(s))
      end function bar
end program foo
Comment 10 John 2011-05-22 19:36:33 UTC
(In reply to comment #9)
> Note the routine need not be pure to invoke the segfault.  Here's
> an even  shorter test case.
> 
> program foo
>    implicit none
>    character s(5)
>    s = ['a', 'b', 'c', 'd', 'e']
>    print *, bar(s)
>    contains
>       function bar(s) result(a)
> !         character, intent(in) :: s(5)       ! Compiles and runs
>          character, intent(in) :: s(:)        ! Compiles and segfaults
>          character(len=:), allocatable :: a
>          a = repeat('a', size(s))
>       end function bar
> end program foo

My bug report is actually about the fact that the "pure" attribute triggers an (incorrect) error, and that error is associated to the deferred-length character result.  The code compiles just fine by removing the "pure" attribute from the original code... Or by changing "character(:), allocatable :: string" to something like "character(2047) :: string".

So I guess the subject line is fine.

The reason why I used interoperability with C, is because the module is just a reduced version of the actual, practical case that triggered the error ---sorry if it's "garbage" to you.
Comment 11 Dominique d'Humieres 2011-05-22 20:46:56 UTC
This PR seems related to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45170#c9 .
Comment 12 Steve Kargl 2011-05-22 21:30:07 UTC
On Sun, May 22, 2011 at 08:03:32PM +0000, jwmwalrus at gmail dot com wrote:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=49110
> 
> --- Comment #10 from John <jwmwalrus at gmail dot com> 2011-05-22 19:36:33 UTC ---
> (In reply to comment #9)
> > Note the routine need not be pure to invoke the segfault.  Here's
> > an even  shorter test case.
> > 
> > program foo
> >    implicit none
> >    character s(5)
> >    s = ['a', 'b', 'c', 'd', 'e']
> >    print *, bar(s)
> >    contains
> >       function bar(s) result(a)
> > !         character, intent(in) :: s(5)       ! Compiles and runs
> >          character, intent(in) :: s(:)        ! Compiles and segfaults
> >          character(len=:), allocatable :: a
> >          a = repeat('a', size(s))
> >       end function bar
> > end program foo
> 
> My bug report is actually about the fact that the "pure" attribute
> triggers an (incorrect) error, and that error is associated to the
> deferred-length character result.

Sigh.  I already told you that my patch in Comment #2 
fixes the errant error message.  That does not fix the
more important bug that is exposed when the errant
error message is suppressed.  With my patch in Comment #2,
and without touching your source code, I get

laptop:kargl[228] gfc4x -o z -fno-backtrace test_gfortran_pure_main.f90 && ./z
Segmentation fault (core dumped)

> The reason why I used interoperability with C, is because the
> module is just a reduced version of the actual, practical case
>  that triggered the error ---sorry if it's "garbage" to you.

The C interop stuff is garbage in that it makes it much
more difficult to diagnosis and fix the real bug.

Your free to apply my patch gcc, build new gfortran, and use it
to compile and run your code.

I shalt spend anymore time on this PR.
Comment 13 Tobias Burnus 2012-01-02 18:53:47 UTC
(In reply to comment #9)
> !         character, intent(in) :: s(5)       ! Compiles and runs
>          character, intent(in) :: s(:)        ! Compiles and segfaults
>          character(len=:), allocatable :: a
>          a = repeat('a', size(s))

For that example, try:
  a = ( repeat('a', size(s)) )
Cf. PR 51055.
Comment 14 Tobias Burnus 2012-05-12 09:54:00 UTC
Author: burnus
Date: Sat May 12 09:53:53 2012
New Revision: 187427

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=187427
Log:
2012-05-12  Tobias Burnus  <burnus@net-b.de>

        PR fortran/49110
        PR fortran/52843
        * resolve.c (resolve_fl_procedure): Don't regard
        character(len=:) as character(*) in the diagnostic.

2012-05-12  Tobias Burnus  <burnus@net-b.de>

        PR fortran/49110
        PR fortran/52843
        * gfortran.dg/deferred_type_param_5.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/deferred_type_param_5.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
Comment 15 Tobias Burnus 2012-05-12 09:59:10 UTC
The commit of comment 13 fixes the issue with the bogus PURE diagnostic.

Sorry that it took one year to get it fixed - and thanks for the bug report.

 * * *

Regarding the REPEAT issue (cf. comment 9 and PR 51055): A patch solving that issue has been posted at http://gcc.gnu.org/ml/fortran/2012-05/msg00054.html
Comment 16 Tobias Burnus 2012-05-14 16:45:31 UTC
Author: burnus
Date: Mon May 14 16:45:16 2012
New Revision: 187472

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=187472
Log:
2012-05-14  Tobias Burnus  <burnus@net-b.de>

        PR fortran/49110
        PR fortran/51055
        PR fortran/53329
        * trans-expr.c (gfc_trans_assignment_1): Fix allocation
        handling for assignment of function results to allocatable
        deferred-length strings.
        * trans-decl.c (gfc_create_string_length): For deferred-length
        module variables, include module name in the assembler name.
        (gfc_get_symbol_decl): Don't override the assembler name.

2012-05-14  Tobias Burnus  <burnus@net-b.de>

        PR fortran/49110
        PR fortran/51055
        PR fortran/53329
        * gfortran.dg/deferred_type_param_4.f90: New.
        * gfortran.dg/deferred_type_param_6.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/deferred_type_param_4.f90
    trunk/gcc/testsuite/gfortran.dg/deferred_type_param_6.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/testsuite/ChangeLog
Comment 17 Tobias Burnus 2012-05-14 16:46:20 UTC
The REPEAT issue has now also been FIXED on the trunk (4.8). Thanks for the patience.