Bug 25072 - non PURE function used in For-All
Summary: non PURE function used in For-All
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.1.0
: P3 normal
Target Milestone: ---
Assignee: Paul Thomas
URL:
Keywords: ice-on-invalid-code
Depends on:
Blocks:
 
Reported: 2005-11-26 17:55 UTC by Joost VandeVondele
Modified: 2006-06-25 18:13 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2006-01-27 20:55:58


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joost VandeVondele 2005-11-26 17:55:15 UTC
using GNU Fortran 95 (GCC) 4.1.0 20051126 (prerelease)  with '-g -pedantic -std=f95', I get a bad / no diagnostic for the following invalid code:

INTEGER :: I,A(10)
FORALL(I=1:10,T(I)) A(I)=I
CONTAINS
 LOGICAL FUNCTION T(I)
  INTEGER :: I
  T=(MOD(I,2)==0)
 END FUNCTION T
END
Comment 1 Francois-Xavier Coudert 2005-11-26 19:53:06 UTC
gfortran doesn't issue a correct error, and throw an ICE instead:

 In file foo.f90:2

FORALL(I=1:10,T(I)) A(I)=I
              1
 Internal Error at (1):
 free_expr0(): Bad expr type
## g95 ##
In file foo.f90:2

FORALL(I=1:10,T(I)) A(I)=I
               1
Error: Function reference to 't' in FORALL mask at (1) is to a non-PURE procedure
## Intel ##
fortcom: Error: foo.f90, line 2: Any function referenced in a forall-body-stmt must have the PURE attribute explicitly declared.   [T]
FORALL(I=1:10,T(I)) A(I)=I
--------------^
compilation aborted for foo.f90 (code 1)
## Portland ##
PGF90-F-0155-t - FORALL requires PURE function interface (foo.f90: 2)
PGF90/any Linux/x86 5.2-4: compilation aborted
## Sun ##

FORALL(I=1:10,T(I)) A(I)=I
              ^
"foo.f90", Line = 2, Column = 15: ERROR: Procedure T is referenced within a scalar-mask-expression. It must be a PURE procedure.
Comment 2 kargls 2006-02-02 19:12:02 UTC
Subject: Bug 25072

Author: kargl
Date: Thu Feb  2 19:11:58 2006
New Revision: 110517

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=110517
Log:
2006-02-02  Steven G. Kargl  <kargls@comcast>

	PR fortran/24958
	match.c (gfc_match_nullify):  Free the list from head not tail.

	PR fortran/25072
	* match.c (match_forall_header): Fix internal error caused by bogus
	gfc_epxr pointers.

	gfortran.dg/nullify_2.f90: New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/nullify_2.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/match.c
    trunk/gcc/testsuite/ChangeLog

Comment 3 kargls 2006-02-03 21:32:32 UTC
Subject: Bug 25072

Author: kargl
Date: Fri Feb  3 21:32:14 2006
New Revision: 110560

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=110560
Log:
2006-02-03  Steven G. Kargl  <kargls@comcast>
            Paul Thomas  <pault@gcc.gnu.org>

        PR fortran/20845
        * resolve.c (resolve_symbol): Default initialization of derived type
        component reguires the SAVE attribute.

2006-02-02  Steven G. Kargl  <kargls@comcast>

        PR fortran/24958
        match.c (gfc_match_nullify):  Free the list from head not tail.

        PR fortran/25072
        * match.c (match_forall_header): Fix internal error caused by bogus
        gfc_epxr pointers.


2006-02-03  Steven G. Kargl  <kargls@comcast.net>

        PR fortran/24958
        * gfortran.dg/nullify_2.f90

        PR fortran/20845
        * gfortran.dg/char_result_11.f90: Add SAVE.
        * gfortran.dg/der_pointer_4.f90: Ditto.
        * gfortran.dg/used_dummy_types_5.f90
        * gfortran.dg/default_initialization.f90: New test.



Added:
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/default_initialization.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/nullify_2.f90
Modified:
    branches/gcc-4_1-branch/gcc/fortran/ChangeLog
    branches/gcc-4_1-branch/gcc/fortran/match.c
    branches/gcc-4_1-branch/gcc/fortran/resolve.c
    branches/gcc-4_1-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/char_result_11.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/der_pointer_4.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/used_dummy_types_5.f90

Comment 4 kargls 2006-02-03 21:37:55 UTC
I've committed a patch to both 4.1 and trunk that
fix the ICE.  The actual problem that PR raises is
still open.
Comment 5 Paul Thomas 2006-06-20 13:49:35 UTC
This fixes the problem:

Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c	(révision 114599)
+++ gcc/fortran/primary.c	(copie de travail)
@@ -1926,6 +1926,18 @@
     return MATCH_ERROR;
 
   sym = symtree->n.sym;
