Bug 33162 - INTRINSIC functions as ACTUAL argument
Summary: INTRINSIC functions as ACTUAL argument
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Jerry DeLisle
URL:
Keywords: accepts-invalid, rejects-valid
Depends on:
Blocks: 32834
  Show dependency treegraph
 
Reported: 2007-08-23 16:29 UTC by Tobias Burnus
Modified: 2007-11-14 01:17 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2007-10-21 00:15:45


Attachments
Patch to add checks for double specifics (1.67 KB, patch)
2007-10-21 16:39 UTC, Jerry DeLisle
Details | Diff
Preliminary argument checking with intrinsics (622 bytes, patch)
2007-10-21 21:32 UTC, Jerry DeLisle
Details | Diff
Preliminary last patch for this PR (820 bytes, patch)
2007-11-02 05:25 UTC, Jerry DeLisle
Details | Diff
Revised preliminary last patch (825 bytes, patch)
2007-11-02 05:56 UTC, Jerry DeLisle
Details | Diff
Revised preliminary patch that also fixes comment #19 (944 bytes, patch)
2007-11-03 22:02 UTC, Jerry DeLisle
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2007-08-23 16:29:05 UTC
Example:
  print *, dcos(1.0)
  print *, dcos(1d0)

gfortran treats them as it does with "cos()": Any kind of REAL is accepted. However, DCOS is a specific name of COS which only accepts REAL(8).

The bug should be fixed such that the following works as well:

PROCEDURE(DCOS):: my1
PROCEDURE(COS) :: my2

"MY1" is a function with the interface:
  interface
    double precision function my1(x)
      double precision, intent(in) :: x
    end function my1
  end interface
(Note especially also the intent(in) and the dummy argument "x".)

"MY1" takes the interface from the specific name of COS: Only REAL(4) is accepted.
Comment 1 Tobias Burnus 2007-09-05 14:14:27 UTC
Besides the argument kind checking of specific intrinsic procedures and
besides using specific intrinsic as name in the PROCEDURE statement, the following fails as well. The error message is:
  Error: Type/rank mismatch in argument 'a' at (1)
This program works with NAG f95, g95, ifort, openf95 ...

module m
implicit none
contains
  subroutine sub(a)
    interface
      function a(x)
        real :: a, x
        intent(in) :: x
      end function a
    end interface
    optional :: a
    if(present(a)) print *, a(4.0)
  end subroutine sub
end module m

use m
implicit none
intrinsic cos
call sub()
call sub(cos)
end
Comment 2 Jerry DeLisle 2007-10-21 00:15:44 UTC
This patch:

Index: interface.c
===================================================================
--- interface.c (revision 129496)
+++ interface.c (working copy)
@@ -1679,8 +1679,9 @@ compare_actual_formal (gfc_actual_arglis
            return 0;
 
        }
