This patch avoids fold_convert bombing when the types are not variants of the
same base type.  It is necessary to avoid regressing with the next patch.
It tries to take the VIEW_CONVERT_EXPR path only when it is necessary and
use the usual fold_convert otherwise.  I use gfc_nonrestricted_type in one
assertion, so I had to make it public
For what it's worth, I had another version of this patch which tried harder to
not use VIEW_CONVERT_EXPR by carefully avoiding copying the data pointer
(which is overwritten just after anyway). However, as I didn't want to pull
in the scalarizer to assign arrays, I couldn't avoid VIEW_CONVERT_EXPR in
all cases, so I finally preferred this (simpler) patch.

OK?
2012-08-22  Mikael Morin  <mik...@gcc.gnu.org>

        PR fortran/45586
        * trans-expr.c (gfc_trans_scalar_assign): Wrap in a VIEW_CONVERT_EXPR
        node if the types don't match.
        * trans-types.c (gfc_nonrestricted_type): Make non-static.
        * trans.h (gfc_nonrestricted_type): New declaration.
diff --git a/trans-expr.c b/trans-expr.c
index ebaa238..9dab898 100644
--- a/trans-expr.c
+++ b/trans-expr.c
@@ -6396,8 +6396,24 @@ gfc_trans_scalar_assign (gfc_se * lse, gfc_se * rse, 
gfc_typespec ts,
       gfc_add_block_to_block (&block, &rse->pre);
       gfc_add_block_to_block (&block, &lse->pre);
 
-      gfc_add_modify (&block, lse->expr,
-                          fold_convert (TREE_TYPE (lse->expr), rse->expr));
+      tree converted = NULL_TREE;
+      if (TYPE_MAIN_VARIANT (TREE_TYPE (lse->expr))
+         != TYPE_MAIN_VARIANT (TREE_TYPE (rse->expr))
+         && !POINTER_TYPE_P (TREE_TYPE (lse->expr))
+         && !POINTER_TYPE_P (TREE_TYPE (rse->expr)))
+       {
+         gcc_assert (TYPE_CANONICAL (TREE_TYPE (lse->expr))
+                     == TYPE_CANONICAL (TREE_TYPE (rse->expr))
+                     && gfc_nonrestricted_type (TREE_TYPE (lse->expr))
+                        == gfc_nonrestricted_type (TREE_TYPE (rse->expr)));
+         /* fold_convert won't like this.  Let's bypass it.  */
+         converted = fold_build1_loc (input_location, VIEW_CONVERT_EXPR,
+                                      TREE_TYPE (lse->expr), rse->expr);
+       }
+      else
+       converted = fold_convert (TREE_TYPE (lse->expr), rse->expr);
+
+      gfc_add_modify (&block, lse->expr, converted);
 
       /* Do a deep copy if the rhs is a variable, if it is not the
         same as the lhs.  */
diff --git a/trans-types.c b/trans-types.c
index 3286a5a..a6e5d99 100644
--- a/trans-types.c
+++ b/trans-types.c
@@ -1924,7 +1924,6 @@ gfc_build_pointer_type (gfc_symbol * sym, tree type)
     return build_pointer_type (type);
 }
 
-static tree gfc_nonrestricted_type (tree t);
 /* Given two record or union type nodes TO and FROM, ensure
    that all fields in FROM have a corresponding field in TO,
    their type being nonrestrict variants.  This accepts a TO
@@ -1973,7 +1972,7 @@ mirror_fields (tree to, tree from)
 /* Given a type T, returns a different type of the same structure,
    except that all types it refers to (recursively) are always
    non-restrict qualified types.  */
-static tree
+tree
 gfc_nonrestricted_type (tree t)
 {
   tree ret = t;
diff --git a/trans.h b/trans.h
index 9818ceb..56b6c2f 100644
--- a/trans.h
+++ b/trans.h
@@ -639,6 +639,7 @@ tree getdecls (void);
 /* In trans-types.c.  */
 struct array_descr_info;
 bool gfc_get_array_descr_info (const_tree, struct array_descr_info *);
+tree gfc_nonrestricted_type (tree);
 
 /* In trans-openmp.c */
 bool gfc_omp_privatize_by_reference (const_tree);

Reply via email to