Bug 54667 - [OOP] gimplification failure with c_f_pointer
Summary: [OOP] gimplification failure with c_f_pointer
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: ice-on-invalid-code
Depends on:
Blocks:
 
Reported: 2012-09-22 08:12 UTC by janus
Modified: 2012-09-30 16:42 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-09-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description janus 2012-09-22 08:12:24 UTC
Reported by Andrew Benson at http://gcc.gnu.org/ml/fortran/2012-09/msg00078.html:


use, intrinsic :: ISO_C_Binding
type :: nc
end type
type(c_ptr) :: cSelf
class(nc), pointer :: self
call c_f_pointer(cSelf, self)
end


This ICEs with all gfortran versions I tried. With trunk one gets:

gimplification failed:
&self <addr_expr 0x7f163fa3b4b0
    type <pointer_type 0x7f163fa3c888
        type <record_type 0x7f163fa3c7e0 __class_MAIN___Nc_p type_4 TI
            size <integer_cst 0x7f163f92bda0 constant 128>
            unit size <integer_cst 0x7f163f92bdc0 constant 16>
            align 64 symtab 0 alias set -1 canonical type 0x7f163fa3c7e0 fields <field_decl 0x7f163fa31850 _data>
            pointer_to_this <pointer_type 0x7f163fa3c888> chain <type_decl 0x7f163f94db80 D.1882>>
        unsigned DI
        size <integer_cst 0x7f163f92bd20 constant 64>
        unit size <integer_cst 0x7f163f92bd40 constant 8>
        align 64 symtab 0 alias set -1 canonical type 0x7f163fa3c888>
   
    arg 0 <var_decl 0x7f163fa31980 self type <record_type 0x7f163fa3c7e0 __class_MAIN___Nc_p>
        addressable used TI file andrew3.f90 line 8 col 0 size <integer_cst 0x7f163f92bda0 128> unit size <integer_cst 0x7f163f92bdc0 16>
        align 64 context <function_decl 0x7f163fa39300 MAIN__>>
    andrew3.f90:10:0>
andrew3.f90: In function ‘MAIN__’:
andrew3.f90:10:0: internal compiler error: gimplification failed
   call c_f_pointer(cSelf, self)
Comment 1 janus 2012-09-22 08:39:44 UTC
The dump for comment 0 shows (with -fdump-tree-original):

MAIN__ ()
{
  void * cself;
  struct __class_MAIN___Nc_p self;

  &self = (struct __class_MAIN___Nc_p *) cself;
}

Certainly we are missing are reference to the '_data' component of 'self'.
Comment 2 janus 2012-09-22 08:53:51 UTC
The question is if it is really valid. At first sight both F03 and F08 only specify that FPTR, i.e. the second argument to C_F_POINTER, shall be a pointer with INTENT(OUT).

However, there are additional constraints depending on the actual value of CPTR:

"(1) If the value of CPTR is the C address of an interoperable data
entity, FPTR shall be a data pointer with type and type parame-
ters interoperable with the type of the entity. ..."

"(2) If the value of CPTR is the result of a reference to C LOC with a
noninteroperable argument X, FPTR shall be a nonpolymorphic
scalar pointer with the same type and type parameters as X. ..."


