return check_externals_procedure (sym, loc, actual);
}
-/* Called routine. */
+/* Function to check if any interface clashes with a global
+ identifier, to be invoked via gfc_traverse_ns. */
-void
-gfc_check_externals (gfc_namespace *ns)
+static void
+check_against_globals (gfc_symbol *sym)
{
+ gfc_gsymbol *gsym;
+ gfc_symbol *def_sym = NULL;
+ const char *sym_name;
+ char buf [200];
- gfc_clear_error ();
+ if (sym->attr.if_source != IFSRC_IFBODY || sym->attr.flavor != FL_PROCEDURE
+ || sym->attr.generic || sym->error)
+ return;
- /* Turn errors into warnings if the user indicated this. */
+ if (sym->binding_label)
+ sym_name = sym->binding_label;
+ else
+ sym_name = sym->name;
- if (!pedantic && flag_allow_argument_mismatch)
- gfc_errors_to_warnings (true);
+ gsym = gfc_find_gsymbol (gfc_gsym_root, sym_name);
+ if (gsym && gsym->ns)
+ gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
+
+ if (!def_sym || def_sym->error || def_sym->attr.generic)
+ return;
+
+ buf[0] = 0;
+ gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1, buf, sizeof(buf),
+ NULL, NULL, NULL);
+ if (buf[0] != 0)
+ {
+ gfc_warning (0, "%s between %L and %L", buf, &def_sym->declared_at,
+ &sym->declared_at);
+ sym->error = 1;
+ def_sym->error = 1;
+ }
+
+}
+
+/* Do the code-walkling part for gfc_check_externals. */
+static void
+gfc_check_externals0 (gfc_namespace *ns)
+{
gfc_code_walker (&ns->code, check_externals_code, check_externals_expr, NULL);
for (ns = ns->contained; ns; ns = ns->sibling)
{
if (ns->code == NULL || ns->code->op != EXEC_BLOCK)
- gfc_check_externals (ns);
+ gfc_check_externals0 (ns);
}
+}
+
+/* Called routine. */
+
+void gfc_check_externals (gfc_namespace *ns)
+{
+ gfc_clear_error ();
+
+ /* Turn errors into warnings if the user indicated this. */
+
+ if (!pedantic && flag_allow_argument_mismatch)
+ gfc_errors_to_warnings (true);
+
+ gfc_check_externals0 (ns);
+ gfc_traverse_ns (ns, check_against_globals);
+
gfc_errors_to_warnings (false);
}
+
}
-/* Generate an error if a symbol is ambiguous. */
+/* Generate an error if a symbol is ambiguous, and set the error flag
+ on it. */
static void
ambiguous_symbol (const char *name, gfc_symtree *st)
{
+ if (st->n.sym->error)
+ return;
+
if (st->n.sym->module)
gfc_error ("Name %qs at %C is an ambiguous reference to %qs "
"from module %qs", name, st->n.sym->name, st->n.sym->module);
else
gfc_error ("Name %qs at %C is an ambiguous reference to %qs "
"from current program unit", name, st->n.sym->name);
+
+ st->n.sym->error = 1;
}
--- /dev/null
+! PR fortran/27318
+! { dg-do compile }
+! This tests for mismatch between the interface for a global
+! procedure and the procedure itself.
+
+module test
+implicit none
+interface
+ subroutine hello(n) ! { dg-warning "INTENT mismatch" }
+ integer :: n
+ end subroutine hello
+end interface
+end module test
+
+subroutine hello(n) ! { dg-warning "INTENT mismatch" }
+ integer, intent(in) :: n
+ integer :: i
+ do i = 1,n; print *, 'hello'; end do
+end subroutine hello