User account creation filtered due to spam.

Bug 41556 - [OOP] Errors in applying operator/assignment to an abstract type
Summary: [OOP] Errors in applying operator/assignment to an abstract type
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.5.0
: P3 normal
Target Milestone: 4.5.0
Assignee: janus
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2009-10-03 17:10 UTC by Damian Rouson
Modified: 2016-11-16 12:05 UTC (History)
3 users (show)

See Also:
Host: Mac OS X 10.5.8
Target: Mac OS X 10.5.8
Build: Mac OS X 10.5.8
Known to work:
Known to fail:
Last reconfirmed: 2009-11-05 14:27:59


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Damian Rouson 2009-10-03 17:10:19 UTC
When defining an abstract type with generic operators that map to deferred bindings and using these operators in an expression, the development branch of gfortran 4.5.0 (20090925) gives the errors shown below the program below.  In case it helps to know, IBM XL Fortran 12.1 compiles the program without errors or warnings. 

Damian


$ cat abstract_algebra.f03
module abstract_algebra
  implicit none 
  private      
  public :: rescale
  public :: object

  type ,abstract :: object
  contains
    procedure(assign_interface) ,deferred :: assign   
    procedure(product_interface) ,deferred :: product
    generic  :: assignment(=) => assign
    generic  :: operator(*) => product
  end type 

  abstract interface
    function product_interface(lhs,rhs) result(product)
      import :: object
      class(object) ,intent(in)  :: lhs
      class(object) ,allocatable :: product
      real          ,intent(in)  :: rhs
    end function 
    subroutine assign_interface(lhs,rhs) 
      import :: object 
      class(object) ,intent(inout) :: lhs
      class(object) ,intent(in)    :: rhs
    end subroutine 
  end interface

contains

  subroutine rescale(operand,scale)    
    class(object)    :: operand
    real ,intent(in) :: scale
    operand = operand*scale           ! preferred implementation 
    operand = operand%product(scale)  ! alternate implementation
  end subroutine 
end module

$ /usr/local/gfortran/bin/gfortran-4.5 -c abstract_algebra.f03 
abstract_algebra.f03:9.54:

    procedure(assign_interface) ,deferred :: assign   
                                                      1
Error: Assignment operator interface at (1) must not redefine an INTRINSIC type assignment
abstract_algebra.f03:34.14:

    operand = operand*scale           ! preferred implementation 
              1
Error: Operands of binary numeric operator '*' at (1) are CLASS(object)/REAL(4)
abstract_algebra.f03:35.14:

    operand = operand%product(scale)  
              1
Error: ABSTRACT INTERFACE 'product_interface' must not be referenced at (1)

$ /usr/local/gfortran/bin/gfortran-4.5 --version
GNU Fortran (GCC) 4.5.0 20090925 (experimental)
Comment 1 janus 2009-10-06 13:22:14 UTC
The first error message can be trivially fixed by:

