/* Check type and rank. */
if (type_must_agree && !compare_type_rank (s2, s1))
{
- if (errmsg != NULL)
- snprintf (errmsg, err_len, "Type/rank mismatch in argument '%s'",
- s1->name);
+ snprintf (errmsg, err_len, "Type/rank mismatch in argument '%s'",
+ s1->name);
return FAILURE;
}
}
+/* Check if the characteristics of two function results match,
+ cf. F08:12.3.3. */
+
+static gfc_try
+check_result_characteristics (gfc_symbol *s1, gfc_symbol *s2,
+ char *errmsg, int err_len)
+{
+ gfc_symbol *r1, *r2;
+
+ r1 = s1->result ? s1->result : s1;
+ r2 = s2->result ? s2->result : s2;
+
+ if (r1->ts.type == BT_UNKNOWN)
+ return SUCCESS;
+
+ /* Check type and rank. */
+ if (!compare_type_rank (r1, r2))
+ {
+ snprintf (errmsg, err_len, "Type/rank mismatch in function result");
+ return FAILURE;
+ }
+
+ /* Check ALLOCATABLE attribute. */
+ if (r1->attr.allocatable != r2->attr.allocatable)
+ {
+ snprintf (errmsg, err_len, "ALLOCATABLE attribute mismatch in "
+ "function result");
+ return FAILURE;
+ }
+
+ /* Check POINTER attribute. */
+ if (r1->attr.pointer != r2->attr.pointer)
+ {
+ snprintf (errmsg, err_len, "POINTER attribute mismatch in "
+ "function result");
+ return FAILURE;
+ }
+
+ /* Check CONTIGUOUS attribute. */
+ if (r1->attr.contiguous != r2->attr.contiguous)
+ {
+ snprintf (errmsg, err_len, "CONTIGUOUS attribute mismatch in "
+ "function result");
+ return FAILURE;
+ }
+
+ /* Check PROCEDURE POINTER attribute. */
+ if (r1 != s1 && r1->attr.proc_pointer != r2->attr.proc_pointer)
+ {
+ snprintf (errmsg, err_len, "PROCEDURE POINTER mismatch in "
+ "function result");
+ return FAILURE;
+ }
+
+ /* Check string length. */
+ if (r1->ts.type == BT_CHARACTER && r1->ts.u.cl && r2->ts.u.cl)
+ {
+ if (r1->ts.deferred != r2->ts.deferred)
+ {
+ snprintf (errmsg, err_len, "Character length mismatch "
+ "in function result");
+ return FAILURE;
+ }
+
+ if (r1->ts.u.cl->length)
+ {
+ int compval = gfc_dep_compare_expr (r1->ts.u.cl->length,
+ r2->ts.u.cl->length);
+ switch (compval)
+ {
+ case -1:
+ case 1:
+ case -3:
+ snprintf (errmsg, err_len, "Character length mismatch "
+ "in function result");
+ return FAILURE;
+
+ case -2:
+ /* FIXME: Implement a warning for this case.
+ snprintf (errmsg, err_len, "Possible character length mismatch "
+ "in function result");*/
+ break;
+
+ case 0:
+ break;
+
+ default:
+ gfc_internal_error ("check_result_characteristics (1): Unexpected "
+ "result %i of gfc_dep_compare_expr", compval);
+ break;
+ }
+ }
+ }
+
+ /* Check array shape. */
+ if (!r1->attr.allocatable && !r1->attr.pointer && r1->as && r2->as)
+ {
+ int i, compval;
+ gfc_expr *shape1, *shape2;
+
+ if (r1->as->type != r2->as->type)
+ {
+ snprintf (errmsg, err_len, "Shape mismatch in function result");
+ return FAILURE;
+ }
+
+ if (r1->as->type == AS_EXPLICIT)
+ for (i = 0; i < r1->as->rank + r1->as->corank; i++)
+ {
+ shape1 = gfc_subtract (gfc_copy_expr (r1->as->upper[i]),
+ gfc_copy_expr (r1->as->lower[i]));
+ shape2 = gfc_subtract (gfc_copy_expr (r2->as->upper[i]),
+ gfc_copy_expr (r2->as->lower[i]));
+ compval = gfc_dep_compare_expr (shape1, shape2);
+ gfc_free_expr (shape1);
+ gfc_free_expr (shape2);
+ switch (compval)
+ {
+ case -1:
+ case 1:
+ case -3:
+ snprintf (errmsg, err_len, "Shape mismatch in dimension %i of "
+ "function result", i + 1);
+ return FAILURE;
+
+ case -2:
+ /* FIXME: Implement a warning for this case.
+ gfc_warning ("Possible shape mismatch in return value");*/
+ break;
+
+ case 0:
+ break;
+
+ default:
+ gfc_internal_error ("check_result_characteristics (2): "
+ "Unexpected result %i of "
+ "gfc_dep_compare_expr", compval);
+ break;
+ }
+ }
+ }
+
+ return SUCCESS;
+}
+
+
/* 'Compare' two formal interfaces associated with a pair of symbols.
We return nonzero if there exists an actual argument list that
would be ambiguous between the two interfaces, zero otherwise.
{
if (s1->attr.function && s2->attr.function)
{
- /* If both are functions, check result type. */
- if (s1->ts.type == BT_UNKNOWN)
- return 1;
- if (!compare_type_rank (s1,s2))
- {
- if (errmsg != NULL)
- snprintf (errmsg, err_len, "Type/rank mismatch in return value "
- "of '%s'", name2);
- return 0;
- }
-
- /* FIXME: Check array bounds and string length of result. */
+ /* If both are functions, check result characteristics. */
+ if (check_result_characteristics (s1, s2, errmsg, err_len)
+ == FAILURE)
+ return 0;
}
if (s1->attr.pure && !s2->attr.pure)
gfc_check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
{
locus where;
- const gfc_symbol *proc_target, *old_target;
+ gfc_symbol *proc_target, *old_target;
unsigned proc_pass_arg, old_pass_arg, argpos;
gfc_formal_arglist *proc_formal, *old_formal;
bool check_type;
" FUNCTION", proc->name, &where);
return FAILURE;
}
-
- /* FIXME: Do more comprehensive checking (including, for instance, the
- array-shape). */
- gcc_assert (proc_target->result && old_target->result);
- if (!compare_type_rank (proc_target->result, old_target->result))
- {
- gfc_error ("'%s' at %L and the overridden FUNCTION should have"
- " matching result types and ranks", proc->name, &where);
- return FAILURE;
- }
- /* Check string length. */
- if (proc_target->result->ts.type == BT_CHARACTER
- && proc_target->result->ts.u.cl && old_target->result->ts.u.cl)
+ if (check_result_characteristics (proc_target, old_target,
+ err, sizeof(err)) == FAILURE)
{
- int compval = gfc_dep_compare_expr (proc_target->result->ts.u.cl->length,
- old_target->result->ts.u.cl->length);
- switch (compval)
- {
- case -1:
- case 1:
- case -3:
- gfc_error ("Character length mismatch between '%s' at '%L' and "
- "overridden FUNCTION", proc->name, &where);
- return FAILURE;
-
- case -2:
- gfc_warning ("Possible character length mismatch between '%s' at"
- " '%L' and overridden FUNCTION", proc->name, &where);
- break;
-
- case 0:
- break;
-
- default:
- gfc_internal_error ("gfc_check_typebound_override: Unexpected "
- "result %i of gfc_dep_compare_expr", compval);
- break;
- }
+ gfc_error ("Result mismatch for the overriding procedure "
+ "'%s' at %L: %s", proc->name, &where, err);
+ return FAILURE;
}
}