Bug 44925 - [OOP] C_LOC with CLASS pointer
[OOP] C_LOC with CLASS pointer
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: fortran
4.6.0
: P3 normal
: ---
Assigned To: janus
: diagnostic
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-07-12 20:52 UTC by Barron Bichon
Modified: 2010-07-14 08:15 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-07-13 09:45:41


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Barron Bichon 2010-07-12 20:52:20 UTC
Consider the following code:

module test

  type :: t
  end type t

  type, extends(t) :: tt
  end type tt

contains

  subroutine get_cptr(tt_cptr)
    use iso_c_binding
    type(c_ptr) :: tt_cptr
    class(t), pointer :: tt_fptr
    allocate(tt::tt_fptr)
    if (associated(tt_fptr)) tt_cptr = c_loc(tt_fptr)
  end subroutine get_cptr

end module test

At compile-time (using gcc trunk r162082) this gives "Error: Parameter 'tt_fptr' to 'c_loc' at (1) must be either a TARGET or an associated pointer" even though it has to pass the "if (associated(tt_fptr))" test to execute the "c_loc" function.
Comment 1 janus 2010-07-13 09:45:41 UTC
The following patch fixes the PR:

Index: gcc/fortran/dependency.c
===================================================================
--- gcc/fortran/dependency.c	(revision 162124)
+++ gcc/fortran/dependency.c	(working copy)
@@ -427,22 +427,13 @@ gfc_ref_needs_temporary_p (gfc_ref *ref)
 int
 gfc_is_data_pointer (gfc_expr *e)
 {
-  gfc_ref *ref;
-
+  symbol_attribute attr;
+  
   if (e->expr_type != EXPR_VARIABLE && e->expr_type != EXPR_FUNCTION)
     return 0;
 
-  /* No subreference if it is a function  */
-  gcc_assert (e->expr_type == EXPR_VARIABLE || !e->ref);
-
-  if (e->symtree->n.sym->attr.pointer)
-    return 1;
-
-  for (ref = e->ref; ref; ref = ref->next)
-    if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer)
-      return 1;
-
-  return 0;
+  attr = gfc_expr_attr (e);
+  return attr.pointer;
 }