Index: interface.c
===================================================================
--- interface.c (Revision 152488)
+++ interface.c (Arbeitskopie)
@@ -626,6 +626,7 @@ gfc_check_operator_interface (gfc_symbol *sym, gfc
         - Types and kinds do not conform, and
         - First argument is of derived type.  */
       if (sym->formal->sym->ts.type != BT_DERIVED
+         && sym->formal->sym->ts.type != BT_CLASS
          && (r1 == 0 || r1 == r2)
          && (sym->formal->sym->ts.type == sym->formal->next->sym->ts.type
              || (gfc_numeric_ts (&sym->formal->sym->ts)

The other two may be a bit harder.
Comment 2 janus 2009-11-04 19:41:22 UTC
Subject: Bug 41556

Author: janus
Date: Wed Nov  4 19:41:07 2009
New Revision: 153911

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153911
Log:
2009-11-04  Tobias Burnus <burnus@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	PR fortran/41937
	* interface.c (gfc_check_operator_interface): Handle CLASS arguments.
	* resolve.c (resolve_allocate_expr): Handle allocatable components of
	CLASS variables.


2009-11-04  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	PR fortran/41937
	* gfortran.dg/class_11.f03: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/class_11.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog

Comment 3 janus 2009-11-04 19:55:35 UTC
The commit in comment #2 contains the patchlet from comment #1 and fixes the first of the error messages in comment #0.

At this point, the test case still triggers three error messages:

c0.f90:34.14:

    operand = operand*scale           ! preferred implementation
              1
Error: Operands of binary numeric operator '*' at (1) are CLASS(object)/REAL(4)
c0.f90:35.14:

    operand = operand%product(scale)  ! alternate implementation
              1
Error: ABSTRACT INTERFACE 'product_interface' must not be referenced at (1)
c0.f90:35.14:

    operand = operand%product(scale)  ! alternate implementation
              1
Error: ABSTRACT INTERFACE 'product_interface' must not be referenced at (1)

The last two also appear in PR 41873.
Comment 4 janus 2009-11-05 10:43:00 UTC
Subject: Bug 41556

Author: janus
Date: Thu Nov  5 10:42:48 2009
New Revision: 153934

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153934
Log:
2009-11-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	PR fortran/41873
	* resolve.c (resolve_function,resolve_call): Prevent abstract interfaces
	from being called, but allow deferred type-bound procedures with
	abstract interface.


2009-11-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	PR fortran/41873
	* gfortran.dg/interface_abstract_4.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/interface_abstract_4.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog

Comment 5 janus 2009-11-05 11:52:56 UTC
r153934 fixes the third error message in comment #0. The output for the test case is now:

c0.f90:34.14:

    operand = operand*scale           ! preferred implementation
              1
Error: Operands of binary numeric operator '*' at (1) are CLASS(object)/REAL(4)
c0.f90:35.4:

    operand = operand%product(scale)  ! alternate implementation
    1
Error: Variable must not be polymorphic in assignment at (1)
Comment 6 janus 2009-11-05 13:43:26 UTC
(In reply to comment #5)
>     operand = operand%product(scale)  ! alternate implementation
>     1
> Error: Variable must not be polymorphic in assignment at (1)

This error message has been added in r152919, as a fix for PR41719. In principle it should only apply to intrinsic assignments (cf. F03 standard, section 7.4.1.2), but it falsely rejects the defined assignment in the test case.
Comment 7 janus 2009-11-05 14:27:59 UTC
Here is a patch which fixes both errors in comment #5, and thereby makes the test case in comment #0 compile cleanly:

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c     (revision 153933)
+++ gcc/fortran/interface.c     (working copy)
@@ -2574,13 +2574,16 @@ matching_typebound_op (gfc_expr** tb_base,
   gfc_actual_arglist* base;

   for (base = args; base; base = base->next)
-    if (base->expr->ts.type == BT_DERIVED)
+    if (base->expr->ts.type == BT_DERIVED || base->expr->ts.type == BT_CLASS)
       {
        gfc_typebound_proc* tb;
        gfc_symbol* derived;
        gfc_try result;

-       derived = base->expr->ts.u.derived;
+       if (base->expr->ts.type == BT_CLASS)
+         derived = base->expr->ts.u.derived->components->ts.u.derived;
+       else
+         derived = base->expr->ts.u.derived;

        if (op == INTRINSIC_USER)
          {
@@ -2837,7 +2840,7 @@ gfc_extend_assign (gfc_code *c, gfc_namespace *ns)
   rhs = c->expr2;

   /* Don't allow an intrinsic assignment to be replaced.  */
-  if (lhs->ts.type != BT_DERIVED
+  if (lhs->ts.type != BT_DERIVED && lhs->ts.type != BT_CLASS
       && (rhs->rank == 0 || rhs->rank == lhs->rank)
       && (lhs->ts.type == rhs->ts.type
          || (gfc_numeric_ts (&lhs->ts) && gfc_numeric_ts (&rhs->ts))))


I will regtest this now and (if successful) commit as obvious.
Comment 8 janus 2009-11-05 15:31:27 UTC
Subject: Bug 41556

Author: janus
Date: Thu Nov  5 15:31:07 2009
New Revision: 153946

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=153946
Log:
2009-11-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	* interface.c (matching_typebound_op,gfc_extend_assign): Handle CLASS
	variables.

2009-11-05  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41556
	* gfortran.dg/class_12.f03: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/class_12.f03
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/testsuite/ChangeLog

Comment 9 janus 2009-11-05 15:33:00 UTC
Fixed with r153946. Closing.