+
+  /* Hope that this is a function that has not yet been
+     declared; the need for this comes from the occasional
+     return from gfc_get_ha_sym_tree of spurious values
+     for sym->attr.flavor.  */
+  if (sym->new && sym->refs == 1 && !sym->attr.dimension)
+    {
+      gfc_gobble_whitespace ();
+      if (gfc_peek_char () == '(')
+	sym->attr.flavor = FL_UNKNOWN;
+    }
+
   e = NULL;
   where = gfc_current_locus;
 
I do not understand why spurious values are returning from gfc_get_ha_sym_tree, however.  I put diagnostics on the return value and the result; the value just changes!  The above, however, will not do any harm and certainly allows the following to run correctly.

Paul

module foo
  integer, parameter :: n = 4
contains
  logical function foot (i)
    integer, intent(in) :: i
    foot = (i == 2) .or. (i == 3)
  end function foot
end module foo

  use foo
  integer :: i, a(n)
  logical :: s(n)
  s = (/(foot (i), i=1, n)/)

! Check that non-mask case is still OK
  a = 0
  forall (i=1:n) a(i) = i
  if (any (a .ne. (/1,2,3,4/))) call abort ()

! Now a mask using a function with an explicit interface
! via use association.
  a = 0
  forall (i=1:n, foot (i)) a(i) = i
  if (any (a .ne. (/0,2,3,0/))) call abort ()

! Now an array variable mask
  a = 0
  forall (i=1:n, .not. s(i)) a(i) = i
  if (any (a .ne. (/1,0,0,4/))) call abort ()

! This was the PR - an internal function mask
  a = 0
  forall (i=1:n, t (i)) a(i) = i
  if (any (a .ne. (/0,2,0,4/))) call abort ()

! Check that an expression is OK
  a = 0
  forall (i=1:n, t (i) .eqv. .false.) a(i) = i
  if (any (a .ne. (/1,0,3,0/))) call abort ()

! And that an expression that used to work is OK
  a = 0
  forall (i=1:n, s (i) .or. t(i)) a(i) = i
  if (any (a .ne. (/0,2,3,4/))) call abort ()

contains
  logical function t(i)
    integer, intent(in) :: i
    t = (mod (i, 2) == 0)
  end function t
end
Comment 6 Paul Thomas 2006-06-20 23:45:05 UTC
The line

+       sym->attr.flavor = FL_UNKNOWN;

breaks too much - mainly intrinsics.

+       sym->attr.flavor = FL_PROCEDURE;

is in the final stages of regtesting, as I head off to bed.  It looks OK.

Paul

Comment 7 Paul Thomas 2006-06-21 20:39:56 UTC
Here's the patch (or rather, one of three that I have found!):

Paul