While it would be nontrivial to fully enforce these constraints by a runtime check, I think they might effectively mean that FPTR must not be polymorphic:
In the second case this constraint is spelled out explicitly, and the first case demands that FPTR shall be interoperable. But polymorphic objects are by definition not interoperable.
Comment 3 janus 2012-09-22 09:04:22 UTC
(In reply to comment #2)
> While it would be nontrivial to fully enforce these constraints by a runtime
> check, I think they might effectively mean that FPTR must not be polymorphic:
> In the second case this constraint is spelled out explicitly, and the first
> case demands that FPTR shall be interoperable. But polymorphic objects are by
> definition not interoperable.

Note that there are similar constraints on the argument of C_LOC, where we completely reject any polymorphic entities (cf. PR 44925):

  cSelf = c_loc (self)
                 1
Error: Parameter 'self' to 'c_loc' at (1) must not be polymorphic


I would conclude that this PR should actually be classified as ICE-on-invalid, and we should reject the polymorphic argument to C_F_POINTER.

Andrew, have you tried your test case with any other compilers?
Comment 4 janus 2012-09-22 10:32:40 UTC
(In reply to comment #3)
> Andrew, have you tried your test case with any other compilers?

ifort 12.1 and Oracle Studio 12.3 seem to accept the test case without error message, which does not mean a lot, I guess. Both are not known for extremely good correctness checking. Or they might allow it as an extension.
Comment 5 janus 2012-09-22 13:11:14 UTC
Here is a patch to reject polymorphic arguments of C_F_POINTER (together with a bit of cleanup and fixing/improving two other error messages):


Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 191382)
+++ gcc/fortran/resolve.c	(working copy)
@@ -3532,34 +3532,43 @@ gfc_iso_c_sub_interface (gfc_code *c, gfc_symbol *
 	{
 	  if (c->ext.actual != NULL && c->ext.actual->next != NULL)
 	    {
-	      if (c->ext.actual->expr->ts.type != BT_DERIVED
-		  || c->ext.actual->expr->ts.u.derived->intmod_sym_id
-		     != ISOCBINDING_PTR)
+	      gfc_actual_arglist *arg1 = c->ext.actual;
+	      gfc_actual_arglist *arg2 = c->ext.actual->next;
+
+	      /* Check first argument (CPTR).  */
+	      if (arg1->expr->ts.type != BT_DERIVED
+		  || arg1->expr->ts.u.derived->intmod_sym_id != ISOCBINDING_PTR)
 		{
-		  gfc_error ("Argument at %L to C_F_POINTER shall have the type"
-			     " C_PTR", &c->ext.actual->expr->where);
+		  gfc_error ("Argument CPTR to C_F_POINTER at %L shall have "
+			     "the type C_PTR", &arg1->expr->where);
 		  m = MATCH_ERROR;
 		}
 
-	      /* Make sure we got a third arg if the second arg has non-zero
-		 rank.	We must also check that the type and rank are
+	      /* Check second argument (FPTR).  */
+	      if (arg2->expr->ts.type == BT_CLASS)
+		{
+		  gfc_error ("Argument FPTR to C_F_POINTER at %L must not be "
+			     "polymorphic", &arg2->expr->where);
+		  m = MATCH_ERROR;
+		}
+
+	      /* Make sure we got a third arg (SHAPE) if the second arg has
+		 non-zero rank. We must also check that the type and rank are
 		 correct since we short-circuit this check in
 		 gfc_procedure_use() (called above to sort actual args).  */
-	      if (c->ext.actual->next->expr->rank != 0)
+	      if (arg2->expr->rank != 0)
 		{
-		  if(c->ext.actual->next->next == NULL 
-		     || c->ext.actual->next->next->expr == NULL)
+		  if (arg2->next == NULL || arg2->next->expr == NULL)
 		    {
 		      m = MATCH_ERROR;
-		      gfc_error ("Missing SHAPE parameter for call to %s "
+		      gfc_error ("Missing SHAPE argument for call to %s "
 				 "at %L", sym->name, &(c->loc));
 		    }
-		  else if (c->ext.actual->next->next->expr->ts.type
-			   != BT_INTEGER
-			   || c->ext.actual->next->next->expr->rank != 1)
+		  else if (arg2->next->expr->ts.type != BT_INTEGER
+			   || arg2->next->expr->rank != 1)
 		    {
 		      m = MATCH_ERROR;
-		      gfc_error ("SHAPE parameter for call to %s at %L must "
+		      gfc_error ("SHAPE argument for call to %s at %L must "
 				 "be a rank 1 INTEGER array", sym->name,
 				 &(c->loc));
 		    }
Comment 6 janus 2012-09-22 13:18:31 UTC
Moreover there is a typo in the documentation of C_F_POINTER:


Index: gcc/fortran/intrinsic.texi
===================================================================
--- gcc/fortran/intrinsic.texi	(revision 191382)
+++ gcc/fortran/intrinsic.texi	(working copy)
@@ -2362,9 +2362,8 @@ end program main
 
 @table @asis
 @item @emph{Description}:
-@code{C_F_POINTER(CPTR, FPTR[, SHAPE])} Assign the target the C pointer
-@var{CPTR} to the Fortran pointer @var{FPTR} and specify its
-shape.
+@code{C_F_POINTER(CPTR, FPTR[, SHAPE])} assigns the target of the C pointer
+@var{CPTR} to the Fortran pointer @var{FPTR} and specifies its shape.
 
 @item @emph{Standard}:
 Fortran 2003 and later
Comment 7 Andrew Benson 2012-09-22 16:59:26 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > While it would be nontrivial to fully enforce these constraints by a runtime
> > check, I think they might effectively mean that FPTR must not be polymorphic:
> > In the second case this constraint is spelled out explicitly, and the first
> > case demands that FPTR shall be interoperable. But polymorphic objects are by
> > definition not interoperable.
> 
> Note that there are similar constraints on the argument of C_LOC, where we
> completely reject any polymorphic entities (cf. PR 44925):
> 
>   cSelf = c_loc (self)
>                  1
> Error: Parameter 'self' to 'c_loc' at (1) must not be polymorphic
> 
> 
> I would conclude that this PR should actually be classified as ICE-on-invalid,
> and we should reject the polymorphic argument to C_F_POINTER.
> 
> Andrew, have you tried your test case with any other compilers?

The only other compiler I have access to is ifort 11.1 (which also accepts it), so that doesn't add much unfortunately.
Comment 8 Andrew Benson 2012-09-22 17:02:06 UTC
Thanks for clarifying this. It does look like this is invalid according to the standard. I'll think of another way to do what I was trying to do.....
Comment 9 Tobias Burnus 2012-09-22 18:38:42 UTC
(In reply to comment #7)
> The only other compiler I have access to is ifort 11.1 (which also accepts it),
> so that doesn't add much unfortunately.

As do crayftn and PGI, however, it is a constraint (i.e. the compiler does not have to diagnose it) but required that the user does. From Fortran 2008 15.2.3.6 and 15.2.3.3:

CPTR shall be a scalar of type C PTR. It is an INTENT (IN) argument. Its value
   shall be
   * the C address of an interoperable data entity, or
   * the result of a reference to C LOC with a noninteroperable argument.

And CLASS is not interoperable, while C_LOC has

 [...] It shall either be a variable with interoperable type and kind type
 parameters, or be a scalar, nonpolymorphic variable with no length type parameters."

(Note in TS29113, the "scalar, " has been deleted.)
Comment 10 janus 2012-09-22 19:02:03 UTC
(In reply to comment #9)
> From Fortran 2008 15.2.3.6 and 15.2.3.3:
> 
> CPTR shall be a scalar of type C PTR. It is an INTENT (IN) argument. Its value
>    shall be
>    * the C address of an interoperable data entity, or
>    * the result of a reference to C LOC with a noninteroperable argument.
> 
> And CLASS is not interoperable, while C_LOC has
> 
>  [...] It shall either be a variable with interoperable type and kind type
>  parameters, or be a scalar, nonpolymorphic variable with no length type
> parameters."
> 
> (Note in TS29113, the "scalar, " has been deleted.)

So, in conclusion, I hope you agree that polymorphic arguments should be rejected for both C_LOC and C_F_POINTER. For C_LOC we do it already, and for C_F_POINTER my patch in comment 5 is supposed to do it ...
Comment 11 Andrew Benson 2012-09-22 19:39:17 UTC
(In reply to comment #10)
> (In reply to comment #9)
> > From Fortran 2008 15.2.3.6 and 15.2.3.3:
> > 
> > CPTR shall be a scalar of type C PTR. It is an INTENT (IN) argument. Its value
> >    shall be
> >    * the C address of an interoperable data entity, or
> >    * the result of a reference to C LOC with a noninteroperable argument.
> > 
> > And CLASS is not interoperable, while C_LOC has
> > 
> >  [...] It shall either be a variable with interoperable type and kind type
> >  parameters, or be a scalar, nonpolymorphic variable with no length type
> > parameters."
> > 
> > (Note in TS29113, the "scalar, " has been deleted.)
> 
> So, in conclusion, I hope you agree that polymorphic arguments should be
> rejected for both C_LOC and C_F_POINTER. For C_LOC we do it already, and for
> C_F_POINTER my patch in comment 5 is supposed to do it ...

Yes - I definitely agree on this point.
Comment 12 janus 2012-09-30 16:36:09 UTC
Author: janus
Date: Sun Sep 30 16:36:02 2012
New Revision: 191870

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=191870
Log:
2012-09-30  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54667
	* intrinsic.texi (C_F_POINTER): Fix description.
	* resolve.c (gfc_iso_c_sub_interface): Add a check for FPTR argument
	of C_F_POINTER. Modify two error messages. Cleanup.

2012-09-30  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/54667
	* gfortran.dg/c_funloc_tests_6.f90: Modified error message.
	* gfortran.dg/c_f_pointer_shape_test.f90: Ditto.
	* gfortran.dg/c_f_pointer_tests_5.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_tests_5.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/intrinsic.texi
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/c_f_pointer_shape_test.f90
    trunk/gcc/testsuite/gfortran.dg/c_funloc_tests_6.f90
Comment 13 janus 2012-09-30 16:42:23 UTC
Fixed with r191870. Closing.

Thanks for the report, Andrew!