This patch makes the LTO failures go away. It propagates the information that we want (non-)restrict types from gfc_trans_assignment_1 (where we have access to the LHS) down to gfc_conv_structure (where the type specialization happens). The call graph is roughly as follows (to be seen with a fixed font):
gfc_trans_assignment_1 [set restricted] \ +-> gfc_conv_expr <------------------------------+-------+ \ \ \ +-> gfc_conv_structure [use restricted] <----+-|-----+ | \ \| \| +-> gfc_conv_initializer ----------------+ + \ | +-> gfc_conv_array_initializer -----------+ To avoid polluting every function (and every caller) with a restricted flag I have added it to gfc_se, which has already a good deal of request specification flags. Unfortunately, gfc_conv_initializer and gfc_conv_array_initializer don't have a gfc_se arg, so they don't avoid the restricted argument. To avoid changing all gfc_conv_initializer callers it is made a wrapper around the function with the restricted argument. I didn't do the same for gfc_conv_array_initializer as it has a single caller, so the interface change is harmless/non-invasive. As I had to update the declaration I moved it from gfortran.h to trans-array.h by the way. OK?
2012-08-22 Mikael Morin <mik...@gcc.gnu.org> * trans.h (struct gfc_se): New flag want_restricted_types. * trans-expr.c (gfc_trans_assignment_1): Set the want_restricted_types field. (gfc_conv_structure): Use the new field to choose the variant type that is wanted. (gfc_conv_initializer): Make it a wrapper around the old function renamed to... (conv_initializer_1): ... this. Add the RESTRICTED argument. Pass it down. * gfortran.h (gfc_conv_array_initializer): Move declaration... * trans-array.h (gfc_conv_array_initializer): ... here. Add a boolean argument. * trans-array.c (gfc_conv_array_initializer): Add the RESTRICTED argument. Pass it down.
diff --git a/gfortran.h b/gfortran.h index 4c8a856..c11cb12 100644 --- a/gfortran.h +++ b/gfortran.h @@ -2837,7 +2837,6 @@ gfc_try gfc_array_size (gfc_expr *, mpz_t *); gfc_try gfc_array_dimen_size (gfc_expr *, int, mpz_t *); gfc_try gfc_array_ref_shape (gfc_array_ref *, mpz_t *); gfc_array_ref *gfc_find_array_ref (gfc_expr *); -tree gfc_conv_array_initializer (tree type, gfc_expr *); gfc_try spec_size (gfc_array_spec *, mpz_t *); gfc_try spec_dimen_size (gfc_array_spec *, int, mpz_t *); int gfc_is_compile_time_shape (gfc_array_spec *); diff --git a/trans-array.c b/trans-array.c index c350c3b..217d7b8 100644 --- a/trans-array.c +++ b/trans-array.c @@ -5309,7 +5309,7 @@ gfc_array_deallocate (tree descriptor, tree pstat, tree errmsg, tree errlen, We assume the frontend already did any expansions and conversions. */ tree -gfc_conv_array_initializer (tree type, gfc_expr * expr) +gfc_conv_array_initializer (tree type, gfc_expr * expr, bool restricted) { gfc_constructor *c; tree tmp; @@ -5329,9 +5329,10 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) case EXPR_CONSTANT: case EXPR_STRUCTURE: /* A single scalar or derived type value. Create an array with all - elements equal to that value. */ + elements equal to that value. */ gfc_init_se (&se, NULL); - + se.want_restricted_types = restricted; + if (expr->expr_type == EXPR_CONSTANT) gfc_conv_constant (&se, expr); else @@ -5398,7 +5399,8 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr) else range = NULL; - gfc_init_se (&se, NULL); + gfc_init_se (&se, NULL); + se.want_restricted_types = restricted; switch (c->expr->expr_type) { case EXPR_CONSTANT: diff --git a/trans-array.h b/trans-array.h index de03202..8d071b9 100644 --- a/trans-array.h +++ b/trans-array.h @@ -137,6 +137,8 @@ void gfc_conv_array_parameter (gfc_se *, gfc_expr *, bool, const gfc_symbol *, const char *, tree *); /* Evaluate and transpose a matrix expression. */ void gfc_conv_array_transpose (gfc_se *, gfc_expr *); +/* Creates a middle-end array constructor from a constant expression. */ +tree gfc_conv_array_initializer (tree, gfc_expr *, bool); /* These work with both descriptors and descriptorless arrays. */ tree gfc_conv_array_data (tree); diff --git a/trans-expr.c b/trans-expr.c index 9dab898..38c17a1 100644 --- a/trans-expr.c +++ b/trans-expr.c @@ -5166,12 +5166,13 @@ gfc_conv_array_constructor_expr (gfc_se * se, gfc_expr * expr) /* Build a static initializer. EXPR is the expression for the initial value. - The other parameters describe the variable of the component being - initialized. EXPR may be null. */ + The other parameters describe the variable of the component being + initialized. EXPR may be null. RESTRICTED asks for restrict-qualified + types. */ -tree -gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, - bool array, bool pointer, bool procptr) +static tree +conv_initializer_1 (gfc_expr * expr, gfc_typespec * ts, tree type, + bool array, bool pointer, bool procptr, bool restricted) { gfc_se se; @@ -5206,9 +5207,9 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, ctor = gfc_build_null_descriptor (type); /* Special case assigning an array to zero. */ else if (is_zero_initializer_p (expr)) - ctor = build_constructor (type, NULL); + ctor = build_constructor (type, NULL); else - ctor = gfc_conv_array_initializer (type, expr); + ctor = gfc_conv_array_initializer (type, expr, restricted); TREE_STATIC (ctor) = 1; return ctor; } @@ -5220,8 +5221,9 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, { gfc_init_se (&se, NULL); se.want_pointer = 1; + se.want_restricted_types = restricted; gfc_conv_expr (&se, expr); - gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR); + gcc_assert (TREE_CODE (se.expr) != CONSTRUCTOR); return se.expr; } } @@ -5232,6 +5234,7 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, case BT_DERIVED: case BT_CLASS: gfc_init_se (&se, NULL); + se.want_restricted_types = restricted; if (ts->type == BT_CLASS && expr->expr_type == EXPR_NULL) gfc_conv_structure (&se, gfc_class_null_initializer(ts), 1); else @@ -5255,7 +5258,18 @@ gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, } } } - + + +/* Build a static initializer using default (i.e. restrict-qualified) types. */ + +tree +gfc_conv_initializer (gfc_expr * expr, gfc_typespec * ts, tree type, + bool array, bool pointer, bool procptr) +{ + return conv_initializer_1 (expr, ts, type, array, pointer, procptr, true); +} + + static tree gfc_trans_subarray_assign (tree dest, gfc_component * cm, gfc_expr * expr) { @@ -5653,6 +5667,8 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) gcc_assert (se->ss == NULL); gcc_assert (expr->expr_type == EXPR_STRUCTURE); type = gfc_typenode_for_spec (&expr->ts); + if (!se->want_restricted_types) + type = gfc_nonrestricted_type (type); if (!init) { @@ -5691,10 +5707,14 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) } else { - val = gfc_conv_initializer (c->expr, &cm->ts, - TREE_TYPE (cm->backend_decl), - cm->attr.dimension, cm->attr.pointer, - cm->attr.proc_pointer); + tree component_type = TREE_TYPE (cm->backend_decl); + + if (!se->want_restricted_types) + component_type = gfc_nonrestricted_type (component_type); + val = conv_initializer_1 (c->expr, &cm->ts, component_type, + cm->attr.dimension, cm->attr.pointer, + cm->attr.proc_pointer, + se->want_restricted_types); /* Append it to the constructor list. */ CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val); @@ -7286,6 +7306,7 @@ gfc_trans_assignment_1 (gfc_expr * expr1, gfc_expr * expr2, bool init_flag, l_is_temp = (lss != gfc_ss_terminator && loop.temp_ss != NULL); /* Translate the expression. */ + rse.want_restricted_types = !(gfc_expr_attr (expr1).target); gfc_conv_expr (&rse, expr2); /* Stabilize a string length for temporaries. */ diff --git a/trans.h b/trans.h index 56b6c2f..7b67db9 100644 --- a/trans.h +++ b/trans.h @@ -89,6 +89,10 @@ typedef struct gfc_se unsigned want_coarray:1; + /* If set, we will use types with the restrict qualifier when building + structure and array constructors. */ + unsigned want_restricted_types:1; + /* Scalarization parameters. */ struct gfc_se *parent; struct gfc_ss *ss;