diff mbox

[fortran,3/5] PR 45586: Use the right type to build structure constructors.

Message ID 20120824151014.6294.99503@marvin
State New
Headers show

Commit Message

Mikael Morin Aug. 24, 2012, 3:12 p.m. UTC
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  <mikael@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 mbox

Patch

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;