Commit fb078366 by Thomas Koenig

re PR fortran/91443 (-Wargument-mismatch does not catch mismatch for global procedure)

2019-08-15  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/91443
	* frontend-passes.c (check_externals_expr): New function.
	(check_externals_code): New function.
	(gfc_check_externals): New function.
	* gfortran.h (debug): Add prototypes for gfc_symbol * and
	gfc_expr *.
	(gfc_check_externals): Add prototype.
	* interface.c (compare_actual_formal): Do not complain about
	alternate returns if the formal argument is optional.
	(gfc_procedure_use): Handle cases when an error has been issued
	previously.  Break long line.
	* parse.c (gfc_parse_file): Call gfc_check_externals for all
	external procedures.
	* resolve.c (resolve_global_procedure): Remove checking of
	argument list.

2019-08-15  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/91443
	* gfortran.dg/argument_checking_19.f90: New test.
	* gfortran.dg/altreturn_10.f90: Change dg-warning to dg-error.
	* gfortran.dg/dec_union_11.f90: Add -std=legacy.
	* gfortran.dg/hollerith8.f90: Likewise. Remove warning for
	Hollerith constant.
	* gfortran.dg/integer_exponentiation_2.f90: New subroutine gee_i8;
	use it to avoid type mismatches.
	* gfortran.dg/pr41011.f: Add -std=legacy.
	* gfortran.dg/whole_file_1.f90: Change warnings to errors.
	* gfortran.dg/whole_file_2.f90: Likewise.

