aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-expr.c
diff options
context:
space:
mode:
authorBernd Edlinger <bernd.edlinger@hotmail.de>2014-12-10 15:29:19 +0000
committerBernd Edlinger <edlinger@gcc.gnu.org>2014-12-10 15:29:19 +0000
commit301375fdd557a3ae056580ee3f692ce2bbcc67ad (patch)
tree9846d76a16419247ccbfb3e90de4017076721789 /gcc/fortran/trans-expr.c
parentd7290d1cf47c1b910823af3d42075a76b46b0c31 (diff)
downloadgcc-301375fdd557a3ae056580ee3f692ce2bbcc67ad.zip
gcc-301375fdd557a3ae056580ee3f692ce2bbcc67ad.tar.gz
gcc-301375fdd557a3ae056580ee3f692ce2bbcc67ad.tar.bz2
re PR fortran/60718 (Test case gfortran.dg/select_type_4.f90 fails on ARM)
2014-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de> PR fortran/60718 * trans-expr.c (gfc_conv_procedure_call): Fix a strict aliasing violation when passing a class object to a formal parameter which has different pointer or allocatable attributes. testsuite: 2014-12-10 Bernd Edlinger <bernd.edlinger@hotmail.de> PR fortran/60718 * gfortran.dg/class_alias.f90: New. From-SVN: r218584
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r--gcc/fortran/trans-expr.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 7bdcc72..a82203c 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -4430,6 +4430,55 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
fsym->attr.optional
&& e->expr_type == EXPR_VARIABLE);
}
+ else if (e->ts.type == BT_CLASS && fsym
+ && fsym->ts.type == BT_CLASS
+ && !CLASS_DATA (fsym)->as
+ && !CLASS_DATA (e)->as
+ && (CLASS_DATA (fsym)->attr.class_pointer
+ != CLASS_DATA (e)->attr.class_pointer
+ || CLASS_DATA (fsym)->attr.allocatable
+ != CLASS_DATA (e)->attr.allocatable))
+ {
+ type = gfc_typenode_for_spec (&fsym->ts);
+ var = gfc_create_var (type, fsym->name);
+ gfc_conv_expr (&parmse, e);
+ if (fsym->attr.optional
+ && e->expr_type == EXPR_VARIABLE
+ && e->symtree->n.sym->attr.optional)
+ {
+ stmtblock_t block;
+ tree cond;
+ tmp = gfc_build_addr_expr (NULL_TREE, parmse.expr);
+ cond = fold_build2_loc (input_location, NE_EXPR,
+ boolean_type_node, tmp,
+ fold_convert (TREE_TYPE (tmp),
+ null_pointer_node));
+ gfc_start_block (&block);
+ gfc_add_modify (&block, var,
+ fold_build1_loc (input_location,
+ VIEW_CONVERT_EXPR,
+ type, parmse.expr));
+ gfc_add_expr_to_block (&parmse.pre,
+ fold_build3_loc (input_location,
+ COND_EXPR, void_type_node,
+ cond, gfc_finish_block (&block),
+ build_empty_stmt (input_location)));
+ parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
+ parmse.expr = build3_loc (input_location, COND_EXPR,
+ TREE_TYPE (parmse.expr),
+ cond, parmse.expr,
+ fold_convert (TREE_TYPE (parmse.expr),
+ null_pointer_node));
+ }
+ else
+ {
+ gfc_add_modify (&parmse.pre, var,
+ fold_build1_loc (input_location,
+ VIEW_CONVERT_EXPR,
+ type, parmse.expr));
+ parmse.expr = gfc_build_addr_expr (NULL_TREE, var);
+ }
+ }
else
gfc_conv_expr_reference (&parmse, e);