diff options
author | tkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-08 09:38:13 +0000 |
---|---|---|
committer | tkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-01-08 09:38:13 +0000 |
commit | d197251d5febbd195535ed140a5885e988ca200d (patch) | |
tree | bc81017a641e2c952741cf0d7f440a5956a9f883 /gcc/fortran | |
parent | 63e7c5f411a0f244eefe8ab1107f9764cc644aed (diff) | |
download | gcc-d197251d5febbd195535ed140a5885e988ca200d.tar.gz |
2011-01-08 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/45777
* symbol.c (gfc_symbols_could_alias): Strip gfc_ prefix,
make static and move in front of its only caller, to ...
* trans-array.c (symbols_could_alias): ... here.
Pass information about pointer and target status as
arguments. Allocatable arrays don't alias anything
unless they have the POINTER attribute.
(gfc_could_be_alias): Keep track of pointer and target
status when following references. Also check if typespecs
of components match those of other components or symbols.
2011-01-08 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/45777
* gfortran.dg/dependency_39.f90: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@168596 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/symbol.c | 35 | ||||
-rw-r--r-- | gcc/fortran/trans-array.c | 95 |
4 files changed, 104 insertions, 41 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 57b07100709..f313fd8e2df 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,16 @@ +2011-01-08 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/45777 + * symbol.c (gfc_symbols_could_alias): Strip gfc_ prefix, + make static and move in front of its only caller, to ... + * trans-array.c (symbols_could_alias): ... here. + Pass information about pointer and target status as + arguments. Allocatable arrays don't alias anything + unless they have the POINTER attribute. + (gfc_could_be_alias): Keep track of pointer and target + status when following references. Also check if typespecs + of components match those of other components or symbols. + 2011-01-07 Tobias Burnus <burnus@net-b.de> PR fortran/41580 diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index d4443ecc68f..1444ee8ef65 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2561,8 +2561,6 @@ int gfc_get_sym_tree (const char *, gfc_namespace *, gfc_symtree **, bool); int gfc_get_ha_symbol (const char *, gfc_symbol **); int gfc_get_ha_sym_tree (const char *, gfc_symtree **); -int gfc_symbols_could_alias (gfc_symbol *, gfc_symbol *); - void gfc_undo_symbols (void); void gfc_commit_symbols (void); void gfc_commit_symbol (gfc_symbol *); diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c index 998eac9b3df..1a385b5f7bb 100644 --- a/gcc/fortran/symbol.c +++ b/gcc/fortran/symbol.c @@ -2813,41 +2813,6 @@ gfc_get_ha_symbol (const char *name, gfc_symbol **result) return i; } -/* Return true if both symbols could refer to the same data object. Does - not take account of aliasing due to equivalence statements. */ - -int -gfc_symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym) -{ - /* Aliasing isn't possible if the symbols have different base types. */ - if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0) - return 0; - - /* Pointers can point to other pointers, target objects and allocatable - objects. Two allocatable objects cannot share the same storage. */ - if (lsym->attr.pointer - && (rsym->attr.pointer || rsym->attr.allocatable || rsym->attr.target)) - return 1; - if (lsym->attr.target && rsym->attr.pointer) - return 1; - if (lsym->attr.allocatable && rsym->attr.pointer) - return 1; - - /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7 - and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already - checked above. */ - if (lsym->attr.target && rsym->attr.target - && ((lsym->attr.dummy && !lsym->attr.contiguous - && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE)) - || (rsym->attr.dummy && !rsym->attr.contiguous - && (!rsym->attr.dimension - || rsym->as->type == AS_ASSUMED_SHAPE)))) - return 1; - - return 0; -} - - /* Undoes all the changes made to symbols in the current statement. This subroutine is made simpler due to the fact that attributes are never removed once added. */ diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c index 4b8dd68119f..b95dd90a354 100644 --- a/gcc/fortran/trans-array.c +++ b/gcc/fortran/trans-array.c @@ -3449,6 +3449,37 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop) } } +/* Return true if both symbols could refer to the same data object. Does + not take account of aliasing due to equivalence statements. */ + +static int +symbols_could_alias (gfc_symbol *lsym, gfc_symbol *rsym, bool lsym_pointer, + bool lsym_target, bool rsym_pointer, bool rsym_target) +{ + /* Aliasing isn't possible if the symbols have different base types. */ + if (gfc_compare_types (&lsym->ts, &rsym->ts) == 0) + return 0; + + /* Pointers can point to other pointers and target objects. */ + + if ((lsym_pointer && (rsym_pointer || rsym_target)) + || (rsym_pointer && (lsym_pointer || lsym_target))) + return 1; + + /* Special case: Argument association, cf. F90 12.4.1.6, F2003 12.4.1.7 + and F2008 12.5.2.13 items 3b and 4b. The pointer case (a) is already + checked above. */ + if (lsym_target && rsym_target + && ((lsym->attr.dummy && !lsym->attr.contiguous + && (!lsym->attr.dimension || lsym->as->type == AS_ASSUMED_SHAPE)) + || (rsym->attr.dummy && !rsym->attr.contiguous + && (!rsym->attr.dimension + || rsym->as->type == AS_ASSUMED_SHAPE)))) + return 1; + + return 0; +} + /* Return true if the two SS could be aliased, i.e. both point to the same data object. */ @@ -3461,10 +3492,18 @@ gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss) gfc_ref *rref; gfc_symbol *lsym; gfc_symbol *rsym; + bool lsym_pointer, lsym_target, rsym_pointer, rsym_target; lsym = lss->expr->symtree->n.sym; rsym = rss->expr->symtree->n.sym; - if (gfc_symbols_could_alias (lsym, rsym)) + + lsym_pointer = lsym->attr.pointer; + lsym_target = lsym->attr.target; + rsym_pointer = rsym->attr.pointer; + rsym_target = rsym->attr.target; + + if (symbols_could_alias (lsym, rsym, lsym_pointer, lsym_target, + rsym_pointer, rsym_target)) return 1; if (rsym->ts.type != BT_DERIVED && rsym->ts.type != BT_CLASS @@ -3479,27 +3518,75 @@ gfc_could_be_alias (gfc_ss * lss, gfc_ss * rss) if (lref->type != REF_COMPONENT) continue; - if (gfc_symbols_could_alias (lref->u.c.sym, rsym)) + lsym_pointer = lsym_pointer || lref->u.c.sym->attr.pointer; + lsym_target = lsym_target || lref->u.c.sym->attr.target; + + if (symbols_could_alias (lref->u.c.sym, rsym, lsym_pointer, lsym_target, + rsym_pointer, rsym_target)) return 1; + if ((lsym_pointer && (rsym_pointer || rsym_target)) + || (rsym_pointer && (lsym_pointer || lsym_target))) + { + if (gfc_compare_types (&lref->u.c.component->ts, + &rsym->ts)) + return 1; + } + for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next) { if (rref->type != REF_COMPONENT) continue; - if (gfc_symbols_could_alias (lref->u.c.sym, rref->u.c.sym)) + rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer; + rsym_target = lsym_target || rref->u.c.sym->attr.target; + + if (symbols_could_alias (lref->u.c.sym, rref->u.c.sym, + lsym_pointer, lsym_target, + rsym_pointer, rsym_target)) return 1; + + if ((lsym_pointer && (rsym_pointer || rsym_target)) + || (rsym_pointer && (lsym_pointer || lsym_target))) + { + if (gfc_compare_types (&lref->u.c.component->ts, + &rref->u.c.sym->ts)) + return 1; + if (gfc_compare_types (&lref->u.c.sym->ts, + &rref->u.c.component->ts)) + return 1; + if (gfc_compare_types (&lref->u.c.component->ts, + &rref->u.c.component->ts)) + return 1; + } } } + lsym_pointer = lsym->attr.pointer; + lsym_target = lsym->attr.target; + lsym_pointer = lsym->attr.pointer; + lsym_target = lsym->attr.target; + for (rref = rss->expr->ref; rref != rss->data.info.ref; rref = rref->next) { if (rref->type != REF_COMPONENT) break; - if (gfc_symbols_could_alias (rref->u.c.sym, lsym)) + rsym_pointer = rsym_pointer || rref->u.c.sym->attr.pointer; + rsym_target = lsym_target || rref->u.c.sym->attr.target; + + if (symbols_could_alias (rref->u.c.sym, lsym, + lsym_pointer, lsym_target, + rsym_pointer, rsym_target)) return 1; + + if ((lsym_pointer && (rsym_pointer || rsym_target)) + || (rsym_pointer && (lsym_pointer || lsym_target))) + { + if (gfc_compare_types (&lsym->ts, &rref->u.c.component->ts)) + return 1; + } } return 0; |