This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug fortran/45586] [4.6 Regression] ICE non-trivial conversion at assignment
- From: "mikael at gcc dot gnu.org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 25 Jan 2011 14:32:52 +0000
- Subject: [Bug fortran/45586] [4.6 Regression] ICE non-trivial conversion at assignment
- Auto-submitted: auto-generated
- References: <bug-45586-4@http.gcc.gnu.org/bugzilla/>
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45586
--- Comment #38 from Mikael Morin <mikael at gcc dot gnu.org> 2011-01-25 14:32:28 UTC ---
The patch looks good.
Somewhat hackish as you acknowledge, but worth submitting anyway.
A few minor comments below.
> Index: fortran/trans-expr.c
> ===================================================================
> --- fortran/trans-expr.c (revision 168749)
> +++ fortran/trans-expr.c (working copy)
> @@ -504,6 +504,19 @@ gfc_conv_component_ref (gfc_se * se, gfc
> field = c->backend_decl;
> gcc_assert (TREE_CODE (field) == FIELD_DECL);
> decl = se->expr;
> + if (DECL_CONTEXT (field) != TREE_TYPE (decl))
> + {
> + tree f2 = c->backend_decl2;
> + if (f2 && DECL_FIELD_CONTEXT (f2) == TREE_TYPE (decl))
> + ;
> + else for (f2 = TYPE_FIELDS (TREE_TYPE (decl)); f2; f2 = DECL_CHAIN (f2))
I prefer `if (!cond) ...' instead of `if (cond) ; else ...'
> Index: fortran/gfortran.h
> ===================================================================
> --- fortran/gfortran.h (revision 168749)
> +++ fortran/gfortran.h (working copy)
> @@ -934,6 +934,7 @@ typedef struct gfc_component
> gfc_array_spec *as;
>
> tree backend_decl;
> + tree backend_decl2;
More descriptive name (e.g. restrict_backend_decl or target_backend_decl or
...)
and comment explaining the need for it appreciated.
One could have the combinatorial explosion of backend_decls here as said
Michael. In any case it can be safely removed if needed, as it is just a cache.
> locus loc;
> struct gfc_expr *initializer;
> struct gfc_component *next;
> Index: fortran/trans-types.c
> ===================================================================
> --- fortran/trans-types.c (revision 168749)
> +++ fortran/trans-types.c (working copy)
> @@ -1746,6 +1746,80 @@ gfc_build_pointer_type (gfc_symbol * sym
> else
> return build_pointer_type (type);
> }
> +
> +static tree
> +gfc_nonrestricted_type (tree t)
> +{
> + tree ret = t;
> + if (!TYPE_LANG_SPECIFIC (t))
> + TYPE_LANG_SPECIFIC (t)
> + = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> + if (TYPE_LANG_SPECIFIC (t)->nonrestricted_type)
> + return TYPE_LANG_SPECIFIC (t)->nonrestricted_type;
> + switch (TREE_CODE (t))
> + {
> + default:
> + break;
> +
> + case POINTER_TYPE:
> + case REFERENCE_TYPE:
> + ret = build_qualified_type (t, TYPE_QUALS (t) & ~TYPE_QUAL_RESTRICT);
Isn't it necessary to call gfc_nonrestricted_type on TREE_TYPE (t) here ?
> + break;
> +
> + case ARRAY_TYPE:
> + {
> + tree elemtype = gfc_nonrestricted_type (TREE_TYPE (t));
> + if (elemtype == TREE_TYPE (t))
> + ret = t;
> + else
> + {
> + ret = copy_node (t);
> + TREE_TYPE (t) = elemtype;
> + /* ??? Change some TYPE_LANG_SPECIFICs too? */
> + }
> + }
> + break;
> +
> + case RECORD_TYPE:
> + case UNION_TYPE:
> + case QUAL_UNION_TYPE:
> + {
> + tree field, *chain;
> + for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
> + if (TREE_CODE (field) == FIELD_DECL)
> + {
> + tree elemtype = gfc_nonrestricted_type (TREE_TYPE (field));
> + if (elemtype != TREE_TYPE (field))
> + break;
> + }
> + if (!field)
> + break;
> + ret = copy_node (t);
> + TYPE_FIELDS (ret) = NULL_TREE;
> + chain = &TYPE_FIELDS (ret);
> + for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
> + {
> + tree newfield = copy_node (field);
> + DECL_CONTEXT (newfield) = ret;
> + DECL_CHAIN (newfield) = NULL_TREE;
> + if (TYPE_FIELDS (ret) == NULL_TREE)
> + TYPE_FIELDS (ret) = newfield;
Those two lines seem to duplicate the line below (as initially chain points to
&TYPE_FIELDS(ret)).
> + *chain = newfield;
> + chain = &DECL_CHAIN (newfield);
> +
> + if (TREE_CODE (field) == FIELD_DECL)
> + {
> + tree elemtype = gfc_nonrestricted_type (TREE_TYPE (field));
> + TREE_TYPE (newfield) = elemtype;
> + }
> + }
> + }
> + break;
> + }
> + TYPE_LANG_SPECIFIC (t)->nonrestricted_type = ret;
Don't know if it is absolutely necessary, but one might add also :
TYPE_LANG_SPECIFIC (ret)->nonrestricted_type = ret;
> + return ret;
> +}
> +
>
> /* Return the type for a symbol. Special handling is required for character
> types to get the correct level of indirection.
> @@ -1789,6 +1863,9 @@ gfc_sym_type (gfc_symbol * sym)
> else
> type = gfc_typenode_for_spec (&sym->ts);
>
> + if (sym->attr.pointer)
> + type = gfc_nonrestricted_type (type);
> +
This is missing the target attribute, so you may preferably use the restricted
boolean a few lines below.
> if (sym->attr.dummy && !sym->attr.function && !sym->attr.value)
> byref = 1;
> else
> Index: fortran/trans.h
> ===================================================================
> --- fortran/trans.h (revision 168749)
> +++ fortran/trans.h (working copy)
> @@ -700,6 +700,7 @@ struct GTY((variable_size)) lang_type {
> tree dataptr_type;
> tree span;
> tree base_decl[2];
> + tree nonrestricted_type;
> };
>
> struct GTY((variable_size)) lang_decl {