-      else if (!compare_parameter (f->sym, a->expr,
-                                  ranks_must_agree || rank_check, is_elemental))
+      else if (a->expr->ts.type != BT_PROCEDURE 
+              && !compare_parameter (f->sym, a->expr, ranks_must_agree
+                                     || rank_check, is_elemental))
        {
          if (where)
            gfc_error ("Type/rank mismatch in argument '%s' at %L",

Allows the test case in comment #1 to compile and run correctly with no regressions in the test suite.

Comment 3 Jerry DeLisle 2007-10-21 03:34:08 UTC
Tobias, is this what you meant in your original comment that should work?

module m
implicit none
  interface
    double precision function my1(x)
      double precision, intent(in) :: x
    end function my1
  end interface
  interface
    real(kind=4) function my2(x)
      real, intent(in) :: x
    end function my2
  end interface
end module

use m
procedure(dcos):: my1
procedure(cos) :: my2
print *, my2(1.0)
print *, my1(1d0)
end

Now this gives:

test.f90:16.14:

procedure(dcos) :: my1
             1
Error: Fortran 2003: Support for intrinsic procedure 'dcos' in PROCEDURE statement at (1) not yet implemented in gfortran
test.f90:17.13:

procedure(cos) :: my2
            1
Error: Fortran 2003: Support for intrinsic procedure 'cos' in PROCEDURE statement at (1) not yet implemented in gfortran
Comment 4 Tobias Burnus 2007-10-21 09:30:27 UTC
Several intrinsic functions come as specific and as generic functions. For instance
  COS as generic function takes as argument REAL(k) and COMPLEX(k), k=4,8,10,16
      and returns the same type and kind as it got as argument.
whereas
  COS as specific function takes as argument REAL(4) and returns REAL(4)
 DCOS as specific function takes as argument REAL(8) and returns REAL(8)

Therefore,
  intrinsic cos
  COS(1.0) ! generic intrinsic function; matches specific function  COS
  COS(1d0) ! generic intrinsic function; matches specific function DCOS
  end
are valid, however,
  intrinsic dcos
  DCOS(1.0)
is wrong as the specific function requires REAL(8) as argument and not REAL(4).
NAG f95:
  ERROR: Wrong data type for argument X to the DCOS intrinsic
g95:
  Error: Type of argument 'x' in call to 'dcos' at (1) should be REAL(8),
         not REAL(4)

In order to detect this, either check.c has to be refined or for specific function the interface has to be stored. The latter is needed in the following.

If one passes an intrinsic function as actual argument, e.g.
  call sub(cos) ! see valid program in comment 1
the procedure is the specific intrinsic and not the generic intrinsic; in this case this it means that "cos" gets REAL(4) as argument and returns REAL(4).

Currently, this information is not stored in intrinsic.c. If it were, one could simply do:
  module mm
  contains
    subroutine foo(trig)
      intrinsic cos
      procedure(cos) :: trig ! real(4) function
      print *, trig(1.0)
    end subroutine
  end module mm
!and then
  use mm
  call foo(sin) ! specific function with real(4)
  call foo(tan) ! specific function with real(4)
  call foo(dcos)! wrong: specific function with real(8)
  end
The statement
  PROCEDURE(cos) :: trig
declares trig as a procedure which has the same interface as the specific function cos. In this case the interface of the specific COS is probably:

  elemental function cos(x)
    real(4), intent(in) :: x
    real(4) :: cos
  end function cos

Thus, in order to implement
  "PROCEDURE( intrinsic specific function )"
one needs to know (in match_procedure) the explicit interface of that function. While the PROCEDURE statement is a Fortran 2003 feature, the program in comment 1 is a valid Fortran 95 program. The problem of the patch in comment 2 is that it also allows the following program which is invalid:

module m
implicit none
contains
  subroutine sub(a)
    interface
      function a()
        real :: a
      end function a
    end interface
    print *, a()
  end subroutine sub
end module m

use m
implicit none
intrinsic cos
! NAG f95:
! Error: Specific intrinsic COS has more arguments than dummy proc A
call sub(cos)
end

Note that the program in comment 4 is wrong since
  use m
imports the interface of my1 and and my2, while the following declares the interfaces again:
  procedure(dcos):: my1
  procedure(cos) :: my2

The reason that Janus has not implemented "PROCEDURE( specific intrinsic )" is that we currently do not store the interface of specific intrinsics, which made the support a bit difficult.

(PROCEDURE(otherProcedure) is already supported for non-intrinsic procedures such as:
  procedure(foo) :: bar
  call bar(4,4.4)
 contains
  subroutine foo(x,y)
    integer :: x
    real    :: y
  end subroutine
end ! )
Comment 5 Tobias Burnus 2007-10-21 10:44:10 UTC
> This patch: Allows the test case in comment #1 to compile and run correctly with
> no regressions in the test suite.

It also wrongly allows the test case in the bugreport PR 33847 to compile. Thus we should add a test case for this to the test suite. (That PR is not about intrinsic functions.)
Comment 6 Jerry DeLisle 2007-10-21 16:39:01 UTC
Created attachment 14381 [details]
Patch to add checks for double specifics

This patch adds checks for double specific intrinsics.  I added checks for those specific intrinsics listed in the standard as well as some extensions provided by gfortran.  Please give it a look over for completeness.  I will submit to list after I build the ChangeLog entry.
Comment 7 Jerry DeLisle 2007-10-21 21:32:32 UTC
Created attachment 14382 [details]
Preliminary argument checking with intrinsics

This "draft" patch catches the latest invalid case provided in Comment #4.  This is only checking a simple case of no argument vs there is an argument.  With gfc_find_function we can access the formal argument list for the intrinsics and proceed to check them.  I will develop this further to check number and types of arguments to verify a match.
Comment 8 Tobias Burnus 2007-10-22 06:56:02 UTC
(In reply to comment #6)
> Created an attachment (id=14381) [edit]
> Patch to add checks for double specifics

This looks wrong:
+gfc_check_a_pd (gfc_expr *a, gfc_expr *p)
+  if (double_check (a, 0) == FAILURE || double_check (a, 0) == FAILURE)
(left of || same as right)

(In reply to comment #7)
> Created an attachment (id=14382) [edit]
> Preliminary argument checking with intrinsics
>
> This "draft" patch catches the latest invalid case provided in Comment #4. 
> This is only checking a simple case of no argument vs there is an argument.

I'm not sure this is the right approach, see example in PR 33847 for something gfortran rightfully rejects. gfortran currently has already interface checks, however, there is no interface known for specific intrinsics procedures, which we also need for PROCEDURE.

Interesting is whether the following should be accepted or not. NAG f95 and gfortran reject it, g95 and ifort allow it (well, as PR 33847 shows, their checking is rather weak).

-----------------------------
module m
implicit none
contains
  subroutine sub(a)
    interface
      function a(x)
        real :: a, x
        intent(in) :: x
      end function a
    end interface
    print *, a(4.0)
  end subroutine sub
end module m

use m
implicit none
EXTERNAL foo  ! implicit interface
call sub(foo) ! sub's argument has an explicit interface
end
Comment 9 Jerry DeLisle 2007-10-23 01:42:26 UTC
The example in Comment #8 is rejected by gfortran because of this bug.  It is rejected by Lahey:

Diagnostic messages: program name(main)
   2204-S: "SOURCE.F90", line 18, column 6: In the reference to procedure 'sub', the type of actual argument must be the same as that of the corresponding dummy argument.

There is no type information about external foo so I think this should be rejected. (Siding with NAG and Lahey as well)
Comment 10 Jerry DeLisle 2007-10-27 00:54:35 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Sat Oct 27 00:54:20 2007
New Revision: 129673

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129673
Log:
2007-10-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	* intrinsic.h: Add prototypes for four new functions, gfc_check_datan2,
	gfc_check_dprod, gfc_check_fn_d, and gfc_check_x_yd.
	* intrinsic.c (add_functions): Add double precision checks for dabs,
	dacos, dacosh, dasin, dasinh, datan, datanh, datan2, dbesj0, dbesj1,
	dbesy0, dbesy1, dcos, dcosh, ddim, derf, derfc, dexp, dgamma,
	dlgama, dlog, dlog10, dmod, dsign, dsin, dsinh, dsqrt, dtan, and dtanh.
	Add real check dprod.
	* check.c (gfc_check_datan2): New function to check for double precision
	argumants. (gfc_check_dprod, gfc_check_fn_d, and gfc_check_x_yd): Ditto.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/check.c
    trunk/gcc/fortran/intrinsic.c
    trunk/gcc/fortran/intrinsic.h

Comment 11 Jerry DeLisle 2007-10-27 00:57:38 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Sat Oct 27 00:57:26 2007
New Revision: 129674

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129674
Log:
2007-10-26  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	* gfortran.dg/argument_checking_9.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/argument_checking_9.f90
Modified:
    trunk/gcc/testsuite/ChangeLog

Comment 12 Tobias Burnus 2007-10-27 21:07:11 UTC
(In reply to comment #8)
> Interesting is whether the following should be accepted or not.
[...]
> EXTERNAL foo  ! implicit interface
> call sub(foo) ! sub's argument has an explicit interface

gfortran, NAG f95 and Lahey rightfully reject it:

"12.4.1.3 Actual arguments associated with dummy procedure entities"
[...]
"If the interface of the dummy argument is explicit, the characteristics listed in 12.2 shall be the same for the associated actual argument and the corresponding dummy argument"

(openf95, sunf95, g95 and ifort accept this program; one could allow it for -std=gnu or legacy, but it is probably not worth the trouble.)
Comment 13 patchapp@dberlin.org 2007-10-31 04:00:33 UTC
Subject: Bug number PR33162

A patch for this bug has been added to the patch tracker.
The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2007-10/msg01855.html
Comment 14 Jerry DeLisle 2007-10-31 14:27:10 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Wed Oct 31 14:26:57 2007
New Revision: 129798

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129798
Log:
2007-10-31  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	* interface.c (compare_intr_interfaces): New function to check intrinsic
	function arguments against formal arguments. (compare_interfaces): Fix
	logic in comparison of function and subroutine attributes.
	(compare_parameter): Use new function for intrinsic as argument.
	* resolve.c (resolve_actual_arglist): Allow an intrinsic without
	function attribute to be checked further.  Set function attribute if
	intrinsic symbol is found, return FAILURE if not.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/resolve.c

Comment 15 Jerry DeLisle 2007-10-31 14:31:02 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Wed Oct 31 14:30:48 2007
New Revision: 129799

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=129799
Log:
2007-10-31  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	* gfortran.dg/interface_19.f90: New.
	* gfortran.dg/interface_20.f90: New.
	* gfortran.dg/interface_21.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/interface_19.f90
    trunk/gcc/testsuite/gfortran.dg/interface_20.f90
    trunk/gcc/testsuite/gfortran.dg/interface_21.f90
Modified:
    trunk/gcc/testsuite/ChangeLog

Comment 16 Jerry DeLisle 2007-11-02 05:25:58 UTC
Created attachment 14465 [details]
Preliminary last patch for this PR

This patch enables the test case in Comment #3 to compile and execute correctly.  I am not certain it covers all necessary checks.  I would appreciate some testing and comments.
Comment 17 Jerry DeLisle 2007-11-02 05:40:49 UTC
hmm I posted that part3 patch too soon. I see I have several regressions.  Oh well, its a start. :)
Comment 18 Jerry DeLisle 2007-11-02 05:56:37 UTC
Created attachment 14466 [details]
Revised preliminary last patch

This revised patch adds a check for NULL proc_if in decl.c

This appears to fix the regressions.  Also, one dg-error must be removed from line 40 of proc_decl_1.f90 since that line now compiles without error with this patch.
Comment 19 Janus Weil 2007-11-02 20:53:32 UTC
Hi Jerry,
I tried your patch (part 3b), and noticed that it fails on the following code:

real function t(x)
  real ::x
  t = x
end function

program p
  implicit none
  intrinsic sin
  procedure(sin):: t
  print *,t(1.0)
end program

Seems like this is due to the stuff which you added to decl.c (match_procedure_decl):

+      if (proc_if != NULL && proc_if->attr.intrinsic
+	  && gfc_intrinsic_actual_ok (proc_if->name, 0))
+	goto set_if;
+
       if (!sym->attr.pointer && gfc_add_external (&sym->attr, NULL) == FAILURE)
 	return MATCH_ERROR;
       if (gfc_add_proc (&sym->attr, sym->name, NULL) == FAILURE)
 	return MATCH_ERROR;
 
       /* Set interface.  */
+set_if:

This prevents the procedure from getting the "external" and "procedure" attributes, if the interface is an intrinsic routine. This is wrong. A symbol declared by a PROCEDURE() statement should always get the "procedure" attribute.
Comment 20 Jerry DeLisle 2007-11-03 22:02:21 UTC
Created attachment 14480 [details]
Revised preliminary patch that also fixes comment #19

This patch adds some similar code to resolve_unknown_f.  I may explore pushing this code block up one level.

Janus, regarding the two statements I bypass in decl.c.  I find that I get an error for trying to change attributes of use associated functions.  If I include !attr.use_assoc in the conditions I get a negative refs error.  This may be a matter of finding the write combination of conditions for these.  In the meantime, this part3c patch is working for the cases I have and regression tests fine.
Comment 21 patchapp@dberlin.org 2007-11-12 05:56:25 UTC
Subject: Bug number PR33162

A patch for this bug has been added to the patch tracker.
The mailing list url for the patch is http://gcc.gnu.org/ml/gcc-patches/2007-11/msg00598.html
Comment 22 Jerry DeLisle 2007-11-14 00:59:20 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Wed Nov 14 00:59:09 2007
New Revision: 130168

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130168
Log:
2007-11-11  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	* decl.c (match_procedure_decl): Remove TODO and allow intrinsics in
	PROCEDURE declarations.  Set attr.untyped to allow the interface to be
	resolved later where the symbol type will be set.
	* interface.c (compare_intr_interfaces): Remove static from pointer
	declarations.  Add type and kind checks for dummy function arguments.
	(compare_actual_formal_intr): New function to compare an actual
	argument with an intrinsic function. (gfc_procedures_use): Add check for
	interface that points to an intrinsic function, use the new function.
	* resolve.c (resolve_specific_f0): Resolve the intrinsic interface.
	(resolve_specific_s0): Ditto.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/decl.c
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/resolve.c

Comment 23 Jerry DeLisle 2007-11-14 01:06:24 UTC
Subject: Bug 33162

Author: jvdelisle
Date: Wed Nov 14 01:06:13 2007
New Revision: 130169

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=130169
Log:
2007-11-13  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/33162
	*gfortran.dg/proc_decl_1.f90: Update.
	*gfortran.dg/proc_decl_7.f90: New test.
	*gfortran.dg/proc_decl_8.f90: New test.
	*gfortran.dg/proc_decl_9.f90: New test.
	*gfortran.dg/proc_decl_10.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/proc_decl_10.f90
    trunk/gcc/testsuite/gfortran.dg/proc_decl_7.f90
    trunk/gcc/testsuite/gfortran.dg/proc_decl_8.f90
    trunk/gcc/testsuite/gfortran.dg/proc_decl_9.f90
Modified:
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/proc_decl_1.f90

Comment 24 Jerry DeLisle 2007-11-14 01:17:20 UTC
Fixed on trunk.