diff options
author | Mikael Morin <mikael.morin@tele2.fr> | 2008-10-31 16:37:17 +0100 |
---|---|---|
committer | Mikael Morin <mikael@gcc.gnu.org> | 2008-10-31 15:37:17 +0000 |
commit | 0e6834af18d539e4615be54eb2f9262898add8b4 (patch) | |
tree | cc77f0252a3e696614d3c0628d79d9fdf56725e2 /gcc/fortran/resolve.c | |
parent | 798c19f8557f4600cab847999a3f70a0ff3763f3 (diff) | |
download | gcc-0e6834af18d539e4615be54eb2f9262898add8b4.zip gcc-0e6834af18d539e4615be54eb2f9262898add8b4.tar.gz gcc-0e6834af18d539e4615be54eb2f9262898add8b4.tar.bz2 |
[multiple changes]
2008-10-31 Mikael Morin <mikael.morin@tele2.fr>
PR fortran/35820
* resolve.c (gfc_count_forall_iterators): New function.
(gfc_resolve_forall): Use gfc_count_forall_iterators to evaluate
the needed memory amount to allocate. Don't forget to free allocated
memory. Add an assertion to check for memory leaks.
2008-10-16 Mikael Morin <mikael.morin@tele2.fr>
PR fortran/35820
* gfortran.dg/nested_forall_1.f: New test.
From-SVN: r141496
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r-- | gcc/fortran/resolve.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 1816907..3cd6899 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -6215,6 +6215,40 @@ gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr) } +/* Counts the number of iterators needed inside a forall construct, including + nested forall constructs. This is used to allocate the needed memory + in gfc_resolve_forall. */ + +static int +gfc_count_forall_iterators (gfc_code *code) +{ + int max_iters, sub_iters, current_iters; + gfc_forall_iterator *fa; + + gcc_assert(code->op == EXEC_FORALL); + max_iters = 0; + current_iters = 0; + + for (fa = code->ext.forall_iterator; fa; fa = fa->next) + current_iters ++; + + code = code->block->next; + + while (code) + { + if (code->op == EXEC_FORALL) + { + sub_iters = gfc_count_forall_iterators (code); + if (sub_iters > max_iters) + max_iters = sub_iters; + } + code = code->next; + } + + return current_iters + max_iters; +} + + /* Given a FORALL construct, first resolve the FORALL iterator, then call gfc_resolve_forall_body to resolve the FORALL body. */ @@ -6224,22 +6258,18 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save) static gfc_expr **var_expr; static int total_var = 0; static int nvar = 0; + int old_nvar, tmp; gfc_forall_iterator *fa; - gfc_code *next; int i; + old_nvar = nvar; + /* Start to resolve a FORALL construct */ if (forall_save == 0) { /* Count the total number of FORALL index in the nested FORALL - construct in order to allocate the VAR_EXPR with proper size. */ - next = code; - while ((next != NULL) && (next->op == EXEC_FORALL)) - { - for (fa = next->ext.forall_iterator; fa; fa = fa->next) - total_var ++; - next = next->block->next; - } + construct in order to allocate the VAR_EXPR with proper size. */ + total_var = gfc_count_forall_iterators (code); /* Allocate VAR_EXPR with NUMBER_OF_FORALL_INDEX elements. */ var_expr = (gfc_expr **) gfc_getmem (total_var * sizeof (gfc_expr *)); @@ -6264,6 +6294,9 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save) var_expr[nvar] = gfc_copy_expr (fa->var); nvar++; + + /* No memory leak. */ + gcc_assert (nvar <= total_var); } /* Resolve the FORALL body. */ @@ -6272,13 +6305,21 @@ gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save) /* May call gfc_resolve_forall to resolve the inner FORALL loop. */ gfc_resolve_blocks (code->block, ns); - /* Free VAR_EXPR after the whole FORALL construct resolved. */ - for (i = 0; i < total_var; i++) - gfc_free_expr (var_expr[i]); + tmp = nvar; + nvar = old_nvar; + /* Free only the VAR_EXPRs allocated in this frame. */ + for (i = nvar; i < tmp; i++) + gfc_free_expr (var_expr[i]); - /* Reset the counters. */ - total_var = 0; - nvar = 0; + if (nvar == 0) + { + /* We are in the outermost FORALL construct. */ + gcc_assert (forall_save == 0); + + /* VAR_EXPR is not needed any more. */ + gfc_free (var_expr); + total_var = 0; + } } |