From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12261 invoked by alias); 24 Feb 2008 14:04:50 -0000 Received: (qmail 11790 invoked by uid 48); 24 Feb 2008 14:04:05 -0000 Date: Sun, 24 Feb 2008 14:04:00 -0000 Message-ID: <20080224140405.11789.qmail@sourceware.org> X-Bugzilla-Reason: CC References: Subject: [Bug fortran/34199] segfault for TRANSFER integer to TYPE(C_PTR) In-Reply-To: Reply-To: gcc-bugzilla@gcc.gnu.org To: gcc-bugs@gcc.gnu.org From: "fxcoudert at gcc dot gnu dot org" Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2008-02/txt/msg02553.txt.bz2 ------- Comment #3 from fxcoudert at gcc dot gnu dot org 2008-02-24 14:04 ------- The ICE itself can be gotten rid of by setting the offset of the private field of our ISO_C derived types: Index: trans-types.c =================================================================== --- trans-types.c (revision 132578) +++ trans-types.c (working copy) @@ -1731,6 +1731,7 @@ get_identifier (derived->components->name), gfc_typenode_for_spec ( &(derived->components->ts))); + DECL_FIELD_OFFSET (derived->components->backend_decl) = size_int (0); derived->ts.kind = gfc_index_integer_kind; derived->ts.type = BT_INTEGER; (Independently of the rest, I think that fix is desirable.) However, with that fix, we now error out: C_NULL_PTR1 = transfer(0_C_INTPTR_T, C_NULL_PTR1) 1 Error: Can't convert INTEGER(4) to TYPE(c_ptr) at (1) The reason for that is that gfc_typenode_for_spec(), which is called from gfc_interpret_derived(), modifies the symbol itself to make it an integer: /* If we're dealing with either C_PTR or C_FUNPTR, we modified the type and kind to fit a (void *) and the basetype returned was a ptr_type_node. We need to pass up this new information to the symbol that was declared of type C_PTR or C_FUNPTR. */ I have always been wary of this course of actions (magically making the ISO_C_BINDING derived types into scalar integer variables), and in that case it is biting us hard. I have tried to work around this in target-memory.c by a custom-tailored fix: Index: target-memory.c =================================================================== --- target-memory.c (revision 132578) +++ target-memory.c (working copy) @@ -379,7 +379,21 @@ /* The attributes of the derived type need to be bolted to the floor. */ result->expr_type = EXPR_STRUCTURE; - type = gfc_typenode_for_spec (&result->ts); + /* FIXME -- This is more of a workaround than a real fix, please see + PR34199 for details. + For ISO_C_BINDING derived types, gfc_typenode_for_spec() will change + the symbol under our feet into an integer, which we don't want, so + we restore it. */ + if (result->ts.type == BT_DERIVED && result->ts.derived->attr.is_iso_c) + { + gfc_typespec ts; + ts = result->ts; + type = gfc_typenode_for_spec (&result->ts); + result->ts = ts; + } + else + type = gfc_typenode_for_spec (&result->ts); + cmp = result->ts.derived->components; /* Run through the derived type components. */ This in turn makes the derived type constructors go into trans-expr.c's gfc_conv_expr(), which does not deal with them. This is fixed with the following patchlet: Index: trans-expr.c =================================================================== --- trans-expr.c (revision 132578) +++ trans-expr.c (working copy) @@ -3517,14 +3517,19 @@ } /* We need to convert the expressions for the iso_c_binding derived types. - C_NULL_PTR and C_NULL_FUNPTR will be made EXPR_NULL, which evaluates to - null_pointer_node. C_PTR and C_FUNPTR are converted to match the - typespec for the C_PTR and C_FUNPTR symbols, which has already been - updated to be an integer with a kind equal to the size of a (void *). */ + C_NULL_PTR, C_NULL_FUNPTR and constants (coming, for example, from the + simplification of TRANSFER expressions) will be made EXPR_NULL, + which evaluates to null_pointer_node. C_PTR and C_FUNPTR are converted + to match the typespec for the C_PTR and C_FUNPTR symbols, which has + already been updated to be an integer with a kind equal to the size of + a (void *). */ if (expr->ts.type == BT_DERIVED && expr->ts.derived && expr->ts.derived->attr.is_iso_c) { - if (expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR + /* expr->expr_type == EXPR_STRUCTURE matches the constant derived + types. */ + if (expr->expr_type == EXPR_STRUCTURE + || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_PTR || expr->symtree->n.sym->intmod_sym_id == ISOCBINDING_NULL_FUNPTR) { /* Set expr_type to EXPR_NULL, which will result in Now, with all three patches, we can compile the testcase and run it fine. I'm not really satisfied with the patch to target-memory.c, as it is more a workaround than a patch. For that reason, I'm not assigning this to myself and will let the ISO_C_BINDING experts decide what course is most appropriate. -- fxcoudert at gcc dot gnu dot org changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |fxcoudert at gcc dot gnu dot | |org Keywords| |patch Last reconfirmed|2007-11-25 03:11:32 |2008-02-24 14:04:05 date| | http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34199