Index: gcc/fortran/primary.c
===================================================================
*** gcc/fortran/primary.c	(revision 114823)
--- gcc/fortran/primary.c	(working copy)
*************** match_variable (gfc_expr ** result, int 
*** 2282,2287 ****
--- 2282,2299 ----
        break;
  
      case FL_UNKNOWN:
+       /* If a putative variable is followed by a left parenthesis
+ 	 but does not have the attribute of dimension, this cannot
+ 	 be a variable.  */
+       if (!sym->attr.dimension
+ 	    && !equiv_flag
+ 	    && sym->ts.type != BT_CHARACTER)
+ 	{
+ 	  gfc_gobble_whitespace ();
+ 	  if (gfc_peek_char () == '(')
+ 	    return MATCH_NO;
+ 	}
+ 
        if (gfc_add_flavor (&sym->attr, FL_VARIABLE,
  			  sym->name, NULL) == FAILURE)
  	return MATCH_ERROR;
Comment 8 Paul Thomas 2006-06-25 15:11:36 UTC
Subject: Bug 25072

Author: pault
Date: Sun Jun 25 15:11:02 2006
New Revision: 114987

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114987
Log:
2006-06-25  Paul Thomas  <pault@gcc.gnu.org>
 
	PR fortran/25056
	* interface.c (compare_actual_formal): Signal an error if the formal
	argument is a pure procedure and the actual is not pure.

	PR fortran/27554
	* resolve.c (resolve_actual_arglist): If the type of procedure
	passed as an actual argument is not already declared, see if it is
	an intrinsic.

	PR fortran/25073
	* resolve.c (resolve_select): Use bits 1 and 2 of a new int to
	keep track of  the appearance of constant logical case expressions.
	Signal an error is either value appears more than once.

	PR fortran/20874
	* resolve.c (resolve_fl_procedure): Signal an error if an elemental
	function is not scalar valued.

	PR fortran/20867
	* match.c (recursive_stmt_fcn): Perform implicit typing of variables.

	PR fortran/22038
	* match.c (match_forall_iterator): Mark new variables as
	FL_UNKNOWN if the match fails.

	PR fortran/28119
	* match.c (gfc_match_forall): Remove extraneous call to
	gfc_match_eos.

	PR fortran/25072
	* resolve.c (resolve_code, resolve_function): Rework
	forall_flag scheme so that it is set and has a value of
	2, when the code->expr (ie. the forall mask) is resolved.
	This is used to change "block" to "mask" in the non-PURE
	error message.


2006-06-25  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/20867
	* gfortran.dg/stfunc_3.f90: New test.

	PR fortran/25056
	* gfortran.dg/impure_actual_1.f90: New test.

	PR fortran/20874
	* gfortran.dg/elemental_result_1.f90: New test.

	PR fortran/25073
	* gfortran.dg/select_7.f90: New test.

	PR fortran/27554
	* intrinsic_actual_1.f: New test.

	PR fortran/22038
	PR fortran/28119
	* gfortran.dg/forall_4.f90: New test.

	PR fortran/25072
	* gfortran.dg/forall_5.f90: New test.



Added:
    trunk/gcc/testsuite/gfortran.dg/elemental_result_1.f90
    trunk/gcc/testsuite/gfortran.dg/forall_4.f90
    trunk/gcc/testsuite/gfortran.dg/forall_5.f90
    trunk/gcc/testsuite/gfortran.dg/impure_actual_1.f90
    trunk/gcc/testsuite/gfortran.dg/intrinsic_actual_1.f
    trunk/gcc/testsuite/gfortran.dg/select_7.f90
    trunk/gcc/testsuite/gfortran.dg/stfunc_3.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/match.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog

Comment 9 Paul Thomas 2006-06-25 18:08:45 UTC
Subject: Bug 25072

Author: pault
Date: Sun Jun 25 18:08:13 2006
New Revision: 114994

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=114994
Log:
2006-06-25  Paul Thomas  <pault@gcc.gnu.org>
 
	PR fortran/25056
	* interface.c (compare_actual_formal): Signal an error if the formal
	argument is a pure procedure and the actual is not pure.

	PR fortran/27554
	* resolve.c (resolve_actual_arglist): If the type of procedure
	passed as an actual argument is not already declared, see if it is
	an intrinsic.

	PR fortran/25073
	* resolve.c (resolve_select): Use bits 1 and 2 of a new int to
	keep track of  the appearance of constant logical case expressions.
	Signal an error is either value appears more than once.

	PR fortran/20874
	* resolve.c (resolve_fl_procedure): Signal an error if an elemental
	function is not scalar valued.

	PR fortran/20867
	* match.c (recursive_stmt_fcn): Perform implicit typing of variables.

	PR fortran/22038
	* match.c (match_forall_iterator): Mark new variables as
	FL_UNKNOWN if the match fails.

	PR fortran/28119
	* match.c (gfc_match_forall): Remove extraneous call to
	gfc_match_eos.

	PR fortran/25072
	* resolve.c (resolve_code, resolve_function): Rework
	forall_flag scheme so that it is set and has a value of
	2, when the code->expr (ie. the forall mask) is resolved.
	This is used to change "block" to "mask" in the non-PURE
	error message.


2006-06-25  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/20867
	* gfortran.dg/stfunc_3.f90: New test.

	PR fortran/25056
	* gfortran.dg/impure_actual_1.f90: New test.

	PR fortran/20874
	* gfortran.dg/elemental_result_1.f90: New test.

	PR fortran/25073
	* gfortran.dg/select_7.f90: New test.

	PR fortran/27554
	* intrinsic_actual_1.f: New test.

	PR fortran/22038
	PR fortran/28119
	* gfortran.dg/forall_4.f90: New test.

	PR fortran/25072
	* gfortran.dg/forall_5.f90: New test.



Added:
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/elemental_result_1.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/forall_4.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/forall_5.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/impure_actual_1.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/intrinsic_actual_1.f
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/select_7.f90
    branches/gcc-4_1-branch/gcc/testsuite/gfortran.dg/stfunc_3.f90
Modified:
    branches/gcc-4_1-branch/gcc/fortran/ChangeLog
    branches/gcc-4_1-branch/gcc/fortran/interface.c
    branches/gcc-4_1-branch/gcc/fortran/match.c
    branches/gcc-4_1-branch/gcc/fortran/resolve.c
    branches/gcc-4_1-branch/gcc/testsuite/ChangeLog

Comment 10 Paul Thomas 2006-06-25 18:13:40 UTC
Fixed on trunk and 4.1

Paul