This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: Type-bound procedure and procedure pointer component calls
- From: Daniel Kraft <d at domob dot eu>
- To: Janus Weil <jaydub66 at googlemail dot com>, Fortran List <fortran at gcc dot gnu dot org>
- Date: Tue, 26 Aug 2008 19:43:02 +0200
- Subject: Re: Type-bound procedure and procedure pointer component calls
- References: <48B19E34.7050709@domob.eu>
Hi all,
here's a new experimental patch for those interested (and to have it in
the archives in case my computer crashes :D); it handles module IO,
PASS, error handling and everything else I could think of (but of course
no dynamic dispatch still), no regressions including my own new tests on
GNU/Linux-x86-32.
Free for everyone to vivisect... But it still has some rough edges (and
some memory leaks), I'll clean them up and then submit a real patch (and
a ChangeLog) for review if there are no comments crushing my design in
the meantime ;)
So far,
Daniel
--
Done: Arc-Bar-Cav-Sam-Val-Wiz, Dwa-Elf-Gno-Hum-Orc, Law-Neu-Cha, Fem-Mal
To go: Hea-Kni-Mon-Pri-Ran-Rog-Tou
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c (revision 139571)
+++ gcc/fortran/trans-expr.c (working copy)
@@ -1785,6 +1785,7 @@ gfc_apply_interface_mapping_to_ref (gfc_
gfc_apply_interface_mapping_to_expr (mapping, ref->u.ar.offset);
break;
+ case REF_PROCEDURE:
case REF_COMPONENT:
break;
@@ -2007,6 +2008,10 @@ gfc_apply_interface_mapping_to_expr (gfc
}
break;
+ case EXPR_COMPCALL:
+ for (actual = expr->value.compcall.actual; actual; actual = actual->next)
+ gfc_apply_interface_mapping_to_expr (mapping, actual->expr);
+
case EXPR_ARRAY:
case EXPR_STRUCTURE:
gfc_apply_interface_mapping_to_cons (mapping, expr->value.constructor);
Index: gcc/fortran/symbol.c
===================================================================
--- gcc/fortran/symbol.c (revision 139571)
+++ gcc/fortran/symbol.c (working copy)
@@ -4266,7 +4266,7 @@ gfc_get_derived_super_type (gfc_symbol*
through the super-types). */
gfc_symtree*
-gfc_find_typebound_proc (gfc_symbol* derived, const char* name)
+gfc_find_typebound_proc (gfc_symbol* derived, const char* name, bool noaccess)
{
gfc_symtree* res;
@@ -4274,7 +4274,19 @@ gfc_find_typebound_proc (gfc_symbol* der
gcc_assert (derived->f2k_derived);
res = gfc_find_symtree (derived->f2k_derived->sym_root, name);
if (res)
- return res->typebound ? res : NULL;
+ {
+ if (!res->typebound)
+ return NULL;
+
+ if (!noaccess && derived->attr.use_assoc
+ && res->typebound->access == ACCESS_PRIVATE)
+ gfc_error_now ("'%s' of '%s' is PRIVATE at %C", name, derived->name);
+ /* XXX: Should I replace the gfc_error_now above by a gfc_error? This
+ should be possible by some (not much) effort with returning an
+ optional gfc_try FAILURE here. */
+
+ return res;
+ }
/* Otherwise, recurse on parent type if derived is an extension. */
if (derived->attr.extension)
@@ -4282,7 +4294,7 @@ gfc_find_typebound_proc (gfc_symbol* der
gfc_symbol* super_type;
super_type = gfc_get_derived_super_type (derived);
gcc_assert (super_type);
- return gfc_find_typebound_proc (super_type, name);
+ return gfc_find_typebound_proc (super_type, name, noaccess);
}
/* Nothing found. */
Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c (revision 139571)
+++ gcc/fortran/decl.c (working copy)
@@ -6888,7 +6888,7 @@ match_procedure_in_type (void)
}
/* Construct the data structure. */
- tb = XCNEW (gfc_typebound_proc);
+ tb = gfc_get_typebound_proc ();
tb->where = gfc_current_locus;
/* Match binding attributes. */
Index: gcc/fortran/trans-openmp.c
===================================================================
--- gcc/fortran/trans-openmp.c (revision 139571)
+++ gcc/fortran/trans-openmp.c (working copy)
@@ -498,6 +498,7 @@ gfc_trans_omp_array_reduction (tree c, g
e1->symtree = symtree1;
e1->ts = sym->ts;
e1->ref = ref = gfc_get_ref ();
+ ref->type = REF_ARRAY;
ref->u.ar.where = where;
ref->u.ar.as = sym->as;
ref->u.ar.type = AR_FULL;
Index: gcc/fortran/gfortran.h
===================================================================
--- gcc/fortran/gfortran.h (revision 139571)
+++ gcc/fortran/gfortran.h (working copy)
@@ -151,7 +151,7 @@ bt;
/* Expression node types. */
typedef enum
{ EXPR_OP = 1, EXPR_FUNCTION, EXPR_CONSTANT, EXPR_VARIABLE,
- EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL
+ EXPR_SUBSTRING, EXPR_STRUCTURE, EXPR_ARRAY, EXPR_NULL, EXPR_COMPCALL
}
expr_t;
@@ -1003,7 +1003,7 @@ typedef struct
/* Once resolved, we use the position of pass_arg in the formal arglist of
the binding-target procedure to identify it. The first argument has
- number 0 here, the second 1, and so on. */
+ number 1 here, the second 2, and so on. */
unsigned pass_arg_num;
unsigned nopass:1; /* Whether we have NOPASS (PASS otherwise). */
@@ -1011,6 +1011,8 @@ typedef struct
}
gfc_typebound_proc;
+#define gfc_get_typebound_proc() XCNEW (gfc_typebound_proc)
+
/* Symbol nodes. These are important things. They are what the
standard refers to as "entities". The possibly multiple names that
@@ -1306,7 +1308,7 @@ gfc_array_ref;
before the component component. */
typedef enum
- { REF_ARRAY, REF_COMPONENT, REF_SUBSTRING }
+ { REF_ARRAY, REF_COMPONENT, REF_SUBSTRING, REF_PROCEDURE }
ref_type;
typedef struct gfc_ref
@@ -1331,6 +1333,12 @@ typedef struct gfc_ref
}
ss;
+ struct
+ {
+ gfc_symtree* tbp;
+ }
+ p;
+
}
u;
@@ -1447,11 +1455,13 @@ gfc_intrinsic_sym;
EXPR_FUNCTION Function call, symbol points to function's name
EXPR_CONSTANT A scalar constant: Logical, String, Real, Int or Complex
EXPR_VARIABLE An Lvalue with a root symbol and possible reference list
- which expresses structure, array and substring refs.
+ which expresses structure, array and substring refs.
EXPR_NULL The NULL pointer value (which also has a basic type).
EXPR_SUBSTRING A substring of a constant string
EXPR_STRUCTURE A structure constructor
- EXPR_ARRAY An array constructor. */
+ EXPR_ARRAY An array constructor.
+ EXPR_COMPCALL Function (or subroutine) call of a procedure pointer
+ component or type-bound procedure. */
#include <gmp.h>
#include <mpfr.h>
@@ -1526,6 +1536,12 @@ typedef struct gfc_expr
struct
{
+ gfc_actual_arglist* actual;
+ }
+ compcall;
+
+ struct
+ {
int length;
gfc_char_t *string;
}
@@ -1770,8 +1786,8 @@ gfc_forall_iterator;
typedef enum
{
EXEC_NOP = 1, EXEC_ASSIGN, EXEC_LABEL_ASSIGN, EXEC_POINTER_ASSIGN,
- EXEC_GOTO, EXEC_CALL, EXEC_ASSIGN_CALL, EXEC_RETURN, EXEC_ENTRY,
- EXEC_PAUSE, EXEC_STOP, EXEC_CONTINUE, EXEC_INIT_ASSIGN,
+ EXEC_GOTO, EXEC_CALL, EXEC_COMPCALL, EXEC_ASSIGN_CALL, EXEC_RETURN,
+ EXEC_ENTRY, EXEC_PAUSE, EXEC_STOP, EXEC_CONTINUE, EXEC_INIT_ASSIGN,
EXEC_IF, EXEC_ARITHMETIC_IF, EXEC_DO, EXEC_DO_WHILE, EXEC_SELECT,
EXEC_FORALL, EXEC_WHERE, EXEC_CYCLE, EXEC_EXIT,
EXEC_ALLOCATE, EXEC_DEALLOCATE,
@@ -2261,7 +2277,7 @@ gfc_gsymbol *gfc_get_gsymbol (const char
gfc_gsymbol *gfc_find_gsymbol (gfc_gsymbol *, const char *);
gfc_symbol* gfc_get_derived_super_type (gfc_symbol*);
-gfc_symtree* gfc_find_typebound_proc (gfc_symbol*, const char*);
+gfc_symtree* gfc_find_typebound_proc (gfc_symbol*, const char*, bool);
void copy_formal_args (gfc_symbol *dest, gfc_symbol *src);
@@ -2341,6 +2357,7 @@ gfc_expr *gfc_logical_expr (int, locus *
mpz_t *gfc_copy_shape (mpz_t *, int);
mpz_t *gfc_copy_shape_excluding (mpz_t *, int, gfc_expr *);
gfc_expr *gfc_copy_expr (gfc_expr *);
+gfc_ref* gfc_copy_ref (gfc_ref*);
gfc_try gfc_specification_expr (gfc_expr *);
@@ -2464,6 +2481,7 @@ bool gfc_check_access (gfc_access, gfc_a
symbol_attribute gfc_variable_attr (gfc_expr *, gfc_typespec *);
symbol_attribute gfc_expr_attr (gfc_expr *);
match gfc_match_rvalue (gfc_expr **);
+match gfc_match_varspec (gfc_expr*, int, bool);
int gfc_check_digit (char, int);
/* trans.c */
Index: gcc/fortran/expr.c
===================================================================
--- gcc/fortran/expr.c (revision 139571)
+++ gcc/fortran/expr.c (working copy)
@@ -119,6 +119,7 @@ gfc_free_ref_list (gfc_ref *p)
break;
case REF_COMPONENT:
+ case REF_PROCEDURE:
break;
}
@@ -181,6 +182,10 @@ free_expr0 (gfc_expr *e)
gfc_free_actual_arglist (e->value.function.actual);
break;
+ case EXPR_COMPCALL:
+ gfc_free_actual_arglist (e->value.compcall.actual);
+ break;
+
case EXPR_VARIABLE:
break;
@@ -268,8 +273,8 @@ gfc_extract_int (gfc_expr *expr, int *re
/* Recursively copy a list of reference structures. */
-static gfc_ref *
-copy_ref (gfc_ref *src)
+gfc_ref *
+gfc_copy_ref (gfc_ref *src)
{
gfc_array_ref *ar;
gfc_ref *dest;
@@ -297,9 +302,13 @@ copy_ref (gfc_ref *src)
dest->u.ss.start = gfc_copy_expr (src->u.ss.start);
dest->u.ss.end = gfc_copy_expr (src->u.ss.end);
break;
+
+ case REF_PROCEDURE:
+ dest->u.p.tbp = src->u.p.tbp;
+ break;
}
- dest->next = copy_ref (src->next);
+ dest->next = gfc_copy_ref (src->next);
return dest;
}
@@ -502,6 +511,11 @@ gfc_copy_expr (gfc_expr *p)
gfc_copy_actual_arglist (p->value.function.actual);
break;
+ case EXPR_COMPCALL:
+ q->value.compcall.actual =
+ gfc_copy_actual_arglist (p->value.compcall.actual);
+ break;
+
case EXPR_STRUCTURE:
case EXPR_ARRAY:
q->value.constructor = gfc_copy_constructor (p->value.constructor);
@@ -514,7 +528,7 @@ gfc_copy_expr (gfc_expr *p)
q->shape = gfc_copy_shape (p->shape, p->rank);
- q->ref = copy_ref (p->ref);
+ q->ref = gfc_copy_ref (p->ref);
return q;
}
@@ -1443,7 +1457,7 @@ simplify_const_ref (gfc_expr *p)
cons = p->value.constructor;
for (; cons; cons = cons->next)
{
- cons->expr->ref = copy_ref (p->ref->next);
+ cons->expr->ref = gfc_copy_ref (p->ref->next);
simplify_const_ref (cons->expr);
}
}
@@ -1470,6 +1484,9 @@ simplify_const_ref (gfc_expr *p)
gfc_free_ref_list (p->ref);
p->ref = NULL;
break;
+
+ case REF_PROCEDURE:
+ break;
}
}
@@ -1531,7 +1548,7 @@ simplify_parameter_variable (gfc_expr *p
/* Do not copy subobject refs for constant. */
if (e->expr_type != EXPR_CONSTANT && p->ref != NULL)
- e->ref = copy_ref (p->ref);
+ e->ref = gfc_copy_ref (p->ref);
t = gfc_simplify_expr (e, type);
/* Only use the simplification if it eliminated all subobject references. */
@@ -1587,6 +1604,12 @@ gfc_simplify_expr (gfc_expr *p, int type
break;
+ case EXPR_COMPCALL:
+ for (ap = p->value.compcall.actual; ap; ap = ap->next)
+ if (gfc_simplify_expr (ap->expr, type) == FAILURE)
+ return FAILURE;
+ break;
+
case EXPR_SUBSTRING:
if (simplify_ref_chain (p->ref, type) == FAILURE)
return FAILURE;
Index: gcc/fortran/module.c
===================================================================
--- gcc/fortran/module.c (revision 139571)
+++ gcc/fortran/module.c (working copy)
@@ -1693,6 +1693,20 @@ static const mstring attr_bits[] =
minit (NULL, -1)
};
+/* For binding attributes. */
+static const mstring binding_passing[] =
+{
+ minit ("PASS", 0),
+ minit ("NOPASS", 1),
+ minit (NULL, -1)
+};
+static const mstring binding_overriding[] =
+{
+ minit ("OVERRIDABLE", 0),
+ minit ("NON_OVERRIDABLE", 1),
+ minit (NULL, -1)
+};
+
/* Specialization of mio_name. */
DECL_MIO_NAME (ab_attribute)
@@ -2554,6 +2568,7 @@ static const mstring ref_types[] = {
minit ("ARRAY", REF_ARRAY),
minit ("COMPONENT", REF_COMPONENT),
minit ("SUBSTRING", REF_SUBSTRING),
+ minit ("PROCEDURE", REF_PROCEDURE),
minit (NULL, -1)
};
@@ -2584,6 +2599,10 @@ mio_ref (gfc_ref **rp)
mio_expr (&r->u.ss.end);
mio_charlen (&r->u.ss.length);
break;
+
+ case REF_PROCEDURE:
+ gcc_unreachable ();
+ break;
}
mio_rparen ();
@@ -2750,6 +2769,7 @@ static const mstring expr_types[] = {
minit ("STRUCTURE", EXPR_STRUCTURE),
minit ("ARRAY", EXPR_ARRAY),
minit ("NULL", EXPR_NULL),
+ minit ("COMPCALL", EXPR_COMPCALL),
minit (NULL, -1)
};
@@ -2956,6 +2976,11 @@ mio_expr (gfc_expr **ep)
break;
+ case EXPR_COMPCALL:
+ mio_symtree_ref (&e->symtree);
+ mio_actual_arglist (&e->value.compcall.actual);
+ break;
+
case EXPR_VARIABLE:
mio_symtree_ref (&e->symtree);
mio_ref_list (&e->ref);
@@ -3169,6 +3194,54 @@ mio_namespace_ref (gfc_namespace **nsp)
/* Save/restore the f2k_derived namespace of a derived-type symbol. */
static void
+mio_typebound_proc (gfc_typebound_proc** proc)
+{
+ int flag;
+
+ if (iomode == IO_INPUT)
+ {
+ *proc = gfc_get_typebound_proc ();
+ (*proc)->where = gfc_current_locus;
+ }
+ gcc_assert (*proc);
+
+ mio_lparen ();
+ mio_symtree_ref (&(*proc)->target);
+
+ (*proc)->access = MIO_NAME (gfc_access) ((*proc)->access, access_types);
+
+ (*proc)->nopass = mio_name ((*proc)->nopass, binding_passing);
+ (*proc)->non_overridable = mio_name ((*proc)->non_overridable,
+ binding_overriding);
+
+ if (iomode == IO_INPUT)
+ (*proc)->pass_arg = NULL;
+
+ flag = (int) (*proc)->pass_arg_num;
+ mio_integer (&flag);
+ (*proc)->pass_arg_num = (unsigned) flag;
+
+ mio_rparen ();
+}
+
+static void
+mio_typebound_symtree (gfc_symtree* st)
+{
+ if (iomode == IO_OUTPUT && !st->typebound)
+ return;
+
+ if (iomode == IO_OUTPUT)
+ {
+ mio_lparen ();
+ mio_allocated_string (st->name);
+ }
+ /* For IO_INPUT, the above is done in mio_f2k_derived. */
+
+ mio_typebound_proc (&st->typebound);
+ mio_rparen ();
+}
+
+static void
mio_finalizer (gfc_finalizer **f)
{
if (iomode == IO_OUTPUT)
@@ -3211,6 +3284,27 @@ mio_f2k_derived (gfc_namespace *f2k)
}
}
mio_rparen ();
+
+ /* Handle type-bound procedures. */
+ mio_lparen ();
+ if (iomode == IO_OUTPUT)
+ gfc_traverse_symtree (f2k->sym_root, &mio_typebound_symtree);
+ else
+ {
+ while (peek_atom () == ATOM_LPAREN)
+ {
+ gfc_symtree* st;
+
+ mio_lparen ();
+
+ require_atom (ATOM_STRING);
+ gfc_get_sym_tree (atom_string, f2k, &st);
+ gfc_free (atom_string);
+
+ mio_typebound_symtree (st);
+ }
+ }
+ mio_rparen ();
}
static void
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (revision 139571)
+++ gcc/fortran/resolve.c (working copy)
@@ -3633,6 +3633,7 @@ find_array_spec (gfc_expr *e)
break;
+ case REF_PROCEDURE:
case REF_SUBSTRING:
break;
}
@@ -3858,6 +3859,7 @@ resolve_ref (gfc_expr *expr)
return FAILURE;
break;
+ case REF_PROCEDURE:
case REF_COMPONENT:
break;
@@ -3918,6 +3920,9 @@ resolve_ref (gfc_expr *expr)
case REF_SUBSTRING:
break;
+
+ case REF_PROCEDURE:
+ break;
}
if (((ref->type == REF_COMPONENT && n_components > 1)
@@ -4281,6 +4286,163 @@ fixup_charlen (gfc_expr *e)
}
+/* Update an actual argument to include the passed-object for type-bound
+ procedures at the right position. */
+
+static gfc_actual_arglist*
+update_arglist_pass (gfc_actual_arglist* lst, gfc_expr* po, unsigned argpos)
+{
+ if (argpos == 1)
+ {
+ gfc_actual_arglist* result;
+
+ result = gfc_get_actual_arglist ();
+ result->expr = po;
+ result->next = lst;
+
+ return result;
+ }
+
+ gcc_assert (lst);
+ gcc_assert (argpos > 1);
+
+ lst->next = update_arglist_pass (lst->next, po, argpos - 1);
+ return lst;
+}
+
+
+/* Update the arglist of an EXPR_COMPCALL expression to include the
+ passed-object; the REF_PROCEDURE is already split off the ref-chain. */
+
+static gfc_try
+update_compcall_arglist (gfc_expr* e, gfc_ref* ref_proc)
+{
+ gfc_expr* po;
+ gfc_typebound_proc* tbp;
+
+ tbp = ref_proc->u.p.tbp->typebound;
+
+ po = gfc_get_expr ();
+ po->expr_type = EXPR_VARIABLE;
+ po->symtree = e->symtree;
+ po->ref = gfc_copy_ref (e->ref);
+
+ if (gfc_resolve_expr (po) == FAILURE)
+ return FAILURE;
+ if (po->rank > 0)
+ {
+ gfc_error ("Passed-object at %L must be scalar", &e->where);
+ return FAILURE;
+ }
+
+ if (tbp->nopass)
+ {
+ gfc_free_expr (po);
+ return SUCCESS;
+ }
+
+ gcc_assert (tbp->pass_arg_num > 0);
+ e->value.compcall.actual = update_arglist_pass (e->value.compcall.actual, po,
+ tbp->pass_arg_num);
+
+ return SUCCESS;
+}
+
+
+/* Resolve a call to a type-bound procedure, either function or subroutine,
+ statically from the data in an EXPR_COMPCALL expression. The adapted
+ arglist and the target-procedure symtree are returned. */
+
+static gfc_try
+resolve_typebound_static (gfc_expr* e, gfc_symtree** target,
+ gfc_actual_arglist** actual)
+{
+ gfc_ref* r;
+ gfc_ref* ref_proc;
+
+ gcc_assert (e->expr_type == EXPR_COMPCALL);
+
+ /* Find the trailing REF_PROCEDURE. */
+ for (r = e->ref; r && r->type != REF_PROCEDURE; )
+ r = r->next;
+ gcc_assert (r && r->type == REF_PROCEDURE && !r->next);
+ ref_proc = r;
+
+ /* Split it off. */
+ if (e->ref == ref_proc)
+ e->ref = NULL;
+ else
+ {
+ for (r = e->ref; r->next != ref_proc; )
+ r = r->next;
+ gcc_assert (r->next == ref_proc);
+ r->next = NULL;
+ }
+
+ /* Update the actual arglist for PASS. */
+ if (update_compcall_arglist (e, ref_proc) == FAILURE)
+ return FAILURE;
+
+ *actual = e->value.compcall.actual;
+ *target = ref_proc->u.p.tbp->typebound->target;
+
+ /* XXX: Free ref_proc. */
+ /* XXX: Other memory leaks in general... */
+
+ return SUCCESS;
+}
+
+
+/* Resolve a call to a type-bound subroutine. */
+
+static gfc_try
+resolve_typebound_call (gfc_code* c)
+{
+ gfc_actual_arglist* newactual;
+ gfc_symtree* target;
+
+ /* Transform into an ordinary EXEC_CALL for now. */
+
+ if (resolve_typebound_static (c->expr, &target, &newactual) == FAILURE)
+ return FAILURE;
+
+ c->ext.actual = newactual;
+ c->symtree = target;
+ c->op = EXEC_CALL;
+
+ /* XXX: Free. */
+ c->expr = NULL;
+
+ return resolve_call (c);
+}
+
+
+/* Resolve a component-call expression. */
+
+static gfc_try
+resolve_compcall (gfc_expr* e)
+{
+ gfc_actual_arglist* newactual;
+ gfc_symtree* target;
+
+ /* For now, we simply transform it into a EXPR_FUNCTION call with the same
+ arglist to the TBP's binding target. */
+
+ if (resolve_typebound_static (e, &target, &newactual) == FAILURE)
+ return FAILURE;
+
+ e->value.function.actual = newactual;
+ e->symtree = target;
+
+ /* XXX: Free it. */
+ e->ref = NULL;
+
+ e->expr_type = EXPR_FUNCTION;
+
+ return gfc_resolve_expr (e);
+}
+
+
/* Resolve an expression. That is, make sure that types of operands agree
with their operators, intrinsic operators are converted to function calls
for overloaded types and unresolved function references are resolved. */
@@ -4317,6 +4479,10 @@ gfc_resolve_expr (gfc_expr *e)
break;
+ case EXPR_COMPCALL:
+ t = resolve_compcall (e);
+ break;
+
case EXPR_SUBSTRING:
t = resolve_ref (e);
break;
@@ -4636,6 +4802,10 @@ resolve_deallocate_expr (gfc_expr *e)
case REF_SUBSTRING:
allocatable = 0;
break;
+
+ case REF_PROCEDURE:
+ gfc_internal_error ("resolve_deallocate_expr(): REF_PROCEDURE");
+ break;
}
}
@@ -4785,8 +4955,12 @@ resolve_allocate_expr (gfc_expr *e, gfc_
allocatable = 0;
pointer = 0;
break;
+
+ case REF_PROCEDURE:
+ gfc_internal_error ("resolve_allocate_expr(): REF_PROCEDURE");
+ break;
}
- }
+ }
}
if (allocatable == 0 && pointer == 0)
@@ -6201,7 +6375,9 @@ resolve_code (gfc_code *code, gfc_namesp
omp_workshare_flag = omp_workshare_save;
}
- t = gfc_resolve_expr (code->expr);
+ t = SUCCESS;
+ if (code->op != EXEC_COMPCALL)
+ t = gfc_resolve_expr (code->expr);
forall_flag = forall_save;
if (gfc_resolve_expr (code->expr2) == FAILURE)
@@ -6307,6 +6483,10 @@ resolve_code (gfc_code *code, gfc_namesp
resolve_call (code);
break;
+ case EXEC_COMPCALL:
+ resolve_typebound_call (code);
+ break;
+
case EXEC_SELECT:
/* Select is complicated. Also, a SELECT construct could be
a transformed computed GOTO. */
@@ -7842,7 +8022,7 @@ resolve_typebound_procedure (gfc_symtree
and look for it. */
me_arg = NULL;
- stree->typebound->pass_arg_num = 0;
+ stree->typebound->pass_arg_num = 1;
for (i = proc->formal; i; i = i->next)
{
if (!strcmp (i->sym->name, stree->typebound->pass_arg))
@@ -7866,7 +8046,7 @@ resolve_typebound_procedure (gfc_symtree
{
/* Otherwise, take the first one; there should in fact be at least
one. */
- stree->typebound->pass_arg_num = 0;
+ stree->typebound->pass_arg_num = 1;
if (!proc->formal)
{
gfc_error ("Procedure '%s' with PASS at %L must have at"
@@ -7893,7 +8073,7 @@ resolve_typebound_procedure (gfc_symtree
if (super_type)
{
gfc_symtree* overridden;
- overridden = gfc_find_typebound_proc (super_type, stree->name);
+ overridden = gfc_find_typebound_proc (super_type, stree->name, true);
if (overridden && check_typebound_override (stree, overridden) == FAILURE)
goto error;
@@ -7918,15 +8098,6 @@ resolve_typebound_procedure (gfc_symtree
goto error;
}
- /* FIXME: Remove once typebound-procedures are fully implemented. */
- {
- /* Output the error only once so we can do reasonable testing. */
- static bool tbp_error = false;
- if (!tbp_error)
- gfc_error ("Type-bound procedures are not yet implemented at %L", &where);
- tbp_error = true;
- }
-
return;
error:
@@ -7984,7 +8155,7 @@ resolve_fl_derived (gfc_symbol *sym)
{
/* If this type is an extension, see if this component has the same name
as an inherited type-bound procedure. */
- if (super_type && gfc_find_typebound_proc (super_type, c->name))
+ if (super_type && gfc_find_typebound_proc (super_type, c->name, true))
{
gfc_error ("Component '%s' of '%s' at %L has the same name as an"
" inherited type-bound procedure",
Index: gcc/fortran/st.c
===================================================================
--- gcc/fortran/st.c (revision 139571)
+++ gcc/fortran/st.c (working copy)
@@ -108,6 +108,8 @@ gfc_free_statement (gfc_code *p)
case EXEC_ARITHMETIC_IF:
break;
+ case EXEC_COMPCALL:
+ gfc_free_expr (p->expr);
case EXEC_CALL:
case EXEC_ASSIGN_CALL:
gfc_free_actual_arglist (p->ext.actual);
Index: gcc/fortran/match.c
===================================================================
--- gcc/fortran/match.c (revision 139571)
+++ gcc/fortran/match.c (working copy)
@@ -2509,6 +2509,48 @@ done:
}
+/* Match the call of a type-bound procedure, if CALL%var has already been
+ matched and var found to be a derived-type variable. */
+
+static match
+match_typebound_call (gfc_symtree* varst)
+{
+ gfc_symbol* var;
+ gfc_expr* base;
+ match m;
+
+ var = varst->n.sym;
+
+ base = gfc_get_expr ();
+ base->expr_type = EXPR_VARIABLE;
+ base->symtree = varst;
+ base->where = gfc_current_locus;
+
+ m = gfc_match_varspec (base, 0, true);
+ if (m == MATCH_NO)
+ gfc_error ("Expected component reference at %C");
+ if (m != MATCH_YES)
+ return MATCH_ERROR;
+
+ if (gfc_match_eos () != MATCH_YES)
+ {
+ gfc_error ("Junk after CALL at %C");
+ return MATCH_ERROR;
+ }
+
+ if (base->expr_type != EXPR_COMPCALL)
+ {
+ gfc_error ("Expected type-bound procedure reference at %C");
+ return MATCH_ERROR;
+ }
+
+ new_st.op = EXEC_COMPCALL;
+ new_st.expr = base;
+
+ return MATCH_YES;
+}
+
+
/* Match a CALL statement. The tricky part here are possible
alternate return specifiers. We handle these by having all
"subroutines" actually return an integer via a register that gives
@@ -2541,6 +2583,11 @@ gfc_match_call (void)
sym = st->n.sym;
+ /* If this is a variable of derived-type, it probably starts a type-bound
+ procedure call. */
+ if (sym->attr.flavor != FL_PROCEDURE && sym->ts.type == BT_DERIVED)
+ return match_typebound_call (st);
+
/* If it does not seem to be callable... */
if (!sym->attr.generic
&& !sym->attr.subroutine)
Index: gcc/fortran/dependency.c
===================================================================
--- gcc/fortran/dependency.c (revision 139571)
+++ gcc/fortran/dependency.c (working copy)
@@ -414,6 +414,7 @@ gfc_ref_needs_temporary_p (gfc_ref *ref)
types), not in characters. */
return subarray_p;
+ case REF_PROCEDURE:
case REF_COMPONENT:
break;
}
Index: gcc/fortran/primary.c
===================================================================
--- gcc/fortran/primary.c (revision 139571)
+++ gcc/fortran/primary.c (working copy)
@@ -1676,7 +1676,7 @@ cleanup:
}
-/* Used by match_varspec() to extend the reference list by one
+/* Used by gfc_match_varspec() to extend the reference list by one
element. */
static gfc_ref *
@@ -1699,15 +1699,17 @@ extend_ref (gfc_expr *primary, gfc_ref *
/* Match any additional specifications associated with the current
variable like member references or substrings. If equiv_flag is
set we only match stuff that is allowed inside an EQUIVALENCE
- statement. */
+ statement. sub_flag tells whether we expect a type-bound procedure found
+ to be a subroutine as part of CALL or a FUNCTION. */
-static match
-match_varspec (gfc_expr *primary, int equiv_flag)
+match
+gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
{
char name[GFC_MAX_SYMBOL_LEN + 1];
gfc_ref *substring, *tail;
gfc_component *component;
gfc_symbol *sym = primary->symtree->n.sym;
+ gfc_symtree *tbp;
match m;
bool unknown;
@@ -1757,6 +1759,49 @@ match_varspec (gfc_expr *primary, int eq
if (m != MATCH_YES)
return MATCH_ERROR;
+ tbp = gfc_find_typebound_proc (sym, name, false);
+ if (tbp)
+ {
+ gfc_symbol* tbp_sym;
+
+ tail = extend_ref (primary, tail);
+ tail->type = REF_PROCEDURE;
+ tail->u.p.tbp = tbp;
+ gcc_assert (!tail->next);
+
+ gcc_assert (primary->expr_type == EXPR_VARIABLE);
+ primary->expr_type = EXPR_COMPCALL;
+
+ tbp_sym = tbp->typebound->target->n.sym;
+ m = gfc_match_actual_arglist (tbp_sym->attr.subroutine,
+ &primary->value.compcall.actual);
+ if (m == MATCH_ERROR)
+ return MATCH_ERROR;
+ if (m == MATCH_NO)
+ {
+ if (sub_flag)
+ primary->value.compcall.actual = NULL;
+ else
+ {
+ gfc_error ("Expected argument list at %C");
+ return MATCH_ERROR;
+ }
+ }
+
+ if (sub_flag && !tbp_sym->attr.subroutine)
+ {
+ gfc_error ("'%s' at %C should be a SUBROUTINE", name);
+ return MATCH_ERROR;
+ }
+ if (!sub_flag && !tbp_sym->attr.function)
+ {
+ gfc_error ("'%s' at %C should be a FUNCTION", name);
+ return MATCH_ERROR;
+ }
+
+ break;
+ }
+
component = gfc_find_component (sym, name, false, false);
if (component == NULL)
return MATCH_ERROR;
@@ -1919,6 +1964,10 @@ gfc_variable_attr (gfc_expr *expr, gfc_t
case REF_SUBSTRING:
allocatable = pointer = 0;
break;
+
+ case REF_PROCEDURE:
+ gfc_internal_error ("gfc_variable_attr(): REF_PROCEDURE on variable");
+ break;
}
attr.dimension = dimension;
@@ -2387,7 +2436,7 @@ gfc_match_rvalue (gfc_expr **result)
e->expr_type = EXPR_VARIABLE;
e->symtree = symtree;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
break;
case FL_PARAMETER:
@@ -2404,7 +2453,7 @@ gfc_match_rvalue (gfc_expr **result)
}
e->symtree = symtree;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
if (sym->ts.is_c_interop || sym->ts.is_iso_c)
break;
@@ -2461,7 +2510,7 @@ gfc_match_rvalue (gfc_expr **result)
e = gfc_get_expr ();
e->expr_type = EXPR_VARIABLE;
e->symtree = symtree;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
break;
}
@@ -2488,7 +2537,7 @@ gfc_match_rvalue (gfc_expr **result)
e->symtree = symtree;
e->expr_type = EXPR_VARIABLE;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
break;
}
@@ -2584,7 +2633,7 @@ gfc_match_rvalue (gfc_expr **result)
e = gfc_get_expr ();
e->symtree = symtree;
e->expr_type = EXPR_VARIABLE;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
break;
}
@@ -2607,9 +2656,9 @@ gfc_match_rvalue (gfc_expr **result)
break;
}
- /*FIXME:??? match_varspec does set this for us: */
+ /*FIXME:??? gfc_match_varspec does set this for us: */
e->ts = sym->ts;
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
break;
}
@@ -2698,7 +2747,7 @@ gfc_match_rvalue (gfc_expr **result)
/* If our new function returns a character, array or structure
type, it might have subsequent references. */
- m = match_varspec (e, 0);
+ m = gfc_match_varspec (e, 0, false);
if (m == MATCH_NO)
m = MATCH_YES;
@@ -2882,7 +2931,7 @@ match_variable (gfc_expr **result, int e
expr->where = where;
/* Now see if we have to do more. */
- m = match_varspec (expr, equiv_flag);
+ m = gfc_match_varspec (expr, equiv_flag, false);
if (m != MATCH_YES)
{
gfc_free_expr (expr);
Index: gcc/fortran/trans-intrinsic.c
===================================================================
--- gcc/fortran/trans-intrinsic.c (revision 139571)
+++ gcc/fortran/trans-intrinsic.c (working copy)
@@ -901,7 +901,12 @@ gfc_conv_intrinsic_bound (gfc_se * se, g
case AR_FULL:
break;
}
+ break;
}
+
+ case REF_PROCEDURE:
+ gfc_internal_error ("gfc_conv_intrinsic_bound(): REF_PROCEDURE");
+ break;
}
}
}
Index: gcc/fortran/simplify.c
===================================================================
--- gcc/fortran/simplify.c (revision 139571)
+++ gcc/fortran/simplify.c (working copy)
@@ -2289,6 +2289,7 @@ simplify_bound (gfc_expr *array, gfc_exp
as = ref->u.c.component->as;
continue;
+ case REF_PROCEDURE:
case REF_SUBSTRING:
continue;
}
Index: gcc/testsuite/gfortran.dg/typebound_proc_8.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_8.f03 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_8.f03 (working copy)
@@ -35,5 +35,3 @@ CONTAINS
END MODULE testmod
! { dg-final { cleanup-modules "testmod" } }
-! FIXME: Remove not-yet-implemented error when implemented.
-! { dg-excess-errors "not yet implemented" }
Index: gcc/testsuite/gfortran.dg/typebound_call_1.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_1.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_1.f03 (revision 0)
@@ -0,0 +1,98 @@
+! { dg-do run }
+
+! Type-bound procedures
+! Check basic calls to NOPASS type-bound procedures.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE add
+ CONTAINS
+ PROCEDURE, NOPASS :: func => func_add
+ PROCEDURE, NOPASS :: sub => sub_add
+ PROCEDURE, NOPASS :: echo => echo_add
+ END TYPE add
+
+ TYPE mul
+ CONTAINS
+ PROCEDURE, NOPASS :: func => func_mul
+ PROCEDURE, NOPASS :: sub => sub_mul
+ PROCEDURE, NOPASS :: echo => echo_mul
+ END TYPE mul
+
+CONTAINS
+
+ INTEGER FUNCTION func_add (a, b)
+ IMPLICIT NONE
+ INTEGER :: a, b
+ func_add = a + b
+ END FUNCTION func_add
+
+ INTEGER FUNCTION func_mul (a, b)
+ IMPLICIT NONE
+ INTEGER :: a, b
+ func_mul = a * b
+ END FUNCTION func_mul
+
+ SUBROUTINE sub_add (a, b, c)
+ IMPLICIT NONE
+ INTEGER, INTENT(IN) :: a, b
+ INTEGER, INTENT(OUT) :: c
+ c = a + b
+ END SUBROUTINE sub_add
+
+ SUBROUTINE sub_mul (a, b, c)
+ IMPLICIT NONE
+ INTEGER, INTENT(IN) :: a, b
+ INTEGER, INTENT(OUT) :: c
+ c = a * b
+ END SUBROUTINE sub_mul
+
+ SUBROUTINE echo_add ()
+ IMPLICIT NONE
+ WRITE (*,*) "Hi from adder!"
+ END SUBROUTINE echo_add
+
+ INTEGER FUNCTION echo_mul ()
+ IMPLICIT NONE
+ echo_mul = 5
+ WRITE (*,*) "Hi from muler!"
+ END FUNCTION echo_mul
+
+ ! Do the testing here, in the same module as the type is.
+ SUBROUTINE test ()
+ IMPLICIT NONE
+
+ TYPE(add) :: adder
+ TYPE(mul) :: muler
+
+ INTEGER :: x
+
+ IF (adder%func (2, 3) /= 5 .OR. muler%func (2, 3) /= 6) THEN
+ CALL abort ()
+ END IF
+
+ CALL adder%sub (2, 3, x)
+ IF (x /= 5) THEN
+ CALL abort ()
+ END IF
+
+ CALL muler%sub (2, 3, x)
+ IF (x /= 6) THEN
+ CALL abort ()
+ END IF
+
+ ! Check procedures without arguments.
+ CALL adder%echo ()
+ WRITE (*,*) muler%echo ()
+ CALL adder%echo
+ END SUBROUTINE test
+
+END MODULE m
+
+PROGRAM main
+ USE m, ONLY: test
+ CALL test ()
+END PROGRAM main
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_call_2.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_2.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_2.f03 (revision 0)
@@ -0,0 +1,90 @@
+! { dg-do run }
+
+! Type-bound procedures
+! Check calls with passed-objects.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE add
+ INTEGER :: wrong
+ INTEGER :: val
+ CONTAINS
+ PROCEDURE, PASS :: func => func_add
+ PROCEDURE, PASS(me) :: sub => sub_add
+ END TYPE add
+
+ TYPE trueOrFalse
+ LOGICAL :: val
+ CONTAINS
+ PROCEDURE, PASS :: swap
+ END TYPE trueOrFalse
+
+CONTAINS
+
+ INTEGER FUNCTION func_add (me, x)
+ IMPLICIT NONE
+ TYPE(add) :: me
+ INTEGER :: x
+ func_add = me%val + x
+ END FUNCTION func_add
+
+ SUBROUTINE sub_add (res, me, x)
+ IMPLICIT NONE
+ INTEGER, INTENT(OUT) :: res
+ TYPE(add), INTENT(IN) :: me
+ INTEGER, INTENT(IN) :: x
+ res = me%val + x
+ END SUBROUTINE sub_add
+
+ SUBROUTINE swap (me1, me2)
+ IMPLICIT NONE
+ TYPE(trueOrFalse), INTENT(INOUT) :: me1, me2
+
+ IF (.NOT. me1%val .OR. me2%val) THEN
+ CALL abort ()
+ END IF
+
+ me1%val = .FALSE.
+ me2%val = .TRUE.
+ END SUBROUTINE swap
+
+ ! Do the testing here, in the same module as the type is.
+ SUBROUTINE test ()
+ IMPLICIT NONE
+
+ TYPE(add) :: adder
+ TYPE(trueOrFalse) :: t, f
+
+ INTEGER :: x
+
+ adder%wrong = 0
+ adder%val = 42
+ IF (adder%func (8) /= 50) THEN
+ CALL abort ()
+ END IF
+
+ CALL adder%sub (x, 8)
+ IF (x /= 50) THEN
+ CALL abort ()
+ END IF
+
+ t%val = .TRUE.
+ f%val = .FALSE.
+
+ CALL t%swap (f)
+ CALL f%swap (t)
+
+ IF (.NOT. t%val .OR. f%val) THEN
+ CALL abort ()
+ END IF
+ END SUBROUTINE test
+
+END MODULE m
+
+PROGRAM main
+ USE m, ONLY: test
+ CALL test ()
+END PROGRAM main
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_call_3.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_3.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_3.f03 (revision 0)
@@ -0,0 +1,48 @@
+! { dg-do run }
+
+! Type-bound procedures
+! Check that calls work across module-boundaries.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE trueOrFalse
+ LOGICAL :: val
+ CONTAINS
+ PROCEDURE, PASS :: swap
+ END TYPE trueOrFalse
+
+CONTAINS
+
+ SUBROUTINE swap (me1, me2)
+ IMPLICIT NONE
+ TYPE(trueOrFalse), INTENT(INOUT) :: me1, me2
+
+ IF (.NOT. me1%val .OR. me2%val) THEN
+ CALL abort ()
+ END IF
+
+ me1%val = .FALSE.
+ me2%val = .TRUE.
+ END SUBROUTINE swap
+
+END MODULE m
+
+PROGRAM main
+ USE m, ONLY: trueOrFalse
+ IMPLICIT NONE
+
+ TYPE(trueOrFalse) :: t, f
+
+ t%val = .TRUE.
+ f%val = .FALSE.
+
+ CALL t%swap (f)
+ CALL f%swap (t)
+
+ IF (.NOT. t%val .OR. f%val) THEN
+ CALL abort ()
+ END IF
+END PROGRAM main
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_call_4.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_4.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_4.f03 (revision 0)
@@ -0,0 +1,55 @@
+! { dg-do compile }
+
+! Type-bound procedures
+! Check for recognition/errors with more complicated references and some
+! error-handling in general.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE t
+ CONTAINS
+ PROCEDURE, PASS :: proc
+ PROCEDURE, NOPASS :: func
+ END TYPE t
+
+ TYPE compt
+ TYPE(t) :: myobj
+ END TYPE compt
+
+CONTAINS
+
+ SUBROUTINE proc (me)
+ IMPLICIT NONE
+ TYPE(t), INTENT(INOUT) :: me
+ END SUBROUTINE proc
+
+ INTEGER FUNCTION func ()
+ IMPLICIT NONE
+ func = 1812
+ END FUNCTION func
+
+ SUBROUTINE test ()
+ IMPLICIT NONE
+ TYPE(compt) :: arr(2)
+
+ ! These two are OK.
+ CALL arr(1)%myobj%proc ()
+ WRITE (*,*) arr(2)%myobj%func ()
+
+ ! Base-object must be scalar.
+ CALL arr(:)%myobj%proc () ! { dg-error "scalar" }
+ WRITE (*,*) arr(:)%myobj%func () ! { dg-error "scalar" }
+
+ ! Can't CALL a function or take the result of a SUBROUTINE.
+ CALL arr(1)%myobj%func () ! { dg-error "SUBROUTINE" }
+ WRITE (*,*) arr(2)%myobj%proc () ! { dg-error "FUNCTION" }
+
+ ! Error.
+ CALL arr(2)%myobj%proc () x ! { dg-error "Junk after" }
+ WRITE (*,*) arr(1)%myobj%func ! { dg-error "Expected argument list" }
+ END SUBROUTINE test
+
+END MODULE m
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_call_5.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_5.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_5.f03 (revision 0)
@@ -0,0 +1,41 @@
+! { dg-do compile }
+
+! Type-bound procedures
+! Check for correct access-checking on type-bound procedures.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE t
+ CONTAINS
+ PROCEDURE, NOPASS, PRIVATE :: priv => proc
+ PROCEDURE, NOPASS, PUBLIC :: publ => proc
+ END TYPE t
+
+CONTAINS
+
+ SUBROUTINE proc ()
+ END SUBROUTINE proc
+
+ ! This is inside the module.
+ SUBROUTINE test1 ()
+ IMPLICIT NONE
+ TYPE(t) :: obj
+
+ CALL obj%priv () ! { dg-bogus "PRIVATE" }
+ CALL obj%publ ()
+ END SUBROUTINE test1
+
+END MODULE m
+
+! This is outside the module.
+SUBROUTINE test2 ()
+ USE m
+ IMPLICIT NONE
+ TYPE(t) :: obj
+
+ CALL obj%priv () ! { dg-error "PRIVATE" }
+ CALL obj%publ ()
+END SUBROUTINE test2
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_call_6.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_call_6.f03 (revision 0)
+++ gcc/testsuite/gfortran.dg/typebound_call_6.f03 (revision 0)
@@ -0,0 +1,45 @@
+! { dg-do run }
+! { dg-output "Super(\n|\r\n|\r).*Sub" }
+
+! Type-bound procedures
+! Check for calling right overloaded procedure.
+
+MODULE m
+ IMPLICIT NONE
+
+ TYPE supert
+ CONTAINS
+ PROCEDURE, NOPASS :: proc => proc_super
+ END TYPE supert
+
+ TYPE, EXTENDS(supert) :: subt
+ CONTAINS
+ PROCEDURE, NOPASS :: proc => proc_sub
+ END TYPE subt
+
+CONTAINS
+
+ SUBROUTINE proc_super ()
+ IMPLICIT NONE
+ WRITE (*,*) "Super"
+ END SUBROUTINE proc_super
+
+ SUBROUTINE proc_sub ()
+ IMPLICIT NONE
+ WRITE (*,*) "Sub"
+ END SUBROUTINE proc_sub
+
+END MODULE m
+
+PROGRAM main
+ USE m
+ IMPLICIT NONE
+
+ TYPE(supert) :: super
+ TYPE(subt) :: sub
+
+ CALL super%proc
+ CALL sub%proc
+END PROGRAM main
+
+! { dg-final { cleanup-modules "m" } }
Index: gcc/testsuite/gfortran.dg/typebound_proc_1.f08
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_1.f08 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_1.f08 (working copy)
@@ -22,7 +22,7 @@ MODULE testmod
! Might be empty
CONTAINS
PROCEDURE proc1
- PROCEDURE, PASS(me) :: p2 => proc2 ! { dg-error "not yet implemented" }
+ PROCEDURE, PASS(me) :: p2 => proc2
END TYPE t1
TYPE t2
Index: gcc/testsuite/gfortran.dg/typebound_proc_2.f90
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_2.f90 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_2.f90 (working copy)
@@ -31,5 +31,4 @@ CONTAINS
END MODULE testmod
! { dg-final { cleanup-modules "testmod" } }
-! FIXME: Remove not-yet-implemented error when implemented.
-! { dg-excess-errors "no IMPLICIT type|not yet implemented" }
+! { dg-excess-errors "no IMPLICIT type" }
Index: gcc/testsuite/gfortran.dg/typebound_proc_5.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_5.f03 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_5.f03 (working copy)
@@ -117,5 +117,3 @@ CONTAINS
END PROGRAM main
! { dg-final { cleanup-modules "othermod testmod" } }
-! FIXME: Remove not-yet-implemented error when implemented.
-! { dg-excess-errors "not yet implemented" }
Index: gcc/testsuite/gfortran.dg/typebound_proc_6.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_6.f03 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_6.f03 (working copy)
@@ -178,5 +178,3 @@ CONTAINS
END MODULE testmod
! { dg-final { cleanup-modules "testmod" } }
-! FIXME: Remove not-yet-implemented error when implemented.
-! { dg-excess-errors "not yet implemented" }
Index: gcc/testsuite/gfortran.dg/typebound_proc_7.f03
===================================================================
--- gcc/testsuite/gfortran.dg/typebound_proc_7.f03 (revision 139571)
+++ gcc/testsuite/gfortran.dg/typebound_proc_7.f03 (working copy)
@@ -30,5 +30,3 @@ CONTAINS
END MODULE testmod
! { dg-final { cleanup-modules "testmod" } }
-! FIXME: Remove not-yet-implemented error when implemented.
-! { dg-excess-errors "not yet implemented" }