Bug 29389 - Statement functions are not recognized as pure when they are
Summary: Statement functions are not recognized as pure when they are
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.2.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2006-10-08 20:47 UTC by Francois-Xavier Coudert
Modified: 2008-09-06 16:58 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-12-31 07:39:01


Attachments
Tentative patch (980 bytes, patch)
2006-10-31 00:09 UTC, Francois-Xavier Coudert
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Francois-Xavier Coudert 2006-10-08 20:47:43 UTC
The F95 standard says (12.6): "A pure procedure is [...] or (4) A statement function that references only pure functions." But gfortran doesn't like that:

$ cat a5.f90 
INTEGER :: st1,i,a(4) 
st1(i)=i*i*i 
FORALL(i=1:4) a(i)=st1(i) 
print *, a
print *, u(2)

contains
pure integer function u(x)
  integer,intent(in) :: x

  st2(i) = i*i
  u = st2(x)
end function

END 
$ gfortran a5.f90
 In file a5.f90:12

  u = st2(x)
     1
Error: Function reference to 'st2' at (1) is to a non-PURE procedure within a PURE procedure
 In file a5.f90:3

FORALL(i=1:4) a(i)=st1(i) 
                  1
Error: reference to non-PURE function 'st1' at (1) inside a FORALL block
Comment 1 Francois-Xavier Coudert 2006-10-31 00:09:56 UTC
Created attachment 12516 [details]
Tentative patch

This patch doesn't work :)

It's working fine except that the following code:

  implicit none
  INTEGER :: st1,i,a(4)
  st1(i)=i*i*g(i)
  !FORALL(i=1:4) a(i)=st1(i)
  print *, a
  print *, u(2)

contains

pure integer function u(x)
  integer :: st2, i
  integer,intent(in) :: x

  st2(i) = i*i
  u = st2(x)
end function

pure integer function f(x)
  integer,intent(in) :: x
  f = x
end function

integer function g(x)
  integer,intent(in) :: x
  g = x
end function
end

gives the erroneous error message:

 In file pr29389.f90:3

  st1(i)=i*i*g(i)
             1
Error: Function reference to 'g' at (1) is to a non-PURE procedure within a PURE procedure

When the statement function is resolved, gfc_current_ns points to u. I don't understand why.
Comment 2 Paul Thomas 2006-12-31 07:39:00 UTC
This is fixed by:

resolve.c:1429