However, it regresses at least on c_loc_tests_5.f03 and c_loc_tests_14.f90.
Comment 2 janus 2010-07-13 11:10:39 UTC
(In reply to comment #1)
> However, it regresses at least on c_loc_tests_5.f03 and c_loc_tests_14.f90.

Actually I have the feeling that both of these test cases are invalid, and the patch is right to reject them.
Comment 3 Tobias Burnus 2010-07-13 11:52:33 UTC
For the program in comment 0, NAG prints:
  Error: aaa.f90, line 16: The argument to C_LOC must not be polymorphic
though ifort and crayftn accept the code. Thus, at least with -std=f95/f2003/f2008 one should reject it. Whether one wants to allow it as extension (-std=gnu) is another question. It can be useful, sometimes, even though it is not well defined.

(In reply to comment #2)
> (In reply to comment #1)
> > However, it regresses at least on c_loc_tests_5.f03 and c_loc_tests_14.f90.
> 
> Actually I have the feeling that both of these test cases are invalid, and the
> patch is right to reject them.

Well, NAG, ifort, pgi, and crayftn compile both programs; g95 compiles at least c_loc_tests_5.f03; thus, I am inclined to say that those two tests are valid.
Comment 4 Tobias Burnus 2010-07-13 12:04:37 UTC
Thus: The derived type needs to be BIND(C) - but then it cannot be extended (as it is not extensible) - nor can the extended type be BIND(C) (per C1503). And without BIND(C) it is not interoperable - besides that polymorphic types are ruled out explicitly.

F2008 FDIS:

"4.5.7.1 Concepts
A derived type that does not have the BIND attribute or the SEQUENCE attribute is an extensible type."

"15.2.3.6 C_LOC (X)
[...] X shall have either the POINTER or TARGET attribute. It shall not be a coindexed object. It shall either be a variable with interoperable type and kind type parameters, or be a scalar, nonpolymorphic variable with no length type parameters. [...]"

"15.3.4 Interoperability of derived types and C struct types
A Fortran derived type is interoperable if it has the BIND attribute.
C1501 (R425) A derived type with the BIND attribute shall not have the SEQUENCE attribute.
C1502 (R425) A derived type with the BIND attribute shall not have type parameters.
C1503 (R425) A derived type with the BIND attribute shall not have the EXTENDS attribute.
C1504 (R425) A derived type with the BIND attribute shall not have a type-bound-procedure-part.
C1505 (R425) Each component of a derived type with the BIND attribute shall be a nonpointer, nonallocatable data component with interoperable type and type parameters."
Comment 5 janus 2010-07-13 12:12:42 UTC
(In reply to comment #3)
> For the program in comment 0, NAG prints:
>   Error: aaa.f90, line 16: The argument to C_LOC must not be polymorphic
> though ifort and crayftn accept the code. Thus, at least with
> -std=f95/f2003/f2008 one should reject it.

Ah, good point. I totally forgot about the fact that a polymorphic variable is by definition not interoperable.

Still comment #0 is a bug, since the error message is totally wrong.


> > > However, it regresses at least on c_loc_tests_5.f03 and c_loc_tests_14.f90.
> > 
> > Actually I have the feeling that both of these test cases are invalid, and the
> > patch is right to reject them.
> 
> Well, NAG, ifort, pgi, and crayftn compile both programs; g95 compiles at least
> c_loc_tests_5.f03; thus, I am inclined to say that those two tests are valid.

I think Sun Studio 12 even rejects both of them.

Anyway, we should refer to the standard rather than other compilers to fix this. F08 clearly states for the argument of C_LOC: "X shall have either the POINTER or TARGET attribute".

c_loc_tests_5.f03 has:

    integer(c_int), dimension(:), pointer :: int_ptr
    my_c_ptr = c_loc(int_ptr(0))

Here int_ptr is a pointer to an array of integers, but int_ptr(0) is an element of that array, so it doesn't have the POINTER attribute, does it?
Comment 6 janus 2010-07-13 12:32:34 UTC
> c_loc_tests_5.f03 has:
> 
>     integer(c_int), dimension(:), pointer :: int_ptr
>     my_c_ptr = c_loc(int_ptr(0))
> 
> Here int_ptr is a pointer to an array of integers, but int_ptr(0) is an element
> of that array, so it doesn't have the POINTER attribute, does it?

Hm, maybe it does.

Using the logic from above, the following should also be rejected (but it is not):

integer, dimension(:), pointer :: int_array_ptr
integer, dimension(10),target :: int_array
integer, pointer :: int_ptr
int_array_ptr => int_array  ! valid
int_ptr => int_array(5)     ! valid
int_ptr => int_array_ptr(5) ! ???
end
Comment 7 janus 2010-07-13 13:54:44 UTC
Ok, here goes the next try. This patch cures the bogus error from comment #0, removes the regressions on c_loc_tests_* and rejects the test case due to the polymorphic argument:

Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 162125)
+++ gcc/fortran/resolve.c	(working copy)
@@ -2440,10 +2440,11 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_act
 {
   char name[GFC_MAX_SYMBOL_LEN + 1];
   char binding_label[GFC_MAX_BINDING_LABEL_LEN + 1];
-  int optional_arg = 0, is_pointer = 0;
+  int optional_arg = 0;
   gfc_try retval = SUCCESS;
   gfc_symbol *args_sym;
   gfc_typespec *arg_ts;
+  symbol_attribute arg_attr;
 
   if (args->expr->expr_type == EXPR_CONSTANT
       || args->expr->expr_type == EXPR_OP
@@ -2460,8 +2461,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_act
      and not necessarily that of the expr symbol (args_sym), because
      the actual expression could be a part-ref of the expr symbol.  */
   arg_ts = &(args->expr->ts);
-
-  is_pointer = gfc_is_data_pointer (args->expr);
+  arg_attr = gfc_expr_attr (args->expr);
     
   if (sym->intmod_sym_id == ISOCBINDING_ASSOCIATED)
     {
@@ -2504,7 +2504,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_act
       else if (sym->intmod_sym_id == ISOCBINDING_LOC)
         {
           /* Make sure we have either the target or pointer attribute.  */
-	  if (!args_sym->attr.target && !is_pointer)
+	  if (!arg_attr.target && !arg_attr.pointer)
             {
               gfc_error_now ("Parameter '%s' to '%s' at %L must be either "
                              "a TARGET or an associated pointer",
@@ -2587,7 +2587,7 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_act
 			  }
                     }
                 }
-              else if (is_pointer
+              else if (arg_attr.pointer
 		       && is_scalar_expr_ptr (args->expr) != SUCCESS)
                 {
                   /* Case 1c, section 15.1.2.5, J3/04-007: an associated
@@ -2622,6 +2622,13 @@ gfc_iso_c_func_interface (gfc_symbol *sym, gfc_act
                                  &(args->expr->where));
                   retval = FAILURE;
                 }
+	      else if (arg_ts->type == BT_CLASS)
+		{
+		  gfc_error_now ("Parameter '%s' to '%s' at %L must not be "
+				 "polymorphic", args_sym->name, sym->name,
+				 &(args->expr->where));
+		  retval = FAILURE;
+		}
             }
         }
       else if (sym->intmod_sym_id == ISOCBINDING_FUNLOC)
Comment 8 Tobias Burnus 2010-07-13 15:54:43 UTC
(In reply to comment #5)
> Here int_ptr is a pointer to an array of integers, but int_ptr(0) is an element
> of that array, so it doesn't have the POINTER attribute, does it?

It doesn't have the pointer attribute - but it has the target attribute, i.e. int_ptr(0) is the first element of the array to which int_ptr points to; the target can be anonymous (i.g. when allocate has been used) or named, but it is a target.
Comment 9 janus 2010-07-14 08:09:33 UTC
Subject: Bug 44925

Author: janus
Date: Wed Jul 14 08:09:05 2010
New Revision: 162169

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=162169
Log:
2010-07-14  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/44925
	* gfortran.h (gfc_is_data_pointer): Remove prototype.
	* dependency.c (gfc_is_data_pointer): Make it static.
	* intrinsic.texi: Update documentation on C_LOC.
	* resolve.c (gfc_iso_c_func_interface): Fix pointer and target checks
	and add a check for polymorphic variables.


2010-07-14  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/44925
	* gfortran.dg/c_loc_tests_15.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/c_loc_tests_15.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/dependency.c
    trunk/gcc/fortran/gfortran.h
    trunk/gcc/fortran/intrinsic.texi
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog

Comment 10 janus 2010-07-14 08:15:51 UTC
Fixed with r162169. Closing.