Commit eece1eb9 by Paul Thomas

[multiple changes]

2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43896
	* symbol.c (add_proc_component,copy_vtab_proc_comps): Remove
	initializers for PPC members of the vtabs.

2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42274
	* symbol.c (add_proc_component,add_proc_comps): Correctly set the 'ppc'
	attribute for all PPC members of the vtypes.
	(copy_vtab_proc_comps): Copy the correct interface.
	* trans.h (gfc_trans_assign_vtab_procs): Modified prototype.
	* trans-expr.c (gfc_trans_assign_vtab_procs): Pass the derived type as
	a dummy argument and make sure all PPC members of the vtab are
	initialized correctly.
	(gfc_conv_derived_to_class,gfc_trans_class_assign): Additional argument
	in call to gfc_trans_assign_vtab_procs.
	* trans-stmt.c (gfc_trans_allocate): Ditto.

2010-04-29  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/43326
	* resolve.c (resolve_typebound_function): Renamed
	resolve_class_compcall.Do all the detection of class references
	here.
	(resolve_typebound_subroutine): resolve_class_typebound_call
	renamed. Otherwise same as resolve_typebound_function.
	(gfc_resolve_expr): Call resolve_typebound_function.
	(resolve_code): Call resolve_typebound_subroutine.

2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43492
	* resolve.c (resolve_typebound_generic_call): For CLASS methods
	pass back the specific symtree name, rather than the target
	name.

2010-04-29  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/42353
	* resolve.c (resolve_structure_cons): Make the initializer of
	the vtab component 'extends' the same type as the component.

2010-04-29  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/42680
	* interface.c (check_interface1): Pass symbol name rather than NULL to
	gfc_compare_interfaces.(gfc_compare_interfaces): Add assert to
	trap MULL. (gfc_compare_derived_types): Revert previous change
	incorporated incorrectly during merge from trunk, r155778.
	* resolve.c (check_generic_tbp_ambiguity): Pass symbol name rather
	than NULL to gfc_compare_interfaces.
	* symbol.c (add_generic_specifics): Likewise.

2010-02-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42353
	* interface.c (gfc_compare_derived_types): Add condition for vtype.
	* symbol.c (gfc_find_derived_vtab): Sey access to private.
	(gfc_find_derived_vtab): Likewise.
	* module.c (ab_attribute): Add enumerator AB_VTAB.
	(mio_symbol_attribute): Use new attribute, AB_VTAB.
	(check_for_ambiguous): Likewise.

2010-04-29  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41829
	* trans-expr.c (select_class_proc): Remove function.
	(conv_function_val): Delete reference to previous.
	(gfc_conv_derived_to_class): Add second argument to the call to
	gfc_find_derived_vtab.
	(gfc_conv_structure): Exclude proc_pointer components when
	accessing $data field of class objects.
	(gfc_trans_assign_vtab_procs): New function.
	(gfc_trans_class_assign): Add second argument to the call to
	gfc_find_derived_vtab.
	* symbol.c (gfc_build_class_symbol): Add delayed_vtab arg and
	implement holding off searching for the vptr derived type.
	(add_proc_component): New function.
	(add_proc_comps): New function.
	(add_procs_to_declared_vtab1): New function.
	(copy_vtab_proc_comps): New function.
	(add_procs_to_declared_vtab): New function.
	(void add_generic_specifics): New function.
	(add_generics_to_declared_vtab): New function.
	(gfc_find_derived_vtab): Add second argument to the call to
	gfc_find_derived_vtab. Add the calls to
	add_procs_to_declared_vtab and add_generics_to_declared_vtab.
	* decl.c (build_sym, build_struct): Use new arg in calls to
	gfc_build_class_symbol.
	* gfortran.h : Add vtype bitfield to symbol_attr. Remove the
	definition of struct gfc_class_esym_list. Modify prototypes
	of gfc_build_class_symbol and gfc_find_derived_vtab.
	* trans-stmt.c (gfc_trans_allocate): Add second argument to the
	call to gfc_find_derived_vtab.
	* module.c : Add the vtype attribute.
	* trans.h : Add prototype for gfc_trans_assign_vtab_procs.
	* resolve.c (resolve_typebound_generic_call): Add second arg
	to pass along the generic name for class methods.
	(resolve_typebound_call): The same.
	(resolve_compcall): Use the second arg to carry the generic
	name from the above. Remove the reference to class_esym.
	(check_members, check_class_members, resolve_class_esym,
	hash_value_expr): Remove functions.
	(resolve_class_compcall, resolve_class_typebound_call): Modify
	to use vtable rather than member by member calls.
	(gfc_resolve_expr): Modify second arg in call to
	resolve_compcall.
	(resolve_select_type): Add second arg in call to
	gfc_find_derived_vtab.
	(resolve_code): Add second arg in call resolve_typebound_call.
	(resolve_fl_derived): Exclude vtypes from check for late
	procedure definitions. Likewise for checking of explicit
	interface and checking of pass arg.
	* iresolve.c (gfc_resolve_extends_type_of): Add second arg in
	calls to gfc_find_derived_vtab.
	* match.c (select_type_set_tmp): Use new arg in call to
	gfc_build_class_symbol.
	* trans-decl.c (gfc_get_symbol_decl): Complete vtable if
	necessary.
	* parse.c (endType): Finish incomplete classes.


2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42274
	* gfortran.dg/class_16.f03: New test.

2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/42274
	* gfortran.dg/class_15.f03: New.

2010-04-29  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/43326
	* gfortran.dg/dynamic_dispatch_9.f03: New test.

2010-04-29  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/43492
	* gfortran.dg/generic_22.f03 : New test.

2010-04-29  Paul Thomas  <pault@gcc.gnu.org>

	PR fortran/42353
	* gfortran.dg/class_14.f03: New test.

2010-04-29  Jerry DeLisle  <jvdelisle@gcc.gnu.org>

	PR fortran/42680
	* gfortran.dg/interface_32.f90: New test.

2009-04-29  Paul Thomas  <pault@gcc.gnu.org>
	    Janus Weil  <janus@gcc.gnu.org>

	PR fortran/41829
	* gfortran.dg/dynamic_dispatch_5.f03 : Change to "run".
	* gfortran.dg/dynamic_dispatch_7.f03 : New test.
	* gfortran.dg/dynamic_dispatch_8.f03 : New test.