From-SVN: r274551
parent 7148dede
2019-08-15 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/91443
* frontend-passes.c (check_externals_expr): New function.
(check_externals_code): New function.
(gfc_check_externals): New function.
* gfortran.h (debug): Add prototypes for gfc_symbol * and
gfc_expr *.
(gfc_check_externals): Add prototype.
* interface.c (compare_actual_formal): Do not complain about
alternate returns if the formal argument is optional.
(gfc_procedure_use): Handle cases when an error has been issued
previously. Break long line.
* parse.c (gfc_parse_file): Call gfc_check_externals for all
external procedures.
* resolve.c (resolve_global_procedure): Remove checking of
argument list.
2019-08-13 Steven G. Kargl <kargl@gcc.gnu.org> 2019-08-13 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/87991 PR fortran/87991
...@@ -7,7 +25,7 @@ ...@@ -7,7 +25,7 @@
2019-08-13 Steven G. Kargl <kargl@gcc.gnu.org> 2019-08-13 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/88072 PR fortran/88072
* misc.c (gfc_typename): Do not point to something that ought not to * misc.c (gfc_typename): Do not point to something that ought not to
be pointed at. be pointed at.
2013-08-13 Thomas Koenig <tkoenig@gcc.gnu.org> 2013-08-13 Thomas Koenig <tkoenig@gcc.gnu.org>
......
...@@ -56,7 +56,6 @@ static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *, ...@@ -56,7 +56,6 @@ static gfc_expr* check_conjg_transpose_variable (gfc_expr *, bool *,
static int call_external_blas (gfc_code **, int *, void *); static int call_external_blas (gfc_code **, int *, void *);
static int matmul_temp_args (gfc_code **, int *,void *data); static int matmul_temp_args (gfc_code **, int *,void *data);
static int index_interchange (gfc_code **, int*, void *); static int index_interchange (gfc_code **, int*, void *);
static bool is_fe_temp (gfc_expr *e); static bool is_fe_temp (gfc_expr *e);
#ifdef CHECKING_P #ifdef CHECKING_P
...@@ -5364,3 +5363,100 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn, ...@@ -5364,3 +5363,100 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
} }
return 0; return 0;
} }
/* As a post-resolution step, check that all global symbols which are
not declared in the source file match in their call signatures.
We do this by looping over the code (and expressions). The first call
we happen to find is assumed to be canonical. */
/* Callback for external functions. */
static int
check_externals_expr (gfc_expr **ep, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
gfc_expr *e = *ep;
gfc_symbol *sym, *def_sym;
gfc_gsymbol *gsym;
if (e->expr_type != EXPR_FUNCTION)
return 0;
sym = e->value.function.esym;
if (sym == NULL || sym->attr.is_bind_c)
return 0;
if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN)
return 0;
gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
if (gsym == NULL)
return 0;
gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
if (sym && def_sym)
gfc_procedure_use (def_sym, &e->value.function.actual, &e->where);
return 0;
}
/* Callback for external code. */
static int
check_externals_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
gfc_code *co = *c;
gfc_symbol *sym, *def_sym;
gfc_gsymbol *gsym;
if (co->op != EXEC_CALL)
return 0;
sym = co->resolved_sym;
if (sym == NULL || sym->attr.is_bind_c)
return 0;
if (sym->attr.proc != PROC_EXTERNAL && sym->attr.proc != PROC_UNKNOWN)
return 0;
if (sym->attr.if_source == IFSRC_IFBODY || sym->attr.if_source == IFSRC_DECL)
return 0;
gsym = gfc_find_gsymbol (gfc_gsym_root, sym->name);
if (gsym == NULL)
return 0;
gfc_find_symbol (sym->name, gsym->ns, 0, &def_sym);
if (sym && def_sym)
gfc_procedure_use (def_sym, &co->ext.actual, &co->loc);
return 0;
}
/* Called routine. */
void
gfc_check_externals (gfc_namespace *ns)
{
gfc_clear_error ();
/* Turn errors into warnings if -std=legacy is given by the user. */
if (!pedantic && !(gfc_option.warn_std & GFC_STD_LEGACY))
gfc_errors_to_warnings (true);
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_errors_to_warnings (false);
}
...@@ -3477,6 +3477,8 @@ void gfc_dump_parse_tree (gfc_namespace *, FILE *); ...@@ -3477,6 +3477,8 @@ void gfc_dump_parse_tree (gfc_namespace *, FILE *);
void gfc_dump_c_prototypes (gfc_namespace *, FILE *); void gfc_dump_c_prototypes (gfc_namespace *, FILE *);
void gfc_dump_external_c_prototypes (FILE *); void gfc_dump_external_c_prototypes (FILE *);
void gfc_dump_global_symbols (FILE *); void gfc_dump_global_symbols (FILE *);
void debug (gfc_symbol *);
void debug (gfc_expr *);
/* parse.c */ /* parse.c */
bool gfc_parse_file (void); bool gfc_parse_file (void);
...@@ -3551,6 +3553,7 @@ int gfc_dummy_code_callback (gfc_code **, int *, void *); ...@@ -3551,6 +3553,7 @@ int gfc_dummy_code_callback (gfc_code **, int *, void *);
int gfc_expr_walker (gfc_expr **, walk_expr_fn_t, void *); int gfc_expr_walker (gfc_expr **, walk_expr_fn_t, void *);
int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *); int gfc_code_walker (gfc_code **, walk_code_fn_t, walk_expr_fn_t, void *);
bool gfc_has_dimen_vector_ref (gfc_expr *e); bool gfc_has_dimen_vector_ref (gfc_expr *e);
void gfc_check_externals (gfc_namespace *);
/* simplify.c */ /* simplify.c */
......
...@@ -2979,10 +2979,15 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal, ...@@ -2979,10 +2979,15 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
if (a->expr == NULL) if (a->expr == NULL)
{ {
if (where) if (f->sym->attr.optional)
gfc_error_now ("Unexpected alternate return specifier in " continue;
"subroutine call at %L", where); else
return false; {
if (where)
gfc_error_now ("Unexpected alternate return specifier in "
"subroutine call at %L", where);
return false;
}
} }
/* Make sure that intrinsic vtables exist for calls to unlimited /* Make sure that intrinsic vtables exist for calls to unlimited
...@@ -3723,6 +3728,9 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where) ...@@ -3723,6 +3728,9 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
for (a = *ap; a; a = a->next) for (a = *ap; a; a = a->next)
{ {
if (a->expr && a->expr->error)
return false;
/* Skip g77 keyword extensions like %VAL, %REF, %LOC. */ /* Skip g77 keyword extensions like %VAL, %REF, %LOC. */
if (a->name != NULL && a->name[0] != '%') if (a->name != NULL && a->name[0] != '%')
{ {
...@@ -3738,6 +3746,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where) ...@@ -3738,6 +3746,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
gfc_error ("Assumed-type argument %s at %L requires an explicit " gfc_error ("Assumed-type argument %s at %L requires an explicit "
"interface", a->expr->symtree->n.sym->name, "interface", a->expr->symtree->n.sym->name,
&a->expr->where); &a->expr->where);
a->expr->error = 1;
break; break;
} }
...@@ -3751,6 +3760,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where) ...@@ -3751,6 +3760,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
gfc_error ("Actual argument of LOCK_TYPE or with LOCK_TYPE " gfc_error ("Actual argument of LOCK_TYPE or with LOCK_TYPE "
"component at %L requires an explicit interface for " "component at %L requires an explicit interface for "
"procedure %qs", &a->expr->where, sym->name); "procedure %qs", &a->expr->where, sym->name);
a->expr->error = 1;
break; break;
} }
...@@ -3764,13 +3774,16 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where) ...@@ -3764,13 +3774,16 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
gfc_error ("Actual argument of EVENT_TYPE or with EVENT_TYPE " gfc_error ("Actual argument of EVENT_TYPE or with EVENT_TYPE "
"component at %L requires an explicit interface for " "component at %L requires an explicit interface for "
"procedure %qs", &a->expr->where, sym->name); "procedure %qs", &a->expr->where, sym->name);
a->expr->error = 1;
break; break;
} }
if (a->expr && a->expr->expr_type == EXPR_NULL if (a->expr && a->expr->expr_type == EXPR_NULL
&& a->expr->ts.type == BT_UNKNOWN) && a->expr->ts.type == BT_UNKNOWN)
{ {
gfc_error ("MOLD argument to NULL required at %L", &a->expr->where); gfc_error ("MOLD argument to NULL required at %L",
&a->expr->where);
a->expr->error = 1;
return false; return false;
} }
...@@ -3780,6 +3793,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where) ...@@ -3780,6 +3793,7 @@ gfc_procedure_use (gfc_symbol *sym, gfc_actual_arglist **ap, locus *where)
{ {
gfc_error ("Assumed-rank argument requires an explicit interface " gfc_error ("Assumed-rank argument requires an explicit interface "
"at %L", &a->expr->where); "at %L", &a->expr->where);
a->expr->error = 1;
return false; return false;
} }
} }
......
...@@ -6319,6 +6319,12 @@ done: ...@@ -6319,6 +6319,12 @@ done:
/* Do the resolution. */ /* Do the resolution. */
resolve_all_program_units (gfc_global_ns_list); resolve_all_program_units (gfc_global_ns_list);
/* Fixup for external procedures. */
for (gfc_current_ns = gfc_global_ns_list; gfc_current_ns;
gfc_current_ns = gfc_current_ns->sibling)
gfc_check_externals (gfc_current_ns);
/* Do the parse tree dump. */ /* Do the parse tree dump. */
gfc_current_ns = flag_dump_fortran_original ? gfc_global_ns_list : NULL; gfc_current_ns = flag_dump_fortran_original ? gfc_global_ns_list : NULL;
......
...@@ -2506,8 +2506,7 @@ gfc_explicit_interface_required (gfc_symbol *sym, char *errmsg, int err_len) ...@@ -2506,8 +2506,7 @@ gfc_explicit_interface_required (gfc_symbol *sym, char *errmsg, int err_len)
static void static void
resolve_global_procedure (gfc_symbol *sym, locus *where, resolve_global_procedure (gfc_symbol *sym, locus *where, int sub)
gfc_actual_arglist **actual, int sub)
{ {
gfc_gsymbol * gsym; gfc_gsymbol * gsym;
gfc_namespace *ns; gfc_namespace *ns;
...@@ -2615,14 +2614,6 @@ resolve_global_procedure (gfc_symbol *sym, locus *where, ...@@ -2615,14 +2614,6 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
" %s", sym->name, &sym->declared_at, reason); " %s", sym->name, &sym->declared_at, reason);
goto done; goto done;
} }
if (!pedantic
|| ((gfc_option.warn_std & GFC_STD_LEGACY)
&& !(gfc_option.warn_std & GFC_STD_GNU)))
gfc_errors_to_warnings (true);
if (sym->attr.if_source != IFSRC_IFBODY)
gfc_procedure_use (def_sym, actual, where);
} }
done: done:
...@@ -3198,8 +3189,7 @@ resolve_function (gfc_expr *expr) ...@@ -3198,8 +3189,7 @@ resolve_function (gfc_expr *expr)
/* If the procedure is external, check for usage. */ /* If the procedure is external, check for usage. */
if (sym && is_external_proc (sym)) if (sym && is_external_proc (sym))
resolve_global_procedure (sym, &expr->where, resolve_global_procedure (sym, &expr->where, 0);
&expr->value.function.actual, 0);
if (sym && sym->ts.type == BT_CHARACTER if (sym && sym->ts.type == BT_CHARACTER
&& sym->ts.u.cl && sym->ts.u.cl
...@@ -3675,7 +3665,7 @@ resolve_call (gfc_code *c) ...@@ -3675,7 +3665,7 @@ resolve_call (gfc_code *c)
/* If external, check for usage. */ /* If external, check for usage. */
if (csym && is_external_proc (csym)) if (csym && is_external_proc (csym))
resolve_global_procedure (csym, &c->loc, &c->ext.actual, 1); resolve_global_procedure (csym, &c->loc, 1);
t = true; t = true;
if (c->resolved_sym == NULL) if (c->resolved_sym == NULL)
......
2019-08-15 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/91443
* gfortran.dg/argument_checking_19.f90: New test.
* gfortran.dg/altreturn_10.f90: Change dg-warning to dg-error.
* gfortran.dg/dec_union_11.f90: Add -std=legacy.
* gfortran.dg/hollerith8.f90: Likewise. Remove warning for
Hollerith constant.
* gfortran.dg/integer_exponentiation_2.f90: New subroutine gee_i8;
use it to avoid type mismatches.
* gfortran.dg/pr41011.f: Add -std=legacy.
* gfortran.dg/whole_file_1.f90: Change warnings to errors.
* gfortran.dg/whole_file_2.f90: Likewise.
2019-08-15 Richard Biener <rguenther@suse.de> 2019-08-15 Richard Biener <rguenther@suse.de>
PR tree-optimization/91445 PR tree-optimization/91445
......
...@@ -14,6 +14,6 @@ subroutine sub (x) ...@@ -14,6 +14,6 @@ subroutine sub (x)
end end
subroutine sub2 subroutine sub2
call sub (*99) ! { dg-error "Unexpected alternate return specifier" } call sub (*99) ! { dg-error "Unexpected alternate return specifier" }
call sub (99.) ! { dg-warning "Type mismatch in argument" } call sub (99.) ! { dg-error "Type mismatch in argument" }
99 stop 99 stop
end end
! { dg-do compile }
! PR 91443 - this was not caught.
module x
contains
subroutine a
call foo(1) ! { dg-error "Type mismatch in argument" }
end subroutine a
end module x
subroutine foo(a)
real :: a
print *,a
end subroutine foo
program main
use x
call a
end program main
! { dg-do compile } ! { dg-do compile }
! { dg-options "-g -fdec-structure" } ! { dg-options "-g -fdec-structure -std=legacy" }
! !
! Test a regression where typespecs of unions containing character buffers of ! Test a regression where typespecs of unions containing character buffers of
! different lengths where copied, resulting in a bad gimple tree state. ! different lengths where copied, resulting in a bad gimple tree state.
......
! { dg-do run } ! { dg-do run }
! { dg-options "-std=gnu" } ! { dg-options "-std=legacy" }
! PR43217 Output of Hollerith constants which are not a multiple of 4 bytes ! PR43217 Output of Hollerith constants which are not a multiple of 4 bytes
! Test case prepared from OP by Jerry DeLisle <jvdelisle@gcc.gnu.org> ! Test case prepared from OP by Jerry DeLisle <jvdelisle@gcc.gnu.org>
program hello2 program hello2
call wrtout (9hHELLO YOU, 9) call wrtout (9hHELLO YOU, 9) ! { dg-warning "Rank mismatch" }
stop stop
end end
...@@ -22,5 +22,3 @@ subroutine wrtout (iarray, nchrs) ...@@ -22,5 +22,3 @@ subroutine wrtout (iarray, nchrs)
& outstr.ne."48454C4C 4F20594F 55202020") STOP 1 & outstr.ne."48454C4C 4F20594F 55202020") STOP 1
return return
end end
! { dg-warning "Hollerith constant" "" { target *-*-* } 6 }
! { dg-warning "Rank mismatch" "" { target *-*-* } 6 }
...@@ -139,16 +139,16 @@ subroutine foo(a) ...@@ -139,16 +139,16 @@ subroutine foo(a)
call gee_i(i**(-huge(0_4))) call gee_i(i**(-huge(0_4)))
call gee_i(i**(-huge(0_4)-1_4)) call gee_i(i**(-huge(0_4)-1_4))
call gee_i(i**0_8) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**0_8)
call gee_i(i**1_8) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**1_8)
call gee_i(i**2_8) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**2_8)
call gee_i(i**3_8) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**3_8)
call gee_i(i**(-1_8)) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**(-1_8))
call gee_i(i**(-2_8)) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**(-2_8))
call gee_i(i**(-3_8)) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**(-3_8))
call gee_i(i**huge(0_8)) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**huge(0_8))
call gee_i(i**(-huge(0_8))) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**(-huge(0_8)))
call gee_i(i**(-huge(0_8)-1_8)) ! { dg-warning "Type mismatch in argument" } call gee_i8(i**(-huge(0_8)-1_8))
! Real ! Real
call gee_r(a**0_1) call gee_r(a**0_1)
...@@ -245,6 +245,10 @@ subroutine gee_i(i) ...@@ -245,6 +245,10 @@ subroutine gee_i(i)
integer :: i integer :: i
end subroutine gee_i end subroutine gee_i
subroutine gee_i8(i)
integer(kind=8) :: i
end subroutine gee_i8
subroutine gee_r(r) subroutine gee_r(r)
real :: r real :: r
end subroutine gee_r end subroutine gee_r
......
! { dg-do compile } ! { dg-do compile }
! { dg-options "-O3" } ! { dg-options "-O3 -std=legacy" }
CALL UVSET(NX,NY,NZ,HVAR,ZET,NP,DZ,DKM,UM,VM,UG,VG,TM,DCDX, ! { dg-warning "Rank mismatch" } CALL UVSET(NX,NY,NZ,HVAR,ZET,NP,DZ,DKM,UM,VM,UG,VG,TM,DCDX, ! { dg-warning "Rank mismatch" }
*ITY,ISH,NSMT,F) *ITY,ISH,NSMT,F)
CALL DCTDX(NX,NY,NX1,NFILT,C(MLAG),DCDX(MLAG),HELP,HELPA, CALL DCTDX(NX,NY,NX1,NFILT,C(MLAG),DCDX(MLAG),HELP,HELPA,
......
...@@ -19,7 +19,7 @@ subroutine b ...@@ -19,7 +19,7 @@ subroutine b
integer :: u1 integer :: u1
end type end type
type (u) :: q type (u) :: q
call a(q) ! { dg-warning "Type mismatch" } call a(q) ! { dg-error "Type mismatch" }
print *, q%u1 print *, q%u1
end subroutine end subroutine
...@@ -36,7 +36,7 @@ subroutine d ...@@ -36,7 +36,7 @@ subroutine d
integer :: u1 integer :: u1
end type end type
type (u) :: q type (u) :: q
call c(q) ! { dg-warning "Type mismatch" } call c(q) ! { dg-error "Type mismatch" }
print *, q%u1 print *, q%u1
end subroutine end subroutine
......
...@@ -14,8 +14,8 @@ end function ...@@ -14,8 +14,8 @@ end function
program gg program gg
real :: h real :: h
character (5) :: chr = 'hello' character (5) :: chr = 'hello'
h = a(); ! { dg-warning "Missing actual argument" } h = a(); ! { dg-error "Missing actual argument" }
call test ([chr]) ! { dg-warning "Rank mismatch" } call test ([chr]) ! { dg-error "Rank mismatch" }
end program gg end program gg
subroutine test (a) subroutine test (a)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment