aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-expr.c
diff options
context:
space:
mode:
authorDaniel Kraft <d@domob.eu>2008-12-18 11:05:54 +0100
committerDaniel Kraft <domob@gcc.gnu.org>2008-12-18 11:05:54 +0100
commitfb5bc08bb353a574a011eaf5b7ae874672e4b289 (patch)
treec4d520f172c9b4f97852d08d4e5fc12e76b2adde /gcc/fortran/trans-expr.c
parentec81df7d4e83ddd28014e07e0eec7fe0e3559deb (diff)
downloadgcc-fb5bc08bb353a574a011eaf5b7ae874672e4b289.zip
gcc-fb5bc08bb353a574a011eaf5b7ae874672e4b289.tar.gz
gcc-fb5bc08bb353a574a011eaf5b7ae874672e4b289.tar.bz2
re PR fortran/31822 (Missing run-time bound checks for character pointer => target)
2008-12-18 Daniel Kraft <d@domob.eu> PR fortran/31822 * gfortran.h (gfc_check_same_strlen): Made public. * trans.h (gfc_trans_same_strlen_check): Made public. * check.c (gfc_check_same_strlen): Made public and adapted error message output to be useful not only for intrinsics. (gfc_check_merge): Adapt to gfc_check_same_strlen change. * expr.c (gfc_check_pointer_assign): Use gfc_check_same_strlen for string length compile-time check. * trans-expr.c (gfc_trans_pointer_assignment): Add runtime-check for equal string lengths using gfc_trans_same_strlen_check. * trans-intrinsic.c (gfc_trans_same_strlen_check): Renamed and made public from conv_same_strlen_check. (gfc_conv_intrinsic_merge): Adapted accordingly. 2008-12-18 Daniel Kraft <d@domob.eu> PR fortran/31822 * gfortran.dg/char_pointer_assign_2.f90: Updated expected error message to be more detailed. * gfortran.dg/char_pointer_assign_4.f90: New test. * gfortran.dg/char_pointer_assign_5.f90: New test. From-SVN: r142808
Diffstat (limited to 'gcc/fortran/trans-expr.c')
-rw-r--r--gcc/fortran/trans-expr.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 4a84234..5d41145 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -4016,7 +4016,6 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
tree tmp;
tree decl;
-
gfc_start_block (&block);
gfc_init_se (&lse, NULL);
@@ -4039,15 +4038,32 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
gfc_add_block_to_block (&block, &lse.pre);
gfc_add_block_to_block (&block, &rse.pre);
+
+ /* Check character lengths if character expression. The test is only
+ really added if -fbounds-check is enabled. */
+ if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL)
+ {
+ gcc_assert (expr2->ts.type == BT_CHARACTER);
+ gcc_assert (lse.string_length && rse.string_length);
+ gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
+ lse.string_length, rse.string_length,
+ &block);
+ }
+
gfc_add_modify (&block, lse.expr,
fold_convert (TREE_TYPE (lse.expr), rse.expr));
+
gfc_add_block_to_block (&block, &rse.post);
gfc_add_block_to_block (&block, &lse.post);
}
else
{
+ tree strlen_lhs;
+ tree strlen_rhs = NULL_TREE;
+
/* Array pointer. */
gfc_conv_expr_descriptor (&lse, expr1, lss);
+ strlen_lhs = lse.string_length;
switch (expr2->expr_type)
{
case EXPR_NULL:
@@ -4057,8 +4073,9 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
case EXPR_VARIABLE:
/* Assign directly to the pointer's descriptor. */
- lse.direct_byref = 1;
+ lse.direct_byref = 1;
gfc_conv_expr_descriptor (&lse, expr2, rss);
+ strlen_rhs = lse.string_length;
/* If this is a subreference array pointer assignment, use the rhs
descriptor element size for the lhs span. */
@@ -4071,7 +4088,7 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
tmp = gfc_get_element_type (TREE_TYPE (rse.expr));
tmp = fold_convert (gfc_array_index_type, size_in_bytes (tmp));
if (!INTEGER_CST_P (tmp))
- gfc_add_block_to_block (&lse.post, &rse.pre);
+ gfc_add_block_to_block (&lse.post, &rse.pre);
gfc_add_modify (&lse.post, GFC_DECL_SPAN(decl), tmp);
}
@@ -4086,10 +4103,23 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
lse.expr = tmp;
lse.direct_byref = 1;
gfc_conv_expr_descriptor (&lse, expr2, rss);
+ strlen_rhs = lse.string_length;
gfc_add_modify (&lse.pre, desc, tmp);
break;
- }
+ }
+
gfc_add_block_to_block (&block, &lse.pre);
+
+ /* Check string lengths if applicable. The check is only really added
+ to the output code if -fbounds-check is enabled. */
+ if (expr1->ts.type == BT_CHARACTER && expr2->expr_type != EXPR_NULL)
+ {
+ gcc_assert (expr2->ts.type == BT_CHARACTER);
+ gcc_assert (strlen_lhs && strlen_rhs);
+ gfc_trans_same_strlen_check ("pointer assignment", &expr1->where,
+ strlen_lhs, strlen_rhs, &block);
+ }
+
gfc_add_block_to_block (&block, &lse.post);
}
return gfc_finish_block (&block);