summaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authortkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-08 09:38:13 +0000
committertkoenig <tkoenig@138bc75d-0d04-0410-961f-82ee72b054a4>2011-01-08 09:38:13 +0000
commitd197251d5febbd195535ed140a5885e988ca200d (patch)
treebc81017a641e2c952741cf0d7f440a5956a9f883 /gcc/fortran
parent63e7c5f411a0f244eefe8ab1107f9764cc644aed (diff)
downloadgcc-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/ChangeLog13
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/symbol.c35
-rw-r--r--gcc/fortran/trans-array.c95
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;