Bug 38220 - C_LOC intrinsic non-pure and without explicit interface
Summary: C_LOC intrinsic non-pure and without explicit interface
Status: REOPENED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.4.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
Depends on:
Blocks: F2003 29670 ISO_C_Binding
  Show dependency treegraph
 
Reported: 2008-11-21 22:02 UTC by Daniel Franke
Modified: 2023-03-16 20:07 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-01-06 13:05:59


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Franke 2008-11-21 22:02:31 UTC
$> cat cloc.f90
USE ISO_C_BINDING, ONLY: C_PTR, C_LOC
CONTAINS
  PURE SUBROUTINE F(x)
    INTEGER, INTENT(in), TARGET :: x
    TYPE(C_PTR) :: px
    px = C_LOC(x)
  END SUBROUTINE
END

$> gfortran-svn -Wimplicit-interface cloc.f90
cloc.f90:6.9:

    px = C_LOC(x)
        1
Warning: Procedure 'c_loc' called with an implicit interface at (1)
cloc.f90:6.9:

    px = C_LOC(x)
        1
Error: Function reference to 'c_loc' at (1) is to a non-PURE procedure within a PURE procedure

$> gfortran-svn --version
GNU Fortran (GCC) 4.4.0 20081120 (experimental)


To my knowledge, all intrinsics have an explicit interface and are PURE by default?!
Comment 1 Daniel Franke 2008-12-09 20:30:01 UTC
The same seems to hold for C_FUNLOC, but not C_F_POINTER?!
Comment 2 Daniel Franke 2008-12-09 20:49:45 UTC
symbol.c (generate_isocbinding_symbol):
....
4139  /* Here, we're taking the simple approach.  We're defining
4140     c_loc as an external identifier so the compiler will put
4141     what we expect on the stack for the address we want the
4142     C address of.  */
....
4170  tmp_sym->attr.external = 1;
4171  tmp_sym->attr.if_source = IFSRC_UNKNOWN;
....
Comment 3 Thomas Koenig 2009-01-06 13:05:58 UTC
This appears to resolve the issue(s):

Index: interface.c
===================================================================
--- interface.c (revision 143076)
+++ interface.c (working copy)
@@ -2411,9 +2411,12 @@ void
 gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
 {

-  /* Warn about calls with an implicit interface.  */
+  /* Warn about calls with an implicit interface.  Special case
+     for calling a ISO_C_BINDING because these c_loc and c_funloc
+     are pseudo-unknown.  */
   if (gfc_option.warn_implicit_interface
-      && sym->attr.if_source == IFSRC_UNKNOWN)
+      && sym->attr.if_source == IFSRC_UNKNOWN
+      && ! sym->attr.is_iso_c)
     gfc_warning ("Procedure '%s' called with an implicit interface at %L",
                 sym->name, where);

Index: symbol.c
===================================================================
--- symbol.c    (revision 143076)
+++ symbol.c    (working copy)
@@ -4169,6 +4169,7 @@ generate_isocbinding_symbol (const char
                tmp_sym->result = tmp_sym;
                tmp_sym->attr.external = 1;
                tmp_sym->attr.use_assoc = 0;
+               tmp_sym->attr.pure = 1;
                tmp_sym->attr.if_source = IFSRC_UNKNOWN;
                tmp_sym->attr.proc = PROC_UNKNOWN;
              }
Comment 4 Thomas Koenig 2009-01-06 23:03:33 UTC
Subject: Bug 38220

Author: tkoenig
Date: Tue Jan  6 23:03:18 2009
New Revision: 143140

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=143140
Log:
2009-01-06  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/38220
	* interface.c (gfc_procedure_use):  Don't warn about functions
	from ISO_C_BINDING.
	* symbol.c (generate_isocbinding_symbol):  Mark c_loc and
	c_funloc as pure.

2009-01-06  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/38220
	* gfortran.dg/c_loc_pure_1.f90:  New test.


Added:
    trunk/gcc/testsuite/gfortran.dg/c_loc_pure_1.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/symbol.c
    trunk/gcc/testsuite/ChangeLog

