re PR fortran/30146 (Redefining do-variable in excecution cycle)

2012-11-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/30146
	* frontend-passes.c (doloop_warn):  New function.
	(doloop_list):  New static variable.
	(doloop_size):  New static variable.
	(doloop_level):  New static variable.
	(gfc_run_passes): Call doloop_warn.
	(doloop_code):  New function.
	(doloop_function):  New function.
	(gfc_code_walker):  Keep track of DO level.

2012-11-25  Thomas Koenig  <tkoenig@gcc.gnu.org>

	PR fortran/30146
	* gfortran.dg/do_check_6.f90:  New test.

From-SVN: r193793
This commit is contained in:
Thomas Koenig 2012-11-25 17:24:09 +00:00
parent 99303b325e
commit 305a35dafb
4 changed files with 236 additions and 2 deletions

View File

@ -1,3 +1,15 @@
2012-11-25 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/30146
* frontend-passes.c (doloop_warn): New function.
(doloop_list): New static variable.
(doloop_size): New static variable.
(doloop_level): New static variable.
(gfc_run_passes): Call doloop_warn.
(doloop_code): New function.
(doloop_function): New function.
(gfc_code_walker): Keep track of DO level.
2012-11-24 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/55314

View File

@ -39,6 +39,7 @@ static bool optimize_trim (gfc_expr *);
static bool optimize_lexical_comparison (gfc_expr *);
static void optimize_minmaxloc (gfc_expr **);
static bool is_empty_string (gfc_expr *e);
static void doloop_warn (gfc_namespace *);
/* How deep we are inside an argument list. */
@ -76,12 +77,30 @@ static bool in_omp_workshare;
static int iterator_level;
/* Entry point - run all passes for a namespace. So far, only an
optimization pass is run. */
/* Keep track of DO loop levels. */
static gfc_code **doloop_list;
static int doloop_size, doloop_level;
/* Vector of gfc_expr * to keep track of DO loops. */
struct my_struct *evec;
/* Entry point - run all passes for a namespace. */
void
gfc_run_passes (gfc_namespace *ns)
{
/* Warn about dubious DO loops where the index might
change. */
doloop_size = 20;
doloop_level = 0;
doloop_list = XNEWVEC(gfc_code *, doloop_size);
doloop_warn (ns);
XDELETEVEC (doloop_list);
if (gfc_option.flag_frontend_optimize)
{
expr_size = 20;
@ -1225,6 +1244,160 @@ optimize_minmaxloc (gfc_expr **e)
mpz_set_ui (a->expr->value.integer, 1);
}
/* Callback function for code checking that we do not pass a DO variable to an
INTENT(OUT) or INTENT(INOUT) dummy variable. */
static int
doloop_code (gfc_code **c, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
gfc_code *co;
int i;
gfc_formal_arglist *f;
gfc_actual_arglist *a;
co = *c;
switch (co->op)
{
case EXEC_DO:
/* Grow the temporary storage if necessary. */
if (doloop_level >= doloop_size)
{
doloop_size = 2 * doloop_size;
doloop_list = XRESIZEVEC (gfc_code *, doloop_list, doloop_size);
}
/* Mark the DO loop variable if there is one. */
if (co->ext.iterator && co->ext.iterator->var)
doloop_list[doloop_level] = co;
else
doloop_list[doloop_level] = NULL;
break;
case EXEC_CALL:
f = co->symtree->n.sym->formal;
/* Withot a formal arglist, there is only unknown INTENT,
which we don't check for. */
if (f == NULL)
break;
a = co->ext.actual;
while (a && f)
{
for (i=0; i<doloop_level; i++)
{
gfc_symbol *do_sym;
if (doloop_list[i] == NULL)
break;
do_sym = doloop_list[i]->ext.iterator->var->symtree->n.sym;
if (a->expr && a->expr->symtree
&& a->expr->symtree->n.sym == do_sym)
{
if (f->sym->attr.intent == INTENT_OUT)
gfc_error_now("Variable '%s' at %L set to undefined value "
"inside loop beginning at %L as INTENT(OUT) "
"argument to subroutine '%s'", do_sym->name,
&a->expr->where, &doloop_list[i]->loc,
co->symtree->n.sym->name);
else if (f->sym->attr.intent == INTENT_INOUT)
gfc_error_now("Variable '%s' at %L not definable inside loop "
"beginning at %L as INTENT(INOUT) argument to "
"subroutine '%s'", do_sym->name,
&a->expr->where, &doloop_list[i]->loc,
co->symtree->n.sym->name);
}
}
a = a->next;
f = f->next;
}
break;
default:
break;
}
return 0;
}
/* Callback function for functions checking that we do not pass a DO variable
to an INTENT(OUT) or INTENT(INOUT) dummy variable. */
static int
do_function (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
gfc_formal_arglist *f;
gfc_actual_arglist *a;
gfc_expr *expr;
int i;
expr = *e;
if (expr->expr_type != EXPR_FUNCTION)
return 0;
/* Intrinsic functions don't modify their arguments. */
if (expr->value.function.isym)
return 0;
f = expr->symtree->n.sym->formal;
/* Without a formal arglist, there is only unknown INTENT,
which we don't check for. */
if (f == NULL)
return 0;
a = expr->value.function.actual;
while (a && f)
{
for (i=0; i<doloop_level; i++)
{
gfc_symbol *do_sym;
if (doloop_list[i] == NULL)
break;
do_sym = doloop_list[i]->ext.iterator->var->symtree->n.sym;
if (a->expr && a->expr->symtree
&& a->expr->symtree->n.sym == do_sym)
{
if (f->sym->attr.intent == INTENT_OUT)
gfc_error_now("Variable '%s' at %L set to undefined value "
"inside loop beginning at %L as INTENT(OUT) "
"argument to function '%s'", do_sym->name,
&a->expr->where, &doloop_list[i]->loc,
expr->symtree->n.sym->name);
else if (f->sym->attr.intent == INTENT_INOUT)
gfc_error_now("Variable '%s' at %L not definable inside loop "
"beginning at %L as INTENT(INOUT) argument to "
"function '%s'", do_sym->name,
&a->expr->where, &doloop_list[i]->loc,
expr->symtree->n.sym->name);
}
}
a = a->next;
f = f->next;
}
return 0;
}
static void
doloop_warn (gfc_namespace *ns)
{
gfc_code_walker (&ns->code, doloop_code, do_function, NULL);
}
#define WALK_SUBEXPR(NODE) \
do \
{ \
@ -1383,6 +1556,7 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
break;
case EXEC_DO:
doloop_level ++;
WALK_SUBEXPR (co->ext.iterator->var);
WALK_SUBEXPR (co->ext.iterator->start);
WALK_SUBEXPR (co->ext.iterator->end);
@ -1601,6 +1775,9 @@ gfc_code_walker (gfc_code **c, walk_code_fn_t codefn, walk_expr_fn_t exprfn,
if (co->op == EXEC_FORALL)
forall_level --;
if (co->op == EXEC_DO)
doloop_level --;
in_omp_workshare = saved_in_omp_workshare;
}
}

View File

@ -1,3 +1,8 @@
2012-11-25 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/30146
* gfortran.dg/do_check_7.f90: New test.
2012-11-24 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/55446

View File

@ -0,0 +1,40 @@
! { dg-do compile }
! PR 30146 - warn about DO variables as argument to INTENT(IN) and
! INTENT(INOUT) dummy arguments
program main
implicit none
integer :: i,j, k, l
do k=1,2 ! { dg-error "undefined value" }
do i=1,10 ! { dg-error "definable" }
do j=1,10 ! { dg-error "undefined value" }
do l=1,10 ! { dg-error "definable" }
call s_out(k) ! { dg-error "undefined" }
call s_inout(i) ! { dg-error "definable" }
print *,f_out(j) ! { dg-error "undefined" }
print *,f_inout(l) ! { dg-error "definable" }
end do
end do
end do
end do
contains
subroutine s_out(i_arg)
integer, intent(out) :: i_arg
end subroutine s_out
subroutine s_inout(i_arg)
integer, intent(inout) :: i_arg
end subroutine s_inout
function f_out(i_arg)
integer, intent(out) :: i_arg
integer :: f_out
f_out = i_arg
end function f_out
function f_inout(i_arg)
integer, intent(inout) :: i_arg
integer :: f_inout
f_inout = i_arg
end function f_inout
end program main