From-SVN: r158910
parent 716a3481
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/43896
* symbol.c (add_proc_component,copy_vtab_proc_comps): Remove
initializers for PPC members of the vtabs.
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/42274
* symbol.c (add_proc_component,add_proc_comps): Correctly set the 'ppc'
attribute for all PPC members of the vtypes.
(copy_vtab_proc_comps): Copy the correct interface.
* trans.h (gfc_trans_assign_vtab_procs): Modified prototype.
* trans-expr.c (gfc_trans_assign_vtab_procs): Pass the derived type as
a dummy argument and make sure all PPC members of the vtab are
initialized correctly.
(gfc_conv_derived_to_class,gfc_trans_class_assign): Additional argument
in call to gfc_trans_assign_vtab_procs.
* trans-stmt.c (gfc_trans_allocate): Ditto.
2010-04-29 Paul Thomas <pault@gcc.gnu.org>
PR fortran/43326
* resolve.c (resolve_typebound_function): Renamed
resolve_class_compcall.Do all the detection of class references
here.
(resolve_typebound_subroutine): resolve_class_typebound_call
renamed. Otherwise same as resolve_typebound_function.
(gfc_resolve_expr): Call resolve_typebound_function.
(resolve_code): Call resolve_typebound_subroutine.
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/43492
* resolve.c (resolve_typebound_generic_call): For CLASS methods
pass back the specific symtree name, rather than the target
name.
2010-04-29 Paul Thomas <pault@gcc.gnu.org>
PR fortran/42353
* resolve.c (resolve_structure_cons): Make the initializer of
the vtab component 'extends' the same type as the component.
2010-04-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/42680
* interface.c (check_interface1): Pass symbol name rather than NULL to
gfc_compare_interfaces.(gfc_compare_interfaces): Add assert to
trap MULL. (gfc_compare_derived_types): Revert previous change
incorporated incorrectly during merge from trunk, r155778.
* resolve.c (check_generic_tbp_ambiguity): Pass symbol name rather
than NULL to gfc_compare_interfaces.
* symbol.c (add_generic_specifics): Likewise.
2010-02-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/42353
* interface.c (gfc_compare_derived_types): Add condition for vtype.
* symbol.c (gfc_find_derived_vtab): Sey access to private.
(gfc_find_derived_vtab): Likewise.
* module.c (ab_attribute): Add enumerator AB_VTAB.
(mio_symbol_attribute): Use new attribute, AB_VTAB.
(check_for_ambiguous): Likewise.
2010-04-29 Paul Thomas <pault@gcc.gnu.org>
Janus Weil <janus@gcc.gnu.org>
PR fortran/41829
* trans-expr.c (select_class_proc): Remove function.
(conv_function_val): Delete reference to previous.
(gfc_conv_derived_to_class): Add second argument to the call to
gfc_find_derived_vtab.
(gfc_conv_structure): Exclude proc_pointer components when
accessing $data field of class objects.
(gfc_trans_assign_vtab_procs): New function.
(gfc_trans_class_assign): Add second argument to the call to
gfc_find_derived_vtab.
* symbol.c (gfc_build_class_symbol): Add delayed_vtab arg and
implement holding off searching for the vptr derived type.
(add_proc_component): New function.
(add_proc_comps): New function.
(add_procs_to_declared_vtab1): New function.
(copy_vtab_proc_comps): New function.
(add_procs_to_declared_vtab): New function.
(void add_generic_specifics): New function.
(add_generics_to_declared_vtab): New function.
(gfc_find_derived_vtab): Add second argument to the call to
gfc_find_derived_vtab. Add the calls to
add_procs_to_declared_vtab and add_generics_to_declared_vtab.
* decl.c (build_sym, build_struct): Use new arg in calls to
gfc_build_class_symbol.
* gfortran.h : Add vtype bitfield to symbol_attr. Remove the
definition of struct gfc_class_esym_list. Modify prototypes
of gfc_build_class_symbol and gfc_find_derived_vtab.
* trans-stmt.c (gfc_trans_allocate): Add second argument to the
call to gfc_find_derived_vtab.
* module.c : Add the vtype attribute.
* trans.h : Add prototype for gfc_trans_assign_vtab_procs.
* resolve.c (resolve_typebound_generic_call): Add second arg
to pass along the generic name for class methods.
(resolve_typebound_call): The same.
(resolve_compcall): Use the second arg to carry the generic
name from the above. Remove the reference to class_esym.
(check_members, check_class_members, resolve_class_esym,
hash_value_expr): Remove functions.
(resolve_class_compcall, resolve_class_typebound_call): Modify
to use vtable rather than member by member calls.
(gfc_resolve_expr): Modify second arg in call to
resolve_compcall.
(resolve_select_type): Add second arg in call to
gfc_find_derived_vtab.
(resolve_code): Add second arg in call resolve_typebound_call.
(resolve_fl_derived): Exclude vtypes from check for late
procedure definitions. Likewise for checking of explicit
interface and checking of pass arg.
* iresolve.c (gfc_resolve_extends_type_of): Add second arg in
calls to gfc_find_derived_vtab.
* match.c (select_type_set_tmp): Use new arg in call to
gfc_build_class_symbol.
* trans-decl.c (gfc_get_symbol_decl): Complete vtable if
necessary.
* parse.c (endType): Finish incomplete classes.
2010-04-28 Tobias Burnus <burnus@net-b.de> 2010-04-28 Tobias Burnus <burnus@net-b.de>
PR fortran/18918 PR fortran/18918
......
...@@ -1160,7 +1160,7 @@ build_sym (const char *name, gfc_charlen *cl, ...@@ -1160,7 +1160,7 @@ build_sym (const char *name, gfc_charlen *cl,
sym->attr.class_ok = (sym->attr.dummy sym->attr.class_ok = (sym->attr.dummy
|| sym->attr.pointer || sym->attr.pointer
|| sym->attr.allocatable) ? 1 : 0; || sym->attr.allocatable) ? 1 : 0;
gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as); gfc_build_class_symbol (&sym->ts, &sym->attr, &sym->as, false);
} }
return SUCCESS; return SUCCESS;
...@@ -1570,7 +1570,7 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init, ...@@ -1570,7 +1570,7 @@ build_struct (const char *name, gfc_charlen *cl, gfc_expr **init,
scalar: scalar:
if (c->ts.type == BT_CLASS) if (c->ts.type == BT_CLASS)
gfc_build_class_symbol (&c->ts, &c->attr, &c->as); gfc_build_class_symbol (&c->ts, &c->attr, &c->as, true);
return t; return t;
} }
......
...@@ -691,7 +691,8 @@ typedef struct ...@@ -691,7 +691,8 @@ typedef struct
unsigned extension:8; /* extension level of a derived type. */ unsigned extension:8; /* extension level of a derived type. */
unsigned is_class:1; /* is a CLASS container. */ unsigned is_class:1; /* is a CLASS container. */
unsigned class_ok:1; /* is a CLASS object with correct attributes. */ unsigned class_ok:1; /* is a CLASS object with correct attributes. */
unsigned vtab:1; /* is a derived type vtab. */ unsigned vtab:1; /* is a derived type vtab, pointed to by CLASS objects. */
unsigned vtype:1; /* is a derived type of a vtab. */
/* These flags are both in the typespec and attribute. The attribute /* These flags are both in the typespec and attribute. The attribute
list is what gets read from/written to a module file. The typespec list is what gets read from/written to a module file. The typespec
...@@ -1615,17 +1616,6 @@ typedef struct gfc_intrinsic_sym ...@@ -1615,17 +1616,6 @@ typedef struct gfc_intrinsic_sym
gfc_intrinsic_sym; gfc_intrinsic_sym;
typedef struct gfc_class_esym_list
{
gfc_symbol *derived;
gfc_symbol *esym;
struct gfc_expr *hash_value;
struct gfc_class_esym_list *next;
}
gfc_class_esym_list;
#define gfc_get_class_esym_list() XCNEW (gfc_class_esym_list)
/* Expression nodes. The expression node types deserve explanations, /* Expression nodes. The expression node types deserve explanations,
since the last couple can be easily misconstrued: since the last couple can be easily misconstrued:
...@@ -1717,7 +1707,6 @@ typedef struct gfc_expr ...@@ -1717,7 +1707,6 @@ typedef struct gfc_expr
const char *name; /* Points to the ultimate name of the function */ const char *name; /* Points to the ultimate name of the function */
gfc_intrinsic_sym *isym; gfc_intrinsic_sym *isym;
gfc_symbol *esym; gfc_symbol *esym;
gfc_class_esym_list *class_esym;
} }
function; function;
...@@ -2526,8 +2515,8 @@ gfc_gsymbol *gfc_get_gsymbol (const char *); ...@@ -2526,8 +2515,8 @@ gfc_gsymbol *gfc_get_gsymbol (const char *);
gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *); gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *);
gfc_try gfc_build_class_symbol (gfc_typespec *, symbol_attribute *, gfc_try gfc_build_class_symbol (gfc_typespec *, symbol_attribute *,
gfc_array_spec **); gfc_array_spec **, bool);
gfc_symbol *gfc_find_derived_vtab (gfc_symbol *); gfc_symbol *gfc_find_derived_vtab (gfc_symbol *, bool);
gfc_typebound_proc* gfc_get_typebound_proc (void); gfc_typebound_proc* gfc_get_typebound_proc (void);
gfc_symbol* gfc_get_derived_super_type (gfc_symbol*); gfc_symbol* gfc_get_derived_super_type (gfc_symbol*);
gfc_symbol* gfc_get_ultimate_derived_super_type (gfc_symbol*); gfc_symbol* gfc_get_ultimate_derived_super_type (gfc_symbol*);
......
...@@ -1129,8 +1129,8 @@ check_interface1 (gfc_interface *p, gfc_interface *q0, ...@@ -1129,8 +1129,8 @@ check_interface1 (gfc_interface *p, gfc_interface *q0,
if (p->sym->name == q->sym->name && p->sym->module == q->sym->module) if (p->sym->name == q->sym->name && p->sym->module == q->sym->module)
continue; continue;
if (gfc_compare_interfaces (p->sym, q->sym, q->sym->name, generic_flag, 0, if (gfc_compare_interfaces (p->sym, q->sym, q->sym->name, generic_flag,
NULL, 0)) 0, NULL, 0))
{ {
if (referenced) if (referenced)
gfc_error ("Ambiguous interfaces '%s' and '%s' in %s at %L", gfc_error ("Ambiguous interfaces '%s' and '%s' in %s at %L",
......
...@@ -832,7 +832,7 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo) ...@@ -832,7 +832,7 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo)
gfc_add_component_ref (a, "$vptr"); gfc_add_component_ref (a, "$vptr");
else if (a->ts.type == BT_DERIVED) else if (a->ts.type == BT_DERIVED)
{ {
vtab = gfc_find_derived_vtab (a->ts.u.derived); vtab = gfc_find_derived_vtab (a->ts.u.derived, false);
/* Clear the old expr. */ /* Clear the old expr. */
gfc_free_ref_list (a->ref); gfc_free_ref_list (a->ref);
memset (a, '\0', sizeof (gfc_expr)); memset (a, '\0', sizeof (gfc_expr));
...@@ -848,7 +848,7 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo) ...@@ -848,7 +848,7 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo)
gfc_add_component_ref (mo, "$vptr"); gfc_add_component_ref (mo, "$vptr");
else if (mo->ts.type == BT_DERIVED) else if (mo->ts.type == BT_DERIVED)
{ {
vtab = gfc_find_derived_vtab (mo->ts.u.derived); vtab = gfc_find_derived_vtab (mo->ts.u.derived, false);
/* Clear the old expr. */ /* Clear the old expr. */
gfc_free_ref_list (mo->ref); gfc_free_ref_list (mo->ref);
memset (mo, '\0', sizeof (gfc_expr)); memset (mo, '\0', sizeof (gfc_expr));
......
...@@ -4280,7 +4280,7 @@ select_type_set_tmp (gfc_typespec *ts) ...@@ -4280,7 +4280,7 @@ select_type_set_tmp (gfc_typespec *ts)
if (ts->type == BT_CLASS) if (ts->type == BT_CLASS)
{ {
gfc_build_class_symbol (&tmp->n.sym->ts, &tmp->n.sym->attr, gfc_build_class_symbol (&tmp->n.sym->ts, &tmp->n.sym->attr,
&tmp->n.sym->as); &tmp->n.sym->as, false);
tmp->n.sym->attr.class_ok = 1; tmp->n.sym->attr.class_ok = 1;
} }
......
...@@ -1674,7 +1674,7 @@ typedef enum ...@@ -1674,7 +1674,7 @@ typedef enum
AB_POINTER_COMP, AB_PRIVATE_COMP, AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_POINTER_COMP, AB_PRIVATE_COMP, AB_VALUE, AB_VOLATILE, AB_PROTECTED,
AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP, AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION, AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
AB_COARRAY_COMP AB_COARRAY_COMP, AB_VTYPE, AB_VTAB
} }
ab_attribute; ab_attribute;
...@@ -1720,6 +1720,8 @@ static const mstring attr_bits[] = ...@@ -1720,6 +1720,8 @@ static const mstring attr_bits[] =
minit ("IS_CLASS", AB_IS_CLASS), minit ("IS_CLASS", AB_IS_CLASS),
minit ("PROCEDURE", AB_PROCEDURE), minit ("PROCEDURE", AB_PROCEDURE),
minit ("PROC_POINTER", AB_PROC_POINTER), minit ("PROC_POINTER", AB_PROC_POINTER),
minit ("VTYPE", AB_VTYPE),
minit ("VTAB", AB_VTAB),
minit (NULL, -1) minit (NULL, -1)
}; };
...@@ -1880,6 +1882,10 @@ mio_symbol_attribute (symbol_attribute *attr) ...@@ -1880,6 +1882,10 @@ mio_symbol_attribute (symbol_attribute *attr)
MIO_NAME (ab_attribute) (AB_PROCEDURE, attr_bits); MIO_NAME (ab_attribute) (AB_PROCEDURE, attr_bits);
if (attr->proc_pointer) if (attr->proc_pointer)
MIO_NAME (ab_attribute) (AB_PROC_POINTER, attr_bits); MIO_NAME (ab_attribute) (AB_PROC_POINTER, attr_bits);
if (attr->vtype)
MIO_NAME (ab_attribute) (AB_VTYPE, attr_bits);
if (attr->vtab)
MIO_NAME (ab_attribute) (AB_VTAB, attr_bits);
mio_rparen (); mio_rparen ();
...@@ -2016,6 +2022,12 @@ mio_symbol_attribute (symbol_attribute *attr) ...@@ -2016,6 +2022,12 @@ mio_symbol_attribute (symbol_attribute *attr)
case AB_PROC_POINTER: case AB_PROC_POINTER:
attr->proc_pointer = 1; attr->proc_pointer = 1;
break; break;
case AB_VTYPE:
attr->vtype = 1;
break;
case AB_VTAB:
attr->vtab = 1;
break;
} }
} }
} }
...@@ -4201,6 +4213,9 @@ check_for_ambiguous (gfc_symbol *st_sym, pointer_info *info) ...@@ -4201,6 +4213,9 @@ check_for_ambiguous (gfc_symbol *st_sym, pointer_info *info)
if (st_sym == rsym) if (st_sym == rsym)
return false; return false;
if (st_sym->attr.vtab || st_sym->attr.vtype)
return false;
/* If the existing symbol is generic from a different module and /* If the existing symbol is generic from a different module and
the new symbol is generic there can be no ambiguity. */ the new symbol is generic there can be no ambiguity. */
if (st_sym->attr.generic if (st_sym->attr.generic
......
...@@ -2110,6 +2110,22 @@ endType: ...@@ -2110,6 +2110,22 @@ endType:
|| c->attr.access == ACCESS_PRIVATE || c->attr.access == ACCESS_PRIVATE
|| (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.private_comp)) || (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.private_comp))
sym->attr.private_comp = 1; sym->attr.private_comp = 1;
/* Fix up incomplete CLASS components. */
if (c->ts.type == BT_CLASS)
{
gfc_component *data;
gfc_component *vptr;
gfc_symbol *vtab;
data = gfc_find_component (c->ts.u.derived, "$data", true, true);
vptr = gfc_find_component (c->ts.u.derived, "$vptr", true, true);
if (vptr->ts.u.derived == NULL)
{
vtab = gfc_find_derived_vtab (data->ts.u.derived, false);
gcc_assert (vtab);
vptr->ts.u.derived = vtab->ts.u.derived;
}
}
} }
if (!seen_component) if (!seen_component)
......
...@@ -1070,6 +1070,15 @@ gfc_get_symbol_decl (gfc_symbol * sym) ...@@ -1070,6 +1070,15 @@ gfc_get_symbol_decl (gfc_symbol * sym)
else else
byref = 0; byref = 0;
/* Make sure that the vtab for the declared type is completed. */
if (sym->ts.type == BT_CLASS)
{
gfc_component *c = gfc_find_component (sym->ts.u.derived,
"$data", true, true);
if (!c->ts.u.derived->backend_decl)
gfc_find_derived_vtab (c->ts.u.derived, true);
}
if ((sym->attr.dummy && ! sym->attr.function) || (sym->attr.result && byref)) if ((sym->attr.dummy && ! sym->attr.function) || (sym->attr.result && byref))
{ {
/* Return via extra parameter. */ /* Return via extra parameter. */
......
...@@ -1532,141 +1532,11 @@ get_proc_ptr_comp (gfc_expr *e) ...@@ -1532,141 +1532,11 @@ get_proc_ptr_comp (gfc_expr *e)
} }
/* Select a class typebound procedure at runtime. */
static void
select_class_proc (gfc_se *se, gfc_class_esym_list *elist,
tree declared, gfc_expr *expr)
{
tree end_label;
tree label;
tree tmp;
tree hash;
stmtblock_t body;
gfc_class_esym_list *next_elist, *tmp_elist;
gfc_se tmpse;
/* Convert the hash expression. */
gfc_init_se (&tmpse, NULL);
gfc_conv_expr (&tmpse, elist->hash_value);
gfc_add_block_to_block (&se->pre, &tmpse.pre);
hash = gfc_evaluate_now (tmpse.expr, &se->pre);
gfc_add_block_to_block (&se->post, &tmpse.post);
/* Fix the function type to be that of the declared type method. */
declared = gfc_create_var (TREE_TYPE (declared), "method");
end_label = gfc_build_label_decl (NULL_TREE);
gfc_init_block (&body);
/* Go through the list of extensions. */
for (; elist; elist = next_elist)
{
/* This case has already been added. */
if (elist->derived == NULL)
goto free_elist;
/* Skip abstract base types. */
if (elist->derived->attr.abstract)
goto free_elist;
/* Run through the chain picking up all the cases that call the
same procedure. */
tmp_elist = elist;
for (; elist; elist = elist->next)
{
tree cval;
if (elist->esym != tmp_elist->esym)
continue;
cval = build_int_cst (TREE_TYPE (hash),
elist->derived->hash_value);
/* Build a label for the hash value. */
label = gfc_build_label_decl (NULL_TREE);
tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
cval, NULL_TREE, label);
gfc_add_expr_to_block (&body, tmp);
/* Null the reference the derived type so that this case is
not used again. */
elist->derived = NULL;
}
elist = tmp_elist;
/* Get a pointer to the procedure, */
tmp = gfc_get_symbol_decl (elist->esym);
if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
{
gcc_assert (TREE_CODE (tmp) == FUNCTION_DECL);
tmp = gfc_build_addr_expr (NULL_TREE, tmp);
}
/* Assign the pointer to the appropriate procedure. */
gfc_add_modify (&body, declared,
fold_convert (TREE_TYPE (declared), tmp));
/* Break to the end of the construct. */
tmp = build1_v (GOTO_EXPR, end_label);
gfc_add_expr_to_block (&body, tmp);
/* Free the elists as we go; freeing them in gfc_free_expr causes
segfaults because it occurs too early and too often. */
free_elist:
next_elist = elist->next;
if (elist->hash_value)
gfc_free_expr (elist->hash_value);
gfc_free (elist);
elist = NULL;
}
/* Default is an error. */
label = gfc_build_label_decl (NULL_TREE);
tmp = fold_build3 (CASE_LABEL_EXPR, void_type_node,
NULL_TREE, NULL_TREE, label);
gfc_add_expr_to_block (&body, tmp);
tmp = gfc_trans_runtime_error (true, &expr->where,
"internal error: bad hash value in dynamic dispatch");
gfc_add_expr_to_block (&body, tmp);
/* Write the switch expression. */
tmp = gfc_finish_block (&body);
tmp = build3_v (SWITCH_EXPR, hash, tmp, NULL_TREE);
gfc_add_expr_to_block (&se->pre, tmp);
tmp = build1_v (LABEL_EXPR, end_label);
gfc_add_expr_to_block (&se->pre, tmp);
se->expr = declared;
return;
}
static void static void
conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr) conv_function_val (gfc_se * se, gfc_symbol * sym, gfc_expr * expr)
{ {
tree tmp; tree tmp;
if (expr && expr->symtree
&& expr->value.function.class_esym)
{
if (!sym->backend_decl)
sym->backend_decl = gfc_get_extern_function_decl (sym);
tmp = sym->backend_decl;
if (!POINTER_TYPE_P (TREE_TYPE (tmp)))
{
gcc_assert (TREE_CODE (tmp) == FUNCTION_DECL);
tmp = gfc_build_addr_expr (NULL_TREE, tmp);
}
select_class_proc (se, expr->value.function.class_esym,
tmp, expr);
return;
}
if (gfc_is_proc_ptr_comp (expr, NULL)) if (gfc_is_proc_ptr_comp (expr, NULL))
tmp = get_proc_ptr_comp (expr); tmp = get_proc_ptr_comp (expr);
else if (sym->attr.dummy) else if (sym->attr.dummy)
...@@ -2614,8 +2484,9 @@ gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e, ...@@ -2614,8 +2484,9 @@ gfc_conv_derived_to_class (gfc_se *parmse, gfc_expr *e,
/* Remember the vtab corresponds to the derived type /* Remember the vtab corresponds to the derived type
not to the class declared type. */ not to the class declared type. */
vtab = gfc_find_derived_vtab (e->ts.u.derived); vtab = gfc_find_derived_vtab (e->ts.u.derived, true);
gcc_assert (vtab); gcc_assert (vtab);
gfc_trans_assign_vtab_procs (&parmse->pre, e->ts.u.derived, vtab);
tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab)); tmp = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtab));
gfc_add_modify (&parmse->pre, ctree, gfc_add_modify (&parmse->pre, ctree,
fold_convert (TREE_TYPE (ctree), tmp)); fold_convert (TREE_TYPE (ctree), tmp));
...@@ -4463,7 +4334,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) ...@@ -4463,7 +4334,7 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
if (!c->expr || cm->attr.allocatable) if (!c->expr || cm->attr.allocatable)
continue; continue;
if (cm->ts.type == BT_CLASS) if (cm->ts.type == BT_CLASS && !cm->attr.proc_pointer)
{ {
gfc_component *data; gfc_component *data;
data = gfc_find_component (cm->ts.u.derived, "$data", true, true); data = gfc_find_component (cm->ts.u.derived, "$data", true, true);
...@@ -4484,10 +4355,11 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init) ...@@ -4484,10 +4355,11 @@ gfc_conv_structure (gfc_se * se, gfc_expr * expr, int init)
else if (cm->initializer && cm->initializer->expr_type != EXPR_NULL else if (cm->initializer && cm->initializer->expr_type != EXPR_NULL
&& strcmp (cm->name, "$extends") == 0) && strcmp (cm->name, "$extends") == 0)
{ {
tree vtab;
gfc_symbol *vtabs; gfc_symbol *vtabs;
vtabs = cm->initializer->symtree->n.sym; vtabs = cm->initializer->symtree->n.sym;
val = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtabs)); vtab = gfc_build_addr_expr (NULL_TREE, gfc_get_symbol_decl (vtabs));
CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, val); CONSTRUCTOR_APPEND_ELT (v, cm->backend_decl, vtab);
} }
else else
{ {
...@@ -5579,6 +5451,103 @@ gfc_trans_assign (gfc_code * code) ...@@ -5579,6 +5451,103 @@ gfc_trans_assign (gfc_code * code)
} }
/* Generate code to assign typebound procedures to a derived vtab. */
void gfc_trans_assign_vtab_procs (stmtblock_t *block, gfc_symbol *dt,
gfc_symbol *vtab)
{
gfc_component *cmp;
tree vtb;
tree ctree;
tree proc;
tree cond = NULL_TREE;
stmtblock_t body;
bool seen_extends;
/* Point to the first procedure pointer. */
cmp = gfc_find_component (vtab->ts.u.derived, "$extends", true, true);
seen_extends = (cmp != NULL);
vtb = gfc_get_symbol_decl (vtab);
if (seen_extends)
{
cmp = cmp->next;
if (!cmp)
return;
ctree = fold_build3 (COMPONENT_REF, TREE_TYPE (cmp->backend_decl),
vtb, cmp->backend_decl, NULL_TREE);
cond = fold_build2 (EQ_EXPR, boolean_type_node, ctree,
build_int_cst (TREE_TYPE (ctree), 0));
}
else
{
cmp = vtab->ts.u.derived->components;
}
gfc_init_block (&body);
for (; cmp; cmp = cmp->next)
{
gfc_symbol *target = NULL;
/* Generic procedure - build its vtab. */
if (cmp->ts.type == BT_DERIVED && !cmp->tb)
{
gfc_symbol *vt = cmp->ts.interface;
if (vt == NULL)
{
/* Use association loses the interface. Obtain the vtab
by name instead. */
char name[2 * GFC_MAX_SYMBOL_LEN + 8];
sprintf (name, "vtab$%s$%s", vtab->ts.u.derived->name,
cmp->name);
gfc_find_symbol (name, vtab->ns, 0, &vt);
if (vt == NULL)
continue;
}
gfc_trans_assign_vtab_procs (&body, dt, vt);
ctree = fold_build3 (COMPONENT_REF, TREE_TYPE (cmp->backend_decl),
vtb, cmp->backend_decl, NULL_TREE);
proc = gfc_get_symbol_decl (vt);
proc = gfc_build_addr_expr (TREE_TYPE (ctree), proc);
gfc_add_modify (&body, ctree, proc);
continue;
}
/* This is required when typebound generic procedures are called
with derived type targets. The specific procedures do not get
added to the vtype, which remains "empty". */
if (cmp->tb && cmp->tb->u.specific && cmp->tb->u.specific->n.sym)
target = cmp->tb->u.specific->n.sym;
else
{
gfc_symtree *st;
st = gfc_find_typebound_proc (dt, NULL, cmp->name, false, NULL);
if (st->n.tb && st->n.tb->u.specific)
target = st->n.tb->u.specific->n.sym;
}
if (!target)
continue;
ctree = fold_build3 (COMPONENT_REF, TREE_TYPE (cmp->backend_decl),
vtb, cmp->backend_decl, NULL_TREE);
proc = gfc_get_symbol_decl (target);
proc = gfc_build_addr_expr (TREE_TYPE (ctree), proc);
gfc_add_modify (&body, ctree, proc);
}
proc = gfc_finish_block (&body);
if (seen_extends)
proc = build3_v (COND_EXPR, cond, proc, build_empty_stmt (input_location));
gfc_add_expr_to_block (block, proc);
}
/* Translate an assignment to a CLASS object /* Translate an assignment to a CLASS object
(pointer or ordinary assignment). */ (pointer or ordinary assignment). */
...@@ -5620,9 +5589,9 @@ gfc_trans_class_assign (gfc_code *code) ...@@ -5620,9 +5589,9 @@ gfc_trans_class_assign (gfc_code *code)
{ {
gfc_symbol *vtab; gfc_symbol *vtab;
gfc_symtree *st; gfc_symtree *st;
vtab = gfc_find_derived_vtab (code->expr2->ts.u.derived); vtab = gfc_find_derived_vtab (code->expr2->ts.u.derived, true);
gcc_assert (vtab); gcc_assert (vtab);
gfc_trans_assign_vtab_procs (&block, code->expr2->ts.u.derived, vtab);
rhs = gfc_get_expr (); rhs = gfc_get_expr ();
rhs->expr_type = EXPR_VARIABLE; rhs->expr_type = EXPR_VARIABLE;
gfc_find_sym_tree (vtab->name, NULL, 1, &st); gfc_find_sym_tree (vtab->name, NULL, 1, &st);
......
...@@ -4278,8 +4278,9 @@ gfc_trans_allocate (gfc_code * code) ...@@ -4278,8 +4278,9 @@ gfc_trans_allocate (gfc_code * code)
if (ts->type == BT_DERIVED) if (ts->type == BT_DERIVED)
{ {
vtab = gfc_find_derived_vtab (ts->u.derived); vtab = gfc_find_derived_vtab (ts->u.derived, true);
gcc_assert (vtab); gcc_assert (vtab);
gfc_trans_assign_vtab_procs (&block, ts->u.derived, vtab);
gfc_init_se (&lse, NULL); gfc_init_se (&lse, NULL);
lse.want_pointer = 1; lse.want_pointer = 1;
gfc_conv_expr (&lse, lhs); gfc_conv_expr (&lse, lhs);
......
...@@ -492,6 +492,9 @@ tree gfc_trans_assignment (gfc_expr *, gfc_expr *, bool, bool); ...@@ -492,6 +492,9 @@ tree gfc_trans_assignment (gfc_expr *, gfc_expr *, bool, bool);
/* Generate code for a pointer assignment. */ /* Generate code for a pointer assignment. */
tree gfc_trans_pointer_assignment (gfc_expr *, gfc_expr *); tree gfc_trans_pointer_assignment (gfc_expr *, gfc_expr *);
/* Generate code to assign typebound procedures to a derived vtab. */
void gfc_trans_assign_vtab_procs (stmtblock_t*, gfc_symbol*, gfc_symbol*);
/* Initialize function decls for library functions. */ /* Initialize function decls for library functions. */
void gfc_build_intrinsic_lib_fndecls (void); void gfc_build_intrinsic_lib_fndecls (void);
/* Create function decls for IO library functions. */ /* Create function decls for IO library functions. */
......
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/42274
* gfortran.dg/class_16.f03: New test.
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/42274
* gfortran.dg/class_15.f03: New.
2010-04-29 Paul Thomas <pault@gcc.gnu.org>
PR fortran/43326
* gfortran.dg/dynamic_dispatch_9.f03: New test.
2010-04-29 Janus Weil <janus@gcc.gnu.org>
PR fortran/43492
* gfortran.dg/generic_22.f03 : New test.
2010-04-29 Paul Thomas <pault@gcc.gnu.org>
PR fortran/42353
* gfortran.dg/class_14.f03: New test.
2010-04-29 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/42680
* gfortran.dg/interface_32.f90: New test.
2009-04-29 Paul Thomas <pault@gcc.gnu.org>
Janus Weil <janus@gcc.gnu.org>
PR fortran/41829
* gfortran.dg/dynamic_dispatch_5.f03 : Change to "run".
* gfortran.dg/dynamic_dispatch_7.f03 : New test.
* gfortran.dg/dynamic_dispatch_8.f03 : New test.
2010-04-28 Mike Stump <mikestump@comcast.net> 2010-04-28 Mike Stump <mikestump@comcast.net>
* g++.dg/uninit-pred-1_b.C: Use dg-message instead of * g++.dg/uninit-pred-1_b.C: Use dg-message instead of
......
! { dg-do "compile" }
! Test the final fix for PR42353, in which a compilation error was
! occurring because the derived type of the initializer of the vtab
! component '$extends' was not the same as that of the component.
!
! Contributed by Harald Anlauf <anlauf@gmx.de>
!
module abstract_vector
implicit none
type, abstract :: vector_class
end type vector_class
end module abstract_vector
!-------------------------
module concrete_vector
use abstract_vector
implicit none
type, extends(vector_class) :: trivial_vector_type
end type trivial_vector_type
private :: my_assign
contains
subroutine my_assign (this,v)
class(trivial_vector_type), intent(inout) :: this
class(vector_class), intent(in) :: v
end subroutine my_assign
end module concrete_vector
!---------------------------
module concrete_gradient
use abstract_vector
implicit none
type, abstract, extends(vector_class) :: gradient_class
end type gradient_class
type, extends(gradient_class) :: trivial_gradient_type
end type trivial_gradient_type
private :: my_assign
contains
subroutine my_assign (this,v)
class(trivial_gradient_type), intent(inout) :: this
class(vector_class), intent(in) :: v
end subroutine my_assign
end module concrete_gradient
!----------------------------
module concrete_inner_product
use concrete_vector
use concrete_gradient
implicit none
end module concrete_inner_product
! { dg-final { cleanup-modules "abstract_vector concrete_vector" } }
! { dg-final { cleanup-modules "concrete_gradient concrete_inner_product" } }
! { dg-do compile }
!
! PR 42274: [fortran-dev Regression] ICE: segmentation fault
!
! Original test case by Salvatore Filippone <sfilippone@uniroma2.it>
! Modified by Janus Weil <janus@gcc.gnu.org>
module mod_A
type :: t1
contains
procedure,nopass :: fun
end type
contains
logical function fun()
end function
end module
module mod_B
use mod_A
type, extends(t1) :: t2
contains
procedure :: sub1
end type
contains
subroutine sub1(a)
class(t2) :: a
end subroutine
end module
module mod_C
contains
subroutine sub2(b)
use mod_B
type(t2) :: b
end subroutine
end module
module mod_D
use mod_A
use mod_C
end module
! { dg-final { cleanup-modules "mod_A mod_B mod_C mod_D" } }
! { dg-do compile }
!
! PR 43896: [fortran-dev Regression] ICE in gfc_conv_variable, at fortran/trans-expr.c:551
!
! Contributed by Fran Martinez Fadrique <fmartinez@gmv.com>
module m_rotation_matrix
type t_rotation_matrix
contains
procedure :: array => rotation_matrix_array
end type
contains
function rotation_matrix_array( rot ) result(array)
class(t_rotation_matrix) :: rot
double precision, dimension(3,3) :: array
end function
end module
! { dg-final { cleanup-modules "m_rotation_matrix" } }
! { dg-do compile } ! { dg-do run }
! Tests the fix for PR4164656 in which the call to a%a%scal failed to compile. ! Tests the fix for PR4164656 in which the call to a%a%scal failed to compile.
! !
! Contributed by Salvatore Filippone <sfilippone@uniroma2.it> ! Contributed by Salvatore Filippone <sfilippone@uniroma2.it>
...@@ -166,7 +166,8 @@ contains ...@@ -166,7 +166,8 @@ contains
integer :: err_act integer :: err_act
character(len=20) :: name='csnmi' character(len=20) :: name='csnmi'
logical, parameter :: debug=.false. logical, parameter :: debug=.false.
print *, "s_scals" ! print *, "s_scals"
info = 0
call a%a%scal(d,info) call a%a%scal(d,info)
return return
end subroutine s_scals end subroutine s_scals
...@@ -180,6 +181,7 @@ end module s_mat_mod ...@@ -180,6 +181,7 @@ end module s_mat_mod
b%a => c b%a => c
a => b a => b
call a%scal (1.0_spk_, info) call a%scal (1.0_spk_, info)
if (info .ne. 700) call abort
end end
! { dg-final { cleanup-modules "const_mod base_mat_mod s_base_mat_mod s_mat_mod" } } ! { dg-final { cleanup-modules "const_mod base_mat_mod s_base_mat_mod s_mat_mod" } }
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
! Contributed by Janus Weil <janus@gcc.gnu.org> ! Contributed by Janus Weil <janus@gcc.gnu.org>
! !
module m1 module m1
type :: t1 type :: t1
contains contains
procedure :: sizeof procedure :: sizeof
end type end type
contains contains
...@@ -17,11 +17,10 @@ contains ...@@ -17,11 +17,10 @@ contains
sizeof = 1 sizeof = 1
end function sizeof end function sizeof
end module end module
module m2 module m2
use m1 use m1
type, extends(t1) :: t2 type, extends(t1) :: t2
contains contains
procedure :: sizeof => sizeof2 procedure :: sizeof => sizeof2
end type end type
...@@ -32,19 +31,18 @@ contains ...@@ -32,19 +31,18 @@ contains
end function end function
end module end module
module m3 module m3
use m2 use m2
type :: t3 type :: t3
class(t1), pointer :: a class(t1), pointer :: a
contains contains
procedure :: sizeof => sizeof3 procedure :: sizeof => sizeof3
end type end type
contains contains
integer function sizeof3(a) integer function sizeof3(a)
class(t3) :: a class(t3) :: a
sizeof3 = a%a%sizeof() sizeof3 = a%a%sizeof()
end function end function
end module end module
use m1 use m1
...@@ -57,8 +55,7 @@ end module ...@@ -57,8 +55,7 @@ end module
if ((z%sizeof() .ne. 1) .or. (z%a%sizeof() .ne. 1)) call abort if ((z%sizeof() .ne. 1) .or. (z%a%sizeof() .ne. 1)) call abort
z%a => y z%a => y
if ((z%sizeof() .ne. 2) .or. (z%a%sizeof() .ne. 2)) call abort if ((z%sizeof() .ne. 2) .or. (z%a%sizeof() .ne. 2)) call abort
end end
! { dg-final { cleanup-modules "m1 m2 m3" } } ! { dg-final { cleanup-modules "m1 m2 m3" } }
! { dg-do run }
!
! PR 41829: [OOP] Runtime error with dynamic dispatching. Tests
! dynamic dispatch in a case where the caller knows nothing about
! the dynamic type at compile time.
!
! Contributed by Salvatore Filippone <sfilippone@uniroma2.it>
!
module foo_mod
type foo
integer :: i
contains
procedure, pass(a) :: doit
procedure, pass(a) :: 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
end type foo2
private doit2, getit2
contains
subroutine doit2(a)
class(foo2) :: a
a%i = 2
a%j = 3
! write(*,*) 'FOO2%DOIT derived version'
end subroutine doit2
function getit2(a) result(res)
class(foo2) :: a
integer :: res
res = a%j
end function getit2
end module foo2_mod
module bar_mod
use foo_mod
type bar
class(foo), allocatable :: a
contains
procedure, pass(a) :: doit
procedure, pass(a) :: getit
end type bar
private doit,getit
contains
subroutine doit(a)
class(bar) :: a
call a%a%doit()
end subroutine doit
function getit(a) result(res)
class(bar) :: a
integer :: res
res = a%a%getit()
end function getit
end module bar_mod
program testd10
use foo_mod
use foo2_mod
use bar_mod
type(bar) :: a
allocate(foo :: a%a)
call a%doit()
! write(*,*) 'Getit value : ', a%getit()
if (a%getit() .ne. 1) call abort
deallocate(a%a)
allocate(foo2 :: a%a)
call a%doit()
! write(*,*) 'Getit value : ', a%getit()
if (a%getit() .ne. 3) call abort
end program testd10
! { dg-final { cleanup-modules "foo_mod foo2_mod bar_mod" } }
! { dg-do run }
!
! [OOP] Ensure that different specifc interfaces are
! handled properly by dynamic dispatch.
!
! Contributed by Salvatore Filippone <sfilippone@uniroma2.it>
!
module m
type :: t
contains
procedure :: a
generic :: gen => a
end type
type,extends(t) :: t2
contains
procedure :: b
generic :: gen => b
end type
contains
real function a(ct,x)
class(t) :: ct
real :: x
a=2*x
end function
integer function b(ct,x)
class(t2) :: ct
integer :: x
b=3*x
end function
end
use m
class(t), allocatable :: o1
type (t) :: t1
class(t2), allocatable :: o2
allocate(o1)
allocate(o2)
if (t1%gen(2.0) .ne. o1%gen(2.0)) call abort
if (t1%gen(2.0) .ne. o2%gen(2.0)) call abort
if (o2%gen(3) .ne. 9) call abort
end
! { dg-final { cleanup-modules "m" } }
! { dg-do compile }
! Test the fix for PR43492, in which the generic call caused and ICE.
!
! Contributed by Salvatore Filippone <sfilippone@uniroma2.it>
!
module base_mod
type :: base_mat
integer, private :: m, n
contains
procedure, pass(a) :: transp1 => base_transp1
generic, public :: transp => transp1
procedure, pass(a) :: transc1 => base_transc1
generic, public :: transc => transc1
end type base_mat
contains
subroutine base_transp1(a)
implicit none
class(base_mat), intent(inout) :: a
integer :: itmp
itmp = a%m
a%m = a%n
a%n = itmp
end subroutine base_transp1
subroutine base_transc1(a)
implicit none
class(base_mat), intent(inout) :: a
call a%transp()
!!$ call a%transp1()
end subroutine base_transc1
end module base_mod
! { dg-final { cleanup-modules "m" } }
! { dg-do compile }
module m1
implicit none
type, abstract :: vector_class
end type vector_class
end module m1
!---------------------------------------------------------------
module m2
use m1
implicit none
type, abstract :: inner_product_class
contains
procedure(dot), deferred :: dot_v_v
procedure(dot), deferred :: dot_g_g
procedure(sub), deferred :: D_times_v
procedure(sub), deferred :: D_times_g
end type inner_product_class
abstract interface
function dot (this,a,b)
import :: inner_product_class
import :: vector_class
class(inner_product_class), intent(in) :: this
class(vector_class), intent(in) :: a,b
real :: dot
end function
subroutine sub (this,a)
import :: inner_product_class
import :: vector_class
class(inner_product_class), intent(in) :: this
class(vector_class), intent(inout) :: a
end subroutine
end interface
end module m2
!---------------------------------------------------------------
module m3
use :: m1
use :: m2
implicit none
private
public :: gradient_class
type, abstract, extends(vector_class) :: gradient_class
class(inner_product_class), pointer :: my_inner_product => NULL()
contains
procedure, non_overridable :: inquire_inner_product
procedure(op_g_v), deferred :: to_vector
end type gradient_class
abstract interface
subroutine op_g_v(this,v)
import vector_class
import gradient_class
class(gradient_class), intent(in) :: this
class(vector_class), intent(inout) :: v
end subroutine
end interface
contains
function inquire_inner_product (this)
class(gradient_class) :: this
class(inner_product_class), pointer :: inquire_inner_product
inquire_inner_product => this%my_inner_product
end function inquire_inner_product
end module m3
!---------------------------------------------------------------
module m4
use m3
use m2
implicit none
contains
subroutine cg (g_initial)
class(gradient_class), intent(in) :: g_initial
class(inner_product_class), pointer :: ip_save
ip_save => g_initial%inquire_inner_product()
end subroutine cg
end module m4
! { dg-final { cleanup-modules "m1 m2 m3 m4" } }
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