Comment 5 Thomas Koenig 2009-01-06 23:05:21 UTC
Fixed on trunk, closing.
Comment 6 Joost VandeVondele 2014-12-12 07:00:14 UTC
I believe this introduced a regression, C_LOC is not pure. 

Just quoting from here https://software.intel.com/en-us/forums/topic/269061

The "standard intrinsic procedures" are those listed in section 13.7 of F2003. Procedures in intrinsic modules are not included. I happen to be writing this from a meeting of the Fortran standards committee (J3) and posed this question - the response from one member was "because we forgot to issue the Ivory Soap certificates". None of the procedures in ISO_C_BINDING are pure.

The example why this restriction is a good idea (inspired by PR64247) is the fact that if it where, any pure procedure could return different results even if the variables have the same value (as opposed to address):

!
! are functions containing C_LOC pure ?
!
MODULE M1
CONTAINS
  PURE INTEGER*8 FUNCTION F(a) RESULT(I)
   USE ISO_C_BINDING, ONLY: C_LOC
   INTEGER*8, INTENT(IN), TARGET :: a
   I=TRANSFER(C_LOC(a),I)
  END FUNCTION
END MODULE M1

PROGRAM TEST
 USE M1
 INTEGER*8 :: i,ri
 INTEGER*8 :: j,rj
 i=4 ; j=4
 ri=F(i)
 rj=F(j)
 IF (ri.NE.rj) CALL ABORT()
END PROGRAM

ifort rejects this code, gfortran and cft compile but trigger the runtime abort, pgf90 compiles and runs without abort.

CCing Tobias as he approved the patch...
Comment 7 Thomas Koenig 2015-05-16 06:08:09 UTC
Unassignming for the moment.
Comment 8 Jeff Hammond 2023-03-15 11:03:30 UTC
For what it's worth, ISO/IEC DIS 1539-1:2022 (E) now contains the following:

All standard procedures in the intrinsic module ISO_C_BINDING, other than C_F_POINTER and C_F_PROCPOINTER, are now pure.
Comment 9 anlauf 2023-03-15 20:45:28 UTC
(In reply to Joost VandeVondele from comment #6)
> ifort rejects this code, gfortran and cft compile but trigger the runtime
> abort, pgf90 compiles and runs without abort.

Actually that code has the logic wrong.  Adjusted, portable testcase:

MODULE M1
CONTAINS
  PURE INTEGER(C_INTPTR_T) FUNCTION F(a) RESULT(I)
    USE ISO_C_BINDING, ONLY: C_LOC, C_INTPTR_T
    INTEGER, INTENT(IN), TARGET :: a
    I=TRANSFER(C_LOC(a),I)
  END FUNCTION
END MODULE M1

PROGRAM TEST
  USE M1
  USE ISO_C_BINDING, ONLY: C_INTPTR_T
  INTEGER :: i, j
  integer(C_INTPTR_T) :: ri, rj
  i=4 ; j=4
  ri=F(i)
  rj=F(j)
  IF (ri == rj) stop 1
  rj=F(i)
  IF (ri /= rj) stop 2
END PROGRAM

Works with Crayftn 14.0, Intel, Nvidia, gfortran.

Wrong code with flang.

Rejected by NAG with:

NAG Fortran Compiler Release 7.1(Hanzomon) Build 7101
Error: pr38220.f90, line 9: Reference via generic C_LOC to impure C_LOC_PRIVATE from pure F

Can we close it again?
Comment 10 anlauf 2023-03-16 20:07:31 UTC
(In reply to Jeff Hammond from comment #8)
> For what it's worth, ISO/IEC DIS 1539-1:2022 (E) now contains the following:
> 
> All standard procedures in the intrinsic module ISO_C_BINDING, other than
> C_F_POINTER and C_F_PROCPOINTER, are now pure.

Actually the text I have says:

18.2.3.1  General

[...]  The C_F_POINTER and C_F_STRPOINTER subroutines are impure; all other
procedures in the module are simple.


18.2.3.4  C_F_PROCPOINTER (CPTR, FPTR)

[...]
Class. Simple subroutine.


Besides the new concept of "simple procedures" there is no major change here.