Summary: | [F03] Wrong code with structure constructor for proc-pointer components | ||
---|---|---|---|
Product: | gcc | Reporter: | Tobias Burnus <burnus> |
Component: | fortran | Assignee: | 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 |
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) 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 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 FIXED on the trunk (4.8). Thanks for your report (and to your colleague for triggering the bug ;-). |
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