From bfcb501d83778b8f2b4cc52672b940e62e611e17 Mon Sep 17 00:00:00 2001 From: Paul Thomas Date: Wed, 9 Nov 2016 10:10:41 +0000 Subject: [PATCH] check.c (gfc_check_move_alloc): Prevent error that avoids aliasing between to and from arguments from rejecting... 2016-11-09 Paul Thomas * check.c (gfc_check_move_alloc): Prevent error that avoids aliasing between to and from arguments from rejecting valid code. 2016-11-09 Paul Thomas * gfortran.dg/move_alloc_18.f90: New test. From-SVN: r241995 --- gcc/fortran/ChangeLog | 6 +++ gcc/fortran/check.c | 42 ++++++++++++++++++--- gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gfortran.dg/move_alloc_18.f90 | 21 +++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/move_alloc_18.f90 diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 6c39866487f..bb0beb713e9 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,9 @@ +2016-11-09 Paul Thomas + + * check.c (gfc_check_move_alloc): Prevent error that avoids + aliasing between to and from arguments from rejecting valid + code. + 2016-11-09 Janus Weil PR fortran/71894 diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c index 142cdac2e38..265fe22594f 100644 --- a/gcc/fortran/check.c +++ b/gcc/fortran/check.c @@ -3342,14 +3342,44 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to) return false; } - /* F2003 12.4.1.7 */ - if (to->expr_type == EXPR_VARIABLE && from->expr_type ==EXPR_VARIABLE + /* This is based losely on F2003 12.4.1.7. It is intended to prevent + the likes of to = sym->cmp1->cmp2 and from = sym->cmp1, where cmp1 + and cmp2 are allocatable. After the allocation is transferred, + the 'to' chain is broken by the nullification of the 'from'. A bit + of reflection reveals that this can only occur for derived types + with recursive allocatable components. */ + if (to->expr_type == EXPR_VARIABLE && from->expr_type == EXPR_VARIABLE && !strcmp (to->symtree->n.sym->name, from->symtree->n.sym->name)) { - gfc_error ("The FROM and TO arguments at %L are either the same object " - "or subobjects thereof and so violate aliasing restrictions " - "(F2003 12.4.1.7)", &to->where); - return false; + gfc_ref *to_ref, *from_ref; + to_ref = to->ref; + from_ref = from->ref; + bool aliasing = true; + + for (; from_ref && to_ref; + from_ref = from_ref->next, to_ref = to_ref->next) + { + if (to_ref->type != from->ref->type) + aliasing = false; + else if (to_ref->type == REF_ARRAY + && to_ref->u.ar.type != AR_FULL + && from_ref->u.ar.type != AR_FULL) + /* Play safe; assume sections and elements are different. */ + aliasing = false; + else if (to_ref->type == REF_COMPONENT + && to_ref->u.c.component != from_ref->u.c.component) + aliasing = false; + + if (!aliasing) + break; + } + + if (aliasing) + { + gfc_error ("The FROM and TO arguments at %L violate aliasing " + "restrictions (F2003 12.4.1.7)", &to->where); + return false; + } } /* CLASS arguments: Make sure the vtab of from is present. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a7e0250e0c4..f3438bee748 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-11-09 Paul Thomas + + * gfortran.dg/move_alloc_18.f90: New test. + 2016-11-09 Prathamesh Kulkarni PR middle-end/78256 diff --git a/gcc/testsuite/gfortran.dg/move_alloc_18.f90 b/gcc/testsuite/gfortran.dg/move_alloc_18.f90 new file mode 100644 index 00000000000..bc72d5d1f87 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/move_alloc_18.f90 @@ -0,0 +1,21 @@ +! { dg-do compile } +! +! Test that the anti-aliasing restriction does not knock out valid code. +! +! Contributed by Andrew Balwin on +! https://groups.google.com/forum/#!topic/comp.lang.fortran/oiXdl1LPb_s +! + PROGRAM TEST + IMPLICIT NONE + + TYPE FOOBAR + INTEGER, ALLOCATABLE :: COMP(:) + END TYPE + + TYPE (FOOBAR) :: MY_ARRAY(6) + + ALLOCATE (MY_ARRAY(1)%COMP(10)) + + CALL MOVE_ALLOC (MY_ARRAY(1)%COMP, MY_ARRAY(2)%COMP) + + END PROGRAM TEST