diff options
Diffstat (limited to 'gcc/fortran/check.cc')
-rw-r--r-- | gcc/fortran/check.cc | 161 |
1 files changed, 115 insertions, 46 deletions
diff --git a/gcc/fortran/check.cc b/gcc/fortran/check.cc index 3545864..9c66c25 100644 --- a/gcc/fortran/check.cc +++ b/gcc/fortran/check.cc @@ -67,7 +67,7 @@ gfc_invalid_boz (const char *msg, locus *loc) return false; } - const char *hint = _(" [see %<-fno-allow-invalid-boz%>]"); + const char *hint = _(" [see %<-fallow-invalid-boz%>]"); size_t len = strlen (msg) + strlen (hint) + 1; char *msg2 = (char *) alloca (len); strcpy (msg2, msg); @@ -2442,31 +2442,24 @@ gfc_check_co_broadcast (gfc_expr *a, gfc_expr *source_image, gfc_expr *stat, } -bool -gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image, - gfc_expr *stat, gfc_expr *errmsg) +/* Helper function for character arguments in gfc_check_[co_]reduce. */ + +static unsigned long +get_ul_from_cst_cl (const gfc_charlen *cl) +{ + return cl && cl->length && cl->length->expr_type == EXPR_CONSTANT + ? mpz_get_ui (cl->length->value.integer) : 0; +}; + + +/* Checks shared between co_reduce and reduce. */ +static bool +check_operation (gfc_expr *op, gfc_expr *a, bool is_co_reduce) { symbol_attribute attr; gfc_formal_arglist *formal; gfc_symbol *sym; - if (a->ts.type == BT_CLASS) - { - gfc_error ("The A argument at %L of CO_REDUCE shall not be polymorphic", - &a->where); - return false; - } - - if (gfc_expr_attr (a).alloc_comp) - { - gfc_error ("Support for the A argument at %L with allocatable components" - " is not yet implemented", &a->where); - return false; - } - - if (!check_co_collective (a, result_image, stat, errmsg, true)) - return false; - if (!gfc_resolve_expr (op)) return false; @@ -2483,8 +2476,9 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image, /* None of the intrinsics fulfills the criteria of taking two arguments, returning the same type and kind as the arguments and being permitted as actual argument. */ - gfc_error ("Intrinsic function %s at %L is not permitted for CO_REDUCE", - op->symtree->n.sym->name, &op->where); + gfc_error ("Intrinsic function %s at %L is not permitted for %s", + op->symtree->n.sym->name, &op->where, + is_co_reduce ? "CO_REDUCE" : "REDUCE"); return false; } @@ -2510,12 +2504,14 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image, if (!gfc_compare_types (&a->ts, &sym->result->ts)) { - gfc_error ("The A argument at %L has type %s but the function passed as " - "OPERATION at %L returns %s", + gfc_error ("The %s argument at %L has type %s but the function passed " + "as OPERATION at %L returns %s", + is_co_reduce ? "A" : "ARRAY", &a->where, gfc_typename (a), &op->where, gfc_typename (&sym->result->ts)); return false; } + if (!gfc_compare_types (&a->ts, &formal->sym->ts) || !gfc_compare_types (&a->ts, &formal->next->sym->ts)) { @@ -2567,42 +2563,59 @@ gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image, if (a->ts.type == BT_CHARACTER) { - gfc_charlen *cl; unsigned long actual_size, formal_size1, formal_size2, result_size; - cl = a->ts.u.cl; - actual_size = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT - ? mpz_get_ui (cl->length->value.integer) : 0; - - cl = formal->sym->ts.u.cl; - formal_size1 = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT - ? mpz_get_ui (cl->length->value.integer) : 0; - - cl = formal->next->sym->ts.u.cl; - formal_size2 = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT - ? mpz_get_ui (cl->length->value.integer) : 0; - - cl = sym->ts.u.cl; - result_size = cl && cl->length && cl->length->expr_type == EXPR_CONSTANT - ? mpz_get_ui (cl->length->value.integer) : 0; + actual_size = get_ul_from_cst_cl (a->ts.u.cl); + formal_size1 = get_ul_from_cst_cl (formal->sym->ts.u.cl); + formal_size2 = get_ul_from_cst_cl (formal->next->sym->ts.u.cl); + result_size = get_ul_from_cst_cl (sym->ts.u.cl); if (actual_size && ((formal_size1 && actual_size != formal_size1) || (formal_size2 && actual_size != formal_size2))) { - gfc_error ("The character length of the A argument at %L and of the " - "arguments of the OPERATION at %L shall be the same", - &a->where, &op->where); + gfc_error ("The character length of the %s argument at %L and of " + "the arguments of the OPERATION at %L shall be the same", + is_co_reduce ? "A" : "ARRAY", &a->where, &op->where); return false; } + if (actual_size && result_size && actual_size != result_size) { - gfc_error ("The character length of the A argument at %L and of the " - "function result of the OPERATION at %L shall be the same", + gfc_error ("The character length of the %s argument at %L and of " + "the function result of the OPERATION at %L shall be the " + "same", is_co_reduce ? "A" : "ARRAY", &a->where, &op->where); return false; } } + return true; +} + + +bool +gfc_check_co_reduce (gfc_expr *a, gfc_expr *op, gfc_expr *result_image, + gfc_expr *stat, gfc_expr *errmsg) +{ + if (a->ts.type == BT_CLASS) + { + gfc_error ("The A argument at %L of CO_REDUCE shall not be polymorphic", + &a->where); + return false; + } + + if (gfc_expr_attr (a).alloc_comp) + { + gfc_error ("Support for the A argument at %L with allocatable components" + " is not yet implemented", &a->where); + return false; + } + + if (!check_co_collective (a, result_image, stat, errmsg, true)) + return false; + + if (!check_operation (op, a, true)) + return false; return true; } @@ -5136,6 +5149,62 @@ gfc_check_real (gfc_expr *a, gfc_expr *kind) bool +gfc_check_reduce (gfc_expr *array, gfc_expr *operation, gfc_expr *dim, + gfc_expr *mask, gfc_expr *identity, gfc_expr *ordered) +{ + if (array->ts.type == BT_CLASS) + { + gfc_error ("The ARRAY argument at %L of REDUCE shall not be polymorphic", + &array->where); + return false; + } + + if (!check_operation (operation, array, false)) + return false; + + if (dim && (dim->rank || dim->ts.type != BT_INTEGER)) + { + gfc_error ("The DIM argument at %L, if present, must be an integer " + "scalar", &dim->where); + return false; + } + + if (mask && (array->rank != mask->rank || mask->ts.type != BT_LOGICAL)) + { + gfc_error ("The MASK argument at %L, if present, must be a logical " + "array with the same rank as ARRAY", &mask->where); + return false; + } + + if (mask + && !gfc_check_conformance (array, mask, + _("arguments '%s' and '%s' for intrinsic %s"), + "ARRAY", "MASK", "REDUCE")) + return false; + + if (mask && !identity) + gfc_warning (0, "MASK present at %L without IDENTITY", &mask->where); + + if (ordered && (ordered->rank || ordered->ts.type != BT_LOGICAL)) + { + gfc_error ("The ORDERED argument at %L, if present, must be a logical " + "scalar", &ordered->where); + return false; + } + + if (identity && (identity->rank + || !gfc_compare_types (&array->ts, &identity->ts))) + { + gfc_error ("The IDENTITY argument at %L, if present, must be a scalar " + "with the same type as ARRAY", &identity->where); + return false; + } + + return true; +} + + +bool gfc_check_rename (gfc_expr *path1, gfc_expr *path2) { if (!type_check (path1, 0, BT_CHARACTER)) |