static int
pure_function (gfc_expr * e, const char **name)
{
  int pure;

  /* This is the fix.  */
  if (e->expr_type == EXPR_FUNCTION
	&& e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION)
    return 1;

  if (e->value.function.esym)

The testcase should set i = 0 and test its value at the end of the main program, in order to demonstrate that there are no side-effects.

Regtests OK on amd64/Cygwin_NT

Paul
Comment 3 Paul Thomas 2007-01-15 08:16:38 UTC
Subject: Bug 29389

Author: pault
Date: Mon Jan 15 08:16:17 2007
New Revision: 120790

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=120790
Log:
2007-01-15  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/28172
	* trans-stmt.c (gfc_trans_call): If it does not have one, get
	a backend_decl for an alternate return.

	PR fortran/29389
	* resolve.c (pure_function): Statement functions are pure. Note
	that this will have to recurse to comply fully with F95.

	PR fortran/29712
	* resolve.c (resolve_function): Only a reference to the final
	dimension of an assumed size array is an error in an inquiry
	function.

	PR fortran/30283
	* resolve.c (resolve_function): Make sure that the function
	expression has a type.

2007-01-15  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/28172
	* gfortran.dg/altreturn_4.f90: New test.

	PR fortran/29389
	* gfortran.dg/stfunc_4.f90: New test.

	PR fortran/29712
	* gfortran.dg/bound_2.f90: Reinstate commented out line.
	* gfortran.dg/initialization_1.f90: Change warning.

	PR fortran/30283
	* gfortran.dg/specification_type_resolution_2.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/altreturn_4.f90
    trunk/gcc/testsuite/gfortran.dg/specification_type_resolution_2.f90
    trunk/gcc/testsuite/gfortran.dg/stfunc_4.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/bound_2.f90
    trunk/gcc/testsuite/gfortran.dg/initialization_1.f90

Comment 4 Paul Thomas 2007-01-15 08:19:33 UTC
 
> Author: pault
> Date: Mon Jan 15 08:16:17 2007
> New Revision: 120790

As pointed out by FX on the list, this patch does not quite do it yet:

The F95 standard says (12.6): "A pure procedure is [...] or (4) A statement function that references only pure functions." Not all statement functions are pure. Are you sure that check ("references only pure functions") is performed by your patch?

I'll do this asap.

Paul
Comment 5 Paul Thomas 2007-01-23 05:53:33 UTC
Subject: Bug 29389

Author: pault
Date: Tue Jan 23 05:53:14 2007
New Revision: 121077

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=121077
Log:
2007-01-23  Paul Thomas  <pault@gcc.gnu.org>

	Backports from trunk

	PR fortran/28172
	* trans-stmt.c (gfc_trans_call): If it does not have one, get
	a backend_decl for an alternate return.

	PR fortran/29389
	* resolve.c (pure_function): Statement functions are pure. Note
	that this will have to recurse to comply fully with F95.

	PR fortran/29712
	* resolve.c (resolve_function): Only a reference to the final
	dimension of an assumed size array is an error in an inquiry
	function.

	PR fortran/30283
	* resolve.c (resolve_function): Make sure that the function
	expression has a type.

2007-01-23  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/28172
	* gfortran.dg/altreturn_4.f90: New test.

	PR fortran/29389
	* gfortran.dg/stfunc_4.f90: New test.

	PR fortran/29712
	* gfortran.dg/bound_2.f90: Reinstate commented out line.
	* gfortran.dg/initialization_1.f90: Change warning.

	PR fortran/30283
	* gfortran.dg/specification_type_resolution_2.f90: New test.

Added:
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/altreturn_4.f90
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/specification_type_resolution_2.f90
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/stfunc_4.f90
Modified:
    branches/gcc-4_2-branch/gcc/fortran/ChangeLog
    branches/gcc-4_2-branch/gcc/fortran/resolve.c
    branches/gcc-4_2-branch/gcc/fortran/trans-stmt.c
    branches/gcc-4_2-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/bound_2.f90
    branches/gcc-4_2-branch/gcc/testsuite/gfortran.dg/initialization_1.f90

Comment 6 Paul Thomas 2007-01-23 05:56:47 UTC
Partially fixed - see list.

Paul
Comment 7 Joost VandeVondele 2007-07-04 06:29:37 UTC
list link: 

http://gcc.gnu.org/ml/fortran/2007-01/msg00361.html
this suggests that it is now an accepts-invalid bug with an easy fix 

(Bug reporter / assignee should change keyword)
Comment 8 Paul Thomas 2007-11-27 20:48:11 UTC
Subject: Bug 29389

Author: pault
Date: Tue Nov 27 20:47:55 2007
New Revision: 130472

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130472
Log:
2007-11-27  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/29389
	*resolve.c (resolve_ordinary_assign): Use find_sym_in_expr to
	test if a temporary should be written for a vector subscript
	on the lhs.

	PR fortran/33850
	* restore.c (pure_stmt_function): Add prototype and new
	function. Calls impure_stmt_fcn.
	(pure_function): Call it.
	(impure_stmt_fcn): New function.

	* expr.c (gfc_traverse_expr): Call *func for all expression
	types, not just variables. Add traversal of character lengths,
	iterators and component character lengths and arrayspecs.
	(expr_set_symbols_referenced): Return false if not a variable.
	* trans-stmt.c (forall_replace, forall_restore): Ditto.
	* resolve.c (forall_index): Ditto.
	(sym_in_expr): New function.
	(find_sym_in_expr): Rewrite to traverse expression calling
	sym_in_expr.
	*trans-decl.c (expr_decls): New function.
	(generate_expr_decls): Rewrite to traverse expression calling
	expr_decls.
	*match.c (check_stmt_fcn): New function.
	(recursive_stmt_fcn): Rewrite to traverse expression calling
	check_stmt_fcn.

2007-11-27  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/29389
	* gfortran.dg/stfunc_6.f90: New test.

	PR fortran/33850
	* gfortran.dg/assign_10.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/assign_10.f90
    trunk/gcc/testsuite/gfortran.dg/stfunc_6.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/expr.c
    trunk/gcc/fortran/match.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/fortran/trans-decl.c
    trunk/gcc/fortran/trans-stmt.c
    trunk/gcc/testsuite/ChangeLog

Comment 9 Paul Thomas 2007-11-27 20:52:39 UTC
Fixed on trunk

Paul
Comment 10 Dominique d'Humieres 2008-09-06 16:58:49 UTC
Note that before the patch for pr35837, the code in comment #1 was wrongly rejected. This is now fixed by this patch. Also if the FORALL statement is this code is uncommented, it is now accepted while it is invalid, see pr37398.