aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2010-12-24 08:42:04 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2010-12-24 08:42:04 +0000
commit07818af47b961b903aee005f6771e14730d3e003 (patch)
treeba500f5c6a595579533936d48e7faf3bf7b7a1d0 /gcc/fortran
parentab9d6dcfbeced3e2e0052c1cacb541e79e622bdf (diff)
downloadgcc-07818af47b961b903aee005f6771e14730d3e003.zip
gcc-07818af47b961b903aee005f6771e14730d3e003.tar.gz
gcc-07818af47b961b903aee005f6771e14730d3e003.tar.bz2
re PR fortran/31821 (character pointer => target(range) should detect if lengths don't match)
2010-12-24 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/31821 * check.c (gfc_var_strlen): New function, also including substring references. (gfc_check_same_strlen): Use gfc_var_strlen. 2010-12-24 Thomas Koenig <tkoenig@gcc.gnu.org> PR fortran/31821 * gfortran.dg/char_pointer_assign_6.f90: New test. From-SVN: r168224
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog7
-rw-r--r--gcc/fortran/check.c77
2 files changed, 60 insertions, 24 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 4ffb3e3..980d1b1 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,10 @@
+2010-12-24 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/31821
+ * check.c (gfc_var_strlen): New function, also including
+ substring references.
+ (gfc_check_same_strlen): Use gfc_var_strlen.
+
2010-12-23 Mikael Morin <mikael.morin@gcc.gnu.org>
PR fortran/46978
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index ceea6f3..20163f9 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -635,40 +635,69 @@ identical_dimen_shape (gfc_expr *a, int ai, gfc_expr *b, int bi)
return ret;
}
+/* Calculate the length of a character variable, including substrings.
+ Strip away parentheses if necessary. Return -1 if no length could
+ be determined. */
+
+static long
+gfc_var_strlen (const gfc_expr *a)
+{
+ gfc_ref *ra;
+
+ while (a->expr_type == EXPR_OP && a->value.op.op == INTRINSIC_PARENTHESES)
+ a = a->value.op.op1;
+
+ for (ra = a->ref; ra != NULL && ra->type != REF_SUBSTRING; ra = ra->next)
+ ;
+
+ if (ra)
+ {
+ long start_a, end_a;
+
+ if (ra->u.ss.start->expr_type == EXPR_CONSTANT
+ && ra->u.ss.end->expr_type == EXPR_CONSTANT)
+ {
+ start_a = mpz_get_si (ra->u.ss.start->value.integer);
+ end_a = mpz_get_si (ra->u.ss.end->value.integer);
+ return end_a - start_a + 1;
+ }
+ else if (gfc_dep_compare_expr (ra->u.ss.start, ra->u.ss.end) == 0)
+ return 1;
+ else
+ return -1;
+ }
+
+ if (a->ts.u.cl && a->ts.u.cl->length
+ && a->ts.u.cl->length->expr_type == EXPR_CONSTANT)
+ return mpz_get_si (a->ts.u.cl->length->value.integer);
+ else if (a->expr_type == EXPR_CONSTANT
+ && (a->ts.u.cl == NULL || a->ts.u.cl->length == NULL))
+ return a->value.character.length;
+ else
+ return -1;
+
+}
/* Check whether two character expressions have the same length;
- returns SUCCESS if they have or if the length cannot be determined. */
+ returns SUCCESS if they have or if the length cannot be determined,
+ otherwise return FAILURE and raise a gfc_error. */
gfc_try
gfc_check_same_strlen (const gfc_expr *a, const gfc_expr *b, const char *name)
{
long len_a, len_b;
- len_a = len_b = -1;
-
- if (a->ts.u.cl && a->ts.u.cl->length
- && a->ts.u.cl->length->expr_type == EXPR_CONSTANT)
- len_a = mpz_get_si (a->ts.u.cl->length->value.integer);
- else if (a->expr_type == EXPR_CONSTANT
- && (a->ts.u.cl == NULL || a->ts.u.cl->length == NULL))
- len_a = a->value.character.length;
- else
- return SUCCESS;
- if (b->ts.u.cl && b->ts.u.cl->length
- && b->ts.u.cl->length->expr_type == EXPR_CONSTANT)
- len_b = mpz_get_si (b->ts.u.cl->length->value.integer);
- else if (b->expr_type == EXPR_CONSTANT
- && (b->ts.u.cl == NULL || b->ts.u.cl->length == NULL))
- len_b = b->value.character.length;
- else
- return SUCCESS;
+ len_a = gfc_var_strlen(a);
+ len_b = gfc_var_strlen(b);
- if (len_a == len_b)
+ if (len_a == -1 || len_b == -1 || len_a == len_b)
return SUCCESS;
-
- gfc_error ("Unequal character lengths (%ld/%ld) in %s at %L",
- len_a, len_b, name, &a->where);
- return FAILURE;
+ else
+ {
+ gfc_error ("Unequal character lengths (%ld/%ld) in %s at %L",
+ len_a, len_b, name, &a->where);
+ return FAILURE;
+ }
}