Bug 54603

Summary: [F03] Wrong code with structure constructor for proc-pointer components
Product: gcc Reporter: Tobias Burnus <burnus>
Component: fortranAssignee: Not yet assigned to anyone <unassigned>
Status: RESOLVED FIXED    
Severity: normal CC: burnus, janus, xarthisius.kk
Priority: P3 Keywords: ice-on-valid-code, wrong-code
Version: 4.8.0   
Target Milestone: ---   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2012-09-16 00:00:00
Attachments: Test case

Description Tobias Burnus 2012-09-16 19:58:50 UTC
Created attachment 28202 [details]
Test case

Reported by Kacper Kowalik via IRC.


Fortran 2003 (and 2008) allow to initialize procedure-pointer components via the structure constructor, quoting F2003:

"R459  component-data-source  is  expr  or  data-target  or  proc-target"

And the latter can be per R742 and
"C726   A procedure-name shall be the name of ... or a procedure pointer"


I assume we either take a pointer reference too much or too little, leading to both wrong code and an ICE, depending whether we pass the name of a procedure or a procedure pointer.


For
      this%a = ext_ptr(init, cleanup)
      this%a%init => init

gfortran generates

    ext_ptr.0.init = (void (*<T4b4>) (void)) init;
    ext_ptr.0.cleanup = (void (*<T4b4>) (void)) cleanup;
    this->_data->a = ext_ptr.0;

  this->_data->a.init = *init;

Note the missing "*" in the failing declaration.



While using proc-pointers in the initialization
  this%a = ext_ptr(this%a%init,this%a%cleanup)
gives an ICE in fold_convert_loc, bei fold-const.c:1880


The backtrace shows:

#0  fold_convert_loc (loc=0, type=0x2aaaac29f1f8, arg=<optimized out>) at gcc/fold-const.c:1880
#1  0x000000000063406b in gfc_trans_scalar_assign (lse=lse@entry=0x7fffffffcd70, rse=rse@entry=0x7fffffffcd20, ts=..., l_is_temp=l_is_temp@entry=true, 
    deep_copy=deep_copy@entry=false, dealloc=dealloc@entry=true) at /home/tobgcc/fortran/trans-expr.c:6427
#2  0x00000000006359b8 in gfc_trans_subcomponent_assign (expr=0x15e9210, cm=0x15e37e0, dest=0x2aaaac27c0e0) at gcc/fortran/trans-expr.c:5588
#3  gfc_trans_structure_assign (dest=0x2aaaac295be0, expr=<error reading variable: Unhandled dwarf expression opcode 0xfa>, 
    expr=<error reading variable: Unhandled dwarf expression opcode 0xfa>) at gcc/fortran/trans-expr.c:5635
Comment 1 Tobias Burnus 2012-09-16 20:53:30 UTC
For

  this%a = ext_ptr(this%a%init,this%a%cleanup)

and the code (in trans-expr.c)

5584       gfc_conv_expr (&se, expr);
...
5588       tmp = gfc_trans_scalar_assign (&lse, &se, cm->ts, true, false, true);

we have

(gdb) p debug_tree (se.expr)
 <parm_decl 0x2aaaac288380 init
    type <pointer_type 0x2aaaac2a2888
        type <pointer_type 0x2aaaac29f1f8 type <function_type 0x2aaaac29f150>

which is one "pointer_type" too much.

That's fixed by using:
      if (gfc_expr_attr (expr).proc_pointer)
        se.expr = gfc_build_addr_expr (NULL_TREE, se.expr);


However, that will fail for
      this%a = ext_ptr(init, cleanup)
as those have already too much indirection.



The following patch works, but I think the proper fix has to be in gfc_conv_variable/gfc_conv_ref.


--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -5584,2 +5584,9 @@ gfc_trans_subcomponent_assign (tree dest,
       gfc_conv_expr (&se, expr);
+      if (gfc_expr_attr (expr).proc_pointer)
+       {
+         if (expr->symtree->n.sym->attr.dummy && !expr->ref)
+           se.expr = build_fold_indirect_ref_loc (input_location, se.expr);
+         else
+           se.expr = gfc_build_addr_expr (NULL_TREE, se.expr);
+       }
       if (cm->ts.type == BT_CHARACTER)
Comment 2 janus 2012-09-16 21:19:09 UTC
Here is a reduced test case for the ICE:


  implicit none

  type :: ext_ptr
    procedure(), nopass, pointer :: init
  end type

  type(ext_ptr) :: this

  this = ext_ptr(this%init) ! ICE in fold_convert_loc

end
Comment 3 janus 2012-09-16 21:21:56 UTC
Loosely related: PR 50438.
Comment 4 Tobias Burnus 2012-09-17 12:30:29 UTC
Author: burnus
Date: Mon Sep 17 12:30:16 2012
New Revision: 191382

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=191382
Log:
2012-09-17  Tobias Burnus  <burnus@net-b.de>

        PR fortran/54603
        * trans-expr.c (gfc_trans_subcomponent_assign): Handle
        proc-pointer components.

2012-09-17  Tobias Burnus  <burnus@net-b.de>

        PR fortran/54603
        * gfortran.dg/structure_constructor_11.f90: New.


Added:
    trunk/gcc/testsuite/gfortran.dg/structure_constructor_11.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/trans-expr.c
    trunk/gcc/testsuite/ChangeLog
Comment 5 Tobias Burnus 2012-09-17 12:34:27 UTC
FIXED on the trunk (4.8).

Thanks for your report (and to your colleague for triggering the bug ;-).