Commit 15d774f9 by Paul Thomas Committed by Janus Weil

re PR fortran/43945 ([OOP] Derived type with GENERIC: resolved to the wrong specific TBP)

2010-06-05  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43945
	* resolve.c (get_declared_from_expr): Move to before
	resolve_typebound_generic_call.  Make new_ref and class_ref
	ignorable if set to NULL.
	(resolve_typebound_generic_call): Once we have resolved the
	generic call, check that the specific instance is that which
	is bound to the declared type.
	(resolve_typebound_function,resolve_typebound_subroutine): Avoid
	freeing 'class_ref->next' twice.


2010-06-05  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/43945
	* gfortran.dg/generic_23.f03: New test.

Co-Authored-By: Janus Weil <janus@gcc.gnu.org>

From-SVN: r160335
parent be69e91b
2010-06-05 Paul Thomas <pault@gcc.gnu.org> 2010-06-05 Paul Thomas <pault@gcc.gnu.org>
Janus Weil <janus@gcc.gnu.org>
PR fortran/43945
* resolve.c (get_declared_from_expr): Move to before
resolve_typebound_generic_call. Make new_ref and class_ref
ignorable if set to NULL.
(resolve_typebound_generic_call): Once we have resolved the
generic call, check that the specific instance is that which
is bound to the declared type.
(resolve_typebound_function,resolve_typebound_subroutine): Avoid
freeing 'class_ref->next' twice.
2010-06-05 Paul Thomas <pault@gcc.gnu.org>
PR fortran/43895 PR fortran/43895
* trans-array.c (structure_alloc_comps): Dereference scalar * trans-array.c (structure_alloc_comps): Dereference scalar
......
...@@ -5160,6 +5160,43 @@ resolve_typebound_static (gfc_expr* e, gfc_symtree** target, ...@@ -5160,6 +5160,43 @@ resolve_typebound_static (gfc_expr* e, gfc_symtree** target,
} }
/* Get the ultimate declared type from an expression. In addition,
return the last class/derived type reference and the copy of the
reference list. */
static gfc_symbol*
get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref,
gfc_expr *e)
{
gfc_symbol *declared;
gfc_ref *ref;
declared = NULL;
if (class_ref)
*class_ref = NULL;
if (new_ref)
*new_ref = gfc_copy_ref (e->ref);
for (ref = e->ref; ref; ref = ref->next)
{
if (ref->type != REF_COMPONENT)
continue;
if (ref->u.c.component->ts.type == BT_CLASS
|| ref->u.c.component->ts.type == BT_DERIVED)
{
declared = ref->u.c.component->ts.u.derived;
if (class_ref)
*class_ref = ref;
}
}
if (declared == NULL)
declared = e->symtree->n.sym->ts.u.derived;
return declared;
}
/* Given an EXPR_COMPCALL calling a GENERIC typebound procedure, figure out /* Given an EXPR_COMPCALL calling a GENERIC typebound procedure, figure out
which of the specific bindings (if any) matches the arglist and transform which of the specific bindings (if any) matches the arglist and transform
the expression into a call of that binding. */ the expression into a call of that binding. */
...@@ -5169,6 +5206,8 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name) ...@@ -5169,6 +5206,8 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
{ {
gfc_typebound_proc* genproc; gfc_typebound_proc* genproc;
const char* genname; const char* genname;
gfc_symtree *st;
gfc_symbol *derived;
gcc_assert (e->expr_type == EXPR_COMPCALL); gcc_assert (e->expr_type == EXPR_COMPCALL);
genname = e->value.compcall.name; genname = e->value.compcall.name;
...@@ -5236,6 +5275,19 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name) ...@@ -5236,6 +5275,19 @@ resolve_typebound_generic_call (gfc_expr* e, const char **name)
return FAILURE; return FAILURE;
success: success:
/* Make sure that we have the right specific instance for the name. */
genname = e->value.compcall.tbp->u.specific->name;
/* Is the symtree name a "unique name". */
if (*genname == '@')
genname = e->value.compcall.tbp->u.specific->n.sym->name;
derived = get_declared_from_expr (NULL, NULL, e);
st = gfc_find_typebound_proc (derived, NULL, genname, false, &e->where);
if (st)
e->value.compcall.tbp = st->n.tb;
return SUCCESS; return SUCCESS;
} }
...@@ -5343,38 +5395,6 @@ resolve_compcall (gfc_expr* e, const char **name) ...@@ -5343,38 +5395,6 @@ resolve_compcall (gfc_expr* e, const char **name)
} }
/* Get the ultimate declared type from an expression. In addition,
return the last class/derived type reference and the copy of the
reference list. */
static gfc_symbol*
get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref,
gfc_expr *e)
{
gfc_symbol *declared;
gfc_ref *ref;
declared = NULL;
*class_ref = NULL;
*new_ref = gfc_copy_ref (e->ref);
for (ref = *new_ref; ref; ref = ref->next)
{
if (ref->type != REF_COMPONENT)
continue;
if (ref->u.c.component->ts.type == BT_CLASS
|| ref->u.c.component->ts.type == BT_DERIVED)
{
declared = ref->u.c.component->ts.u.derived;
*class_ref = ref;
}
}
if (declared == NULL)
declared = e->symtree->n.sym->ts.u.derived;
return declared;
}
/* Resolve a typebound function, or 'method'. First separate all /* Resolve a typebound function, or 'method'. First separate all
the non-CLASS references by calling resolve_compcall directly. */ the non-CLASS references by calling resolve_compcall directly. */
...@@ -5423,11 +5443,8 @@ resolve_typebound_function (gfc_expr* e) ...@@ -5423,11 +5443,8 @@ resolve_typebound_function (gfc_expr* e)
e->value.function.esym = NULL; e->value.function.esym = NULL;
e->symtree = st; e->symtree = st;
if (class_ref) if (new_ref)
{
gfc_free_ref_list (class_ref->next);
e->ref = new_ref; e->ref = new_ref;
}
/* '$vptr' points to the vtab, which contains the procedure pointers. */ /* '$vptr' points to the vtab, which contains the procedure pointers. */
gfc_add_component_ref (e, "$vptr"); gfc_add_component_ref (e, "$vptr");
...@@ -5496,11 +5513,8 @@ resolve_typebound_subroutine (gfc_code *code) ...@@ -5496,11 +5513,8 @@ resolve_typebound_subroutine (gfc_code *code)
code->expr1->value.function.esym = NULL; code->expr1->value.function.esym = NULL;
code->expr1->symtree = st; code->expr1->symtree = st;
if (class_ref) if (new_ref)
{
gfc_free_ref_list (class_ref->next);
code->expr1->ref = new_ref; code->expr1->ref = new_ref;
}
/* '$vptr' points to the vtab, which contains the procedure pointers. */ /* '$vptr' points to the vtab, which contains the procedure pointers. */
gfc_add_component_ref (code->expr1, "$vptr"); gfc_add_component_ref (code->expr1, "$vptr");
......
2010-06-05 Paul Thomas <pault@gcc.gnu.org> 2010-06-05 Paul Thomas <pault@gcc.gnu.org>
PR fortran/43945
* gfortran.dg/generic_23.f03: New test.
2010-06-05 Paul Thomas <pault@gcc.gnu.org>
PR fortran/43895 PR fortran/43895
* gfortran.dg/alloc_comp_class_1.f90 : New test. * gfortran.dg/alloc_comp_class_1.f90 : New test.
......
! { dg-do run }
! Test the fix for PR43945 in which the over-ridding of 'doit' and
! 'getit' in type 'foo2' was missed in the specific binding to 'do' and 'get'.
!
! Contributed by Tobias Burnus <burnus@gcc.gnu.org>
! and reported to clf by Salvatore Filippone <sfilippone@uniroma2.it>
!
module foo_mod
type foo
integer :: i
contains
procedure, pass(a) :: doit
procedure, pass(a) :: getit
generic, public :: do => doit
generic, public :: get => getit
end type foo
private doit,getit
contains
subroutine doit(a)
class(foo) :: a
a%i = 1
write(*,*) 'FOO%DOIT base version'
end subroutine doit
function getit(a) result(res)
class(foo) :: a
integer :: res
res = a%i
end function getit
end module foo_mod
module foo2_mod
use foo_mod
type, extends(foo) :: foo2
integer :: j
contains
procedure, pass(a) :: doit => doit2
procedure, pass(a) :: getit => getit2
!!$ generic, public :: do => doit
!!$ generic, public :: get => getit
end type foo2
private doit2, getit2
contains
subroutine doit2(a)
class(foo2) :: a
a%i = 2
a%j = 3
end subroutine doit2
function getit2(a) result(res)
class(foo2) :: a
integer :: res
res = a%j
end function getit2
end module foo2_mod
program testd15
use foo2_mod
type(foo2) :: af2
call af2%do()
if (af2%i .ne. 2) call abort
if (af2%get() .ne. 3) call abort
end program testd15
! { dg-final { cleanup-modules "foo_mod foo2_mod" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment