Commit e34ccb4c by Daniel Kraft Committed by Daniel Kraft

gfortran.h (gfc_get_typebound_proc): Removed as macro, now a function.

2009-04-24  Daniel Kraft  <d@domob.eu>

	* gfortran.h (gfc_get_typebound_proc): Removed as macro, now a function.
	(struct gfc_symtree): Moved `typebound' member inside union.
	(struct gfc_namespace): Add `tb_sym_root' as new symtree to sort out
	type-bound procedures there.
	(gfc_get_tbp_symtree): New procedure.
	* symbol.c (tentative_tbp_list): New global.
	(gfc_get_namespace): NULL new `tb_sym_root' member.
	(gfc_new_symtree): Removed initialization of `typebound' member.
	(gfc_undo_symbols): Process list of tentative tbp's.
	(gfc_commit_symbols): Ditto.
	(free_tb_tree): New method.
	(gfc_free_namespace): Call it.
	(gfc_get_typebound_proc): New method.
	(gfc_get_tbp_symtree): New method.
	(gfc_find_typebound_proc): Adapt to structural changes of gfc_symtree
	and gfc_namespace with regards to tbp's.
	* dump-parse-tree.c (show_typebound): Ditto.
	* primary.c (gfc_match_varspec): Ditto.  Don't reference tbp-symbol
	as it isn't a symbol any longer.
	* module.c (mio_typebound_symtree): Adapt to changes.
	(mio_typebound_proc): Ditto, create symtrees using `gfc_get_tbp_symtree'
	rather than `gfc_get_sym_tree'.
	(mio_f2k_derived): Ditto.
	* decl.c (match_procedure_in_type): Ditto.
	(gfc_match_generic): Ditto.  Don't reference tbp-symbol.
	* resolve.c (check_typebound_override): Adapt to changes.
	(resolve_typebound_generic): Ditto.
	(resolve_typebound_procedures): Ditto.
	(ensure_not_abstract_walker): Ditto.
	(ensure_not_abstract): Ditto.
	(resolve_typebound_procedure): Ditto, ignore erraneous symbols (for
	instance, through removed tentative ones).
	* gfc-internals.texi (Type-bound procedures): Document changes.

2009-04-24  Daniel Kraft  <d@domob.eu>

	* gfortran.dg/typebound_generic_1.f03: Change so that no error is
	expected on already erraneous symbol (renamed to fresh one).

From-SVN: r146733
parent b178461a
2009-04-24 Daniel Kraft <d@domob.eu>
* gfortran.h (gfc_get_typebound_proc): Removed as macro, now a function.
(struct gfc_symtree): Moved `typebound' member inside union.
(struct gfc_namespace): Add `tb_sym_root' as new symtree to sort out
type-bound procedures there.
(gfc_get_tbp_symtree): New procedure.
* symbol.c (tentative_tbp_list): New global.
(gfc_get_namespace): NULL new `tb_sym_root' member.
(gfc_new_symtree): Removed initialization of `typebound' member.
(gfc_undo_symbols): Process list of tentative tbp's.
(gfc_commit_symbols): Ditto.
(free_tb_tree): New method.
(gfc_free_namespace): Call it.
(gfc_get_typebound_proc): New method.
(gfc_get_tbp_symtree): New method.
(gfc_find_typebound_proc): Adapt to structural changes of gfc_symtree
and gfc_namespace with regards to tbp's.
* dump-parse-tree.c (show_typebound): Ditto.
* primary.c (gfc_match_varspec): Ditto. Don't reference tbp-symbol
as it isn't a symbol any longer.
* module.c (mio_typebound_symtree): Adapt to changes.
(mio_typebound_proc): Ditto, create symtrees using `gfc_get_tbp_symtree'
rather than `gfc_get_sym_tree'.
(mio_f2k_derived): Ditto.
* decl.c (match_procedure_in_type): Ditto.
(gfc_match_generic): Ditto. Don't reference tbp-symbol.
* resolve.c (check_typebound_override): Adapt to changes.
(resolve_typebound_generic): Ditto.
(resolve_typebound_procedures): Ditto.
(ensure_not_abstract_walker): Ditto.
(ensure_not_abstract): Ditto.
(resolve_typebound_procedure): Ditto, ignore erraneous symbols (for
instance, through removed tentative ones).
* gfc-internals.texi (Type-bound procedures): Document changes.
2009-04-24 Janus Weil <janus@gcc.gnu.org> 2009-04-24 Janus Weil <janus@gcc.gnu.org>
PR fortran/39861 PR fortran/39861
......
...@@ -7141,8 +7141,8 @@ match_procedure_in_type (void) ...@@ -7141,8 +7141,8 @@ match_procedure_in_type (void)
/* See if we already have a binding with this name in the symtree which would /* See if we already have a binding with this name in the symtree which would
be an error. If a GENERIC already targetted this binding, it may be be an error. If a GENERIC already targetted this binding, it may be
already there but then typebound is still NULL. */ already there but then typebound is still NULL. */
stree = gfc_find_symtree (ns->sym_root, name); stree = gfc_find_symtree (ns->tb_sym_root, name);
if (stree && stree->typebound) if (stree && stree->n.tb)
{ {
gfc_error ("There's already a procedure with binding name '%s' for the" gfc_error ("There's already a procedure with binding name '%s' for the"
" derived type '%s' at %C", name, block->name); " derived type '%s' at %C", name, block->name);
...@@ -7150,12 +7150,17 @@ match_procedure_in_type (void) ...@@ -7150,12 +7150,17 @@ match_procedure_in_type (void)
} }
/* Insert it and set attributes. */ /* Insert it and set attributes. */
if (gfc_get_sym_tree (name, ns, &stree))
return MATCH_ERROR; if (!stree)
{
stree = gfc_new_symtree (&ns->tb_sym_root, name);
gcc_assert (stree);
}
stree->n.tb = tb;
if (gfc_get_sym_tree (target, gfc_current_ns, &tb->u.specific)) if (gfc_get_sym_tree (target, gfc_current_ns, &tb->u.specific))
return MATCH_ERROR; return MATCH_ERROR;
gfc_set_sym_referenced (tb->u.specific->n.sym); gfc_set_sym_referenced (tb->u.specific->n.sym);
stree->typebound = tb;
return MATCH_YES; return MATCH_YES;
} }
...@@ -7210,10 +7215,13 @@ gfc_match_generic (void) ...@@ -7210,10 +7215,13 @@ gfc_match_generic (void)
/* If there's already something with this name, check that it is another /* If there's already something with this name, check that it is another
GENERIC and then extend that rather than build a new node. */ GENERIC and then extend that rather than build a new node. */
st = gfc_find_symtree (ns->sym_root, name); st = gfc_find_symtree (ns->tb_sym_root, name);
if (st) if (st)
{ {
if (!st->typebound || !st->typebound->is_generic) gcc_assert (st->n.tb);
tb = st->n.tb;
if (!tb->is_generic)
{ {
gfc_error ("There's already a non-generic procedure with binding name" gfc_error ("There's already a non-generic procedure with binding name"
" '%s' for the derived type '%s' at %C", " '%s' for the derived type '%s' at %C",
...@@ -7221,7 +7229,6 @@ gfc_match_generic (void) ...@@ -7221,7 +7229,6 @@ gfc_match_generic (void)
goto error; goto error;
} }
tb = st->typebound;
if (tb->access != tbattr.access) if (tb->access != tbattr.access)
{ {
gfc_error ("Binding at %C must have the same access as already" gfc_error ("Binding at %C must have the same access as already"
...@@ -7231,10 +7238,10 @@ gfc_match_generic (void) ...@@ -7231,10 +7238,10 @@ gfc_match_generic (void)
} }
else else
{ {
if (gfc_get_sym_tree (name, ns, &st)) st = gfc_new_symtree (&ns->tb_sym_root, name);
return MATCH_ERROR; gcc_assert (st);
st->typebound = tb = gfc_get_typebound_proc (); st->n.tb = tb = gfc_get_typebound_proc ();
tb->where = gfc_current_locus; tb->where = gfc_current_locus;
tb->access = tbattr.access; tb->access = tbattr.access;
tb->is_generic = 1; tb->is_generic = 1;
...@@ -7256,20 +7263,17 @@ gfc_match_generic (void) ...@@ -7256,20 +7263,17 @@ gfc_match_generic (void)
goto error; goto error;
} }
if (gfc_get_sym_tree (name, ns, &target_st)) target_st = gfc_get_tbp_symtree (&ns->tb_sym_root, name);
goto error;
/* See if this is a duplicate specification. */ /* See if this is a duplicate specification. */
for (target = tb->u.generic; target; target = target->next) for (target = tb->u.generic; target; target = target->next)
if (target_st == target->specific_st) if (target_st == target->specific_st)
{ {
gfc_error ("'%s' already defined as specific binding for the" gfc_error ("'%s' already defined as specific binding for the"
" generic '%s' at %C", name, st->n.sym->name); " generic '%s' at %C", name, st->name);
goto error; goto error;
} }
gfc_set_sym_referenced (target_st->n.sym);
target = gfc_get_tbp_generic (); target = gfc_get_tbp_generic ();
target->specific_st = target_st; target->specific_st = target_st;
target->specific = NULL; target->specific = NULL;
......
...@@ -671,40 +671,40 @@ show_components (gfc_symbol *sym) ...@@ -671,40 +671,40 @@ show_components (gfc_symbol *sym)
static void static void
show_typebound (gfc_symtree* st) show_typebound (gfc_symtree* st)
{ {
if (!st->typebound) if (!st->n.tb)
return; return;
show_indent (); show_indent ();
if (st->typebound->is_generic) if (st->n.tb->is_generic)
fputs ("GENERIC", dumpfile); fputs ("GENERIC", dumpfile);
else else
{ {
fputs ("PROCEDURE, ", dumpfile); fputs ("PROCEDURE, ", dumpfile);
if (st->typebound->nopass) if (st->n.tb->nopass)
fputs ("NOPASS", dumpfile); fputs ("NOPASS", dumpfile);
else else
{ {
if (st->typebound->pass_arg) if (st->n.tb->pass_arg)
fprintf (dumpfile, "PASS(%s)", st->typebound->pass_arg); fprintf (dumpfile, "PASS(%s)", st->n.tb->pass_arg);
else else
fputs ("PASS", dumpfile); fputs ("PASS", dumpfile);
} }
if (st->typebound->non_overridable) if (st->n.tb->non_overridable)
fputs (", NON_OVERRIDABLE", dumpfile); fputs (", NON_OVERRIDABLE", dumpfile);
} }
if (st->typebound->access == ACCESS_PUBLIC) if (st->n.tb->access == ACCESS_PUBLIC)
fputs (", PUBLIC", dumpfile); fputs (", PUBLIC", dumpfile);
else else
fputs (", PRIVATE", dumpfile); fputs (", PRIVATE", dumpfile);
fprintf (dumpfile, " :: %s => ", st->n.sym->name); fprintf (dumpfile, " :: %s => ", st->n.sym->name);
if (st->typebound->is_generic) if (st->n.tb->is_generic)
{ {
gfc_tbp_generic* g; gfc_tbp_generic* g;
for (g = st->typebound->u.generic; g; g = g->next) for (g = st->n.tb->u.generic; g; g = g->next)
{ {
fputs (g->specific_st->name, dumpfile); fputs (g->specific_st->name, dumpfile);
if (g->next) if (g->next)
...@@ -712,7 +712,7 @@ show_typebound (gfc_symtree* st) ...@@ -712,7 +712,7 @@ show_typebound (gfc_symtree* st)
} }
} }
else else
fputs (st->typebound->u.specific->n.sym->name, dumpfile); fputs (st->n.tb->u.specific->n.sym->name, dumpfile);
} }
static void static void
......
...@@ -577,15 +577,14 @@ substring reference as described in the subsection above. ...@@ -577,15 +577,14 @@ substring reference as described in the subsection above.
@node Type-bound Procedures @node Type-bound Procedures
@section Type-bound Procedures @section Type-bound Procedures
Type-bound procedures are stored in the @code{sym_root} of the namespace Type-bound procedures are stored in the @code{tb_sym_root} of the namespace
@code{f2k_derived} associated with the derived-type symbol as @code{gfc_symtree} @code{f2k_derived} associated with the derived-type symbol as @code{gfc_symtree}
nodes. The name and symbol of these symtrees corresponds to the binding-name nodes. The name and symbol of these symtrees corresponds to the binding-name
of the procedure, i.e. the name that is used to call it from the context of an of the procedure, i.e. the name that is used to call it from the context of an
object of the derived-type. object of the derived-type.
In addition, those and only those symtrees representing a type-bound procedure In addition, this type of symtrees stores in @code{n.tb} a struct of type
have their @code{typebound} member set; @code{typebound} points to a struct of @code{gfc_typebound_proc} containing the additional data needed: The
type @code{gfc_typebound_proc} containing the additional data needed: The
binding attributes (like @code{PASS} and @code{NOPASS}, @code{NON_OVERRIDABLE} binding attributes (like @code{PASS} and @code{NOPASS}, @code{NON_OVERRIDABLE}
or the access-specifier), the binding's target(s) and, if the current binding or the access-specifier), the binding's target(s) and, if the current binding
overrides or extends an inherited binding of the same name, @code{overridden} overrides or extends an inherited binding of the same name, @code{overridden}
......
...@@ -1049,8 +1049,6 @@ typedef struct gfc_typebound_proc ...@@ -1049,8 +1049,6 @@ typedef struct gfc_typebound_proc
} }
gfc_typebound_proc; gfc_typebound_proc;
#define gfc_get_typebound_proc() XCNEW (gfc_typebound_proc)
/* Symbol nodes. These are important things. They are what the /* Symbol nodes. These are important things. They are what the
standard refers to as "entities". The possibly multiple names that standard refers to as "entities". The possibly multiple names that
...@@ -1215,11 +1213,9 @@ typedef struct gfc_symtree ...@@ -1215,11 +1213,9 @@ typedef struct gfc_symtree
gfc_symbol *sym; /* Symbol associated with this node */ gfc_symbol *sym; /* Symbol associated with this node */
gfc_user_op *uop; gfc_user_op *uop;
gfc_common_head *common; gfc_common_head *common;
gfc_typebound_proc *tb;
} }
n; n;
/* Data for type-bound procedures; NULL if no type-bound procedure. */
gfc_typebound_proc* typebound;
} }
gfc_symtree; gfc_symtree;
...@@ -1248,6 +1244,9 @@ typedef struct gfc_namespace ...@@ -1248,6 +1244,9 @@ typedef struct gfc_namespace
gfc_symtree *uop_root; gfc_symtree *uop_root;
/* Tree containing all the common blocks. */ /* Tree containing all the common blocks. */
gfc_symtree *common_root; gfc_symtree *common_root;
/* Tree containing type-bound procedures. */
gfc_symtree *tb_sym_root;
/* Linked list of finalizer procedures. */ /* Linked list of finalizer procedures. */
struct gfc_finalizer *finalizers; struct gfc_finalizer *finalizers;
...@@ -2370,8 +2369,10 @@ void gfc_free_dt_list (void); ...@@ -2370,8 +2369,10 @@ void gfc_free_dt_list (void);
gfc_gsymbol *gfc_get_gsymbol (const char *); 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_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_symtree* gfc_find_typebound_proc (gfc_symbol*, gfc_try*, const char*, bool); gfc_symtree* gfc_find_typebound_proc (gfc_symbol*, gfc_try*, const char*, bool);
gfc_symtree* gfc_get_tbp_symtree (gfc_symtree**, const char*);
void gfc_copy_formal_args (gfc_symbol *, gfc_symbol *); void gfc_copy_formal_args (gfc_symbol *, gfc_symbol *);
void gfc_copy_formal_args_intr (gfc_symbol *, gfc_intrinsic_sym *); void gfc_copy_formal_args_intr (gfc_symbol *, gfc_intrinsic_sym *);
......
...@@ -3251,12 +3251,14 @@ mio_typebound_proc (gfc_typebound_proc** proc) ...@@ -3251,12 +3251,14 @@ mio_typebound_proc (gfc_typebound_proc** proc)
(*proc)->u.generic = NULL; (*proc)->u.generic = NULL;
while (peek_atom () != ATOM_RPAREN) while (peek_atom () != ATOM_RPAREN)
{ {
gfc_symtree** sym_root;
g = gfc_get_tbp_generic (); g = gfc_get_tbp_generic ();
g->specific = NULL; g->specific = NULL;
require_atom (ATOM_STRING); require_atom (ATOM_STRING);
gfc_get_sym_tree (atom_string, current_f2k_derived, sym_root = &current_f2k_derived->tb_sym_root;
&g->specific_st); g->specific_st = gfc_get_tbp_symtree (sym_root, atom_string);
gfc_free (atom_string); gfc_free (atom_string);
g->next = (*proc)->u.generic; g->next = (*proc)->u.generic;
...@@ -3275,7 +3277,7 @@ mio_typebound_proc (gfc_typebound_proc** proc) ...@@ -3275,7 +3277,7 @@ mio_typebound_proc (gfc_typebound_proc** proc)
static void static void
mio_typebound_symtree (gfc_symtree* st) mio_typebound_symtree (gfc_symtree* st)
{ {
if (iomode == IO_OUTPUT && !st->typebound) if (iomode == IO_OUTPUT && !st->n.tb)
return; return;
if (iomode == IO_OUTPUT) if (iomode == IO_OUTPUT)
...@@ -3285,7 +3287,7 @@ mio_typebound_symtree (gfc_symtree* st) ...@@ -3285,7 +3287,7 @@ mio_typebound_symtree (gfc_symtree* st)
} }
/* For IO_INPUT, the above is done in mio_f2k_derived. */ /* For IO_INPUT, the above is done in mio_f2k_derived. */
mio_typebound_proc (&st->typebound); mio_typebound_proc (&st->n.tb);
mio_rparen (); mio_rparen ();
} }
...@@ -3338,7 +3340,7 @@ mio_f2k_derived (gfc_namespace *f2k) ...@@ -3338,7 +3340,7 @@ mio_f2k_derived (gfc_namespace *f2k)
/* Handle type-bound procedures. */ /* Handle type-bound procedures. */
mio_lparen (); mio_lparen ();
if (iomode == IO_OUTPUT) if (iomode == IO_OUTPUT)
gfc_traverse_symtree (f2k->sym_root, &mio_typebound_symtree); gfc_traverse_symtree (f2k->tb_sym_root, &mio_typebound_symtree);
else else
{ {
while (peek_atom () == ATOM_LPAREN) while (peek_atom () == ATOM_LPAREN)
...@@ -3348,7 +3350,7 @@ mio_f2k_derived (gfc_namespace *f2k) ...@@ -3348,7 +3350,7 @@ mio_f2k_derived (gfc_namespace *f2k)
mio_lparen (); mio_lparen ();
require_atom (ATOM_STRING); require_atom (ATOM_STRING);
gfc_get_sym_tree (atom_string, f2k, &st); st = gfc_get_tbp_symtree (&f2k->tb_sym_root, atom_string);
gfc_free (atom_string); gfc_free (atom_string);
mio_typebound_symtree (st); mio_typebound_symtree (st);
......
...@@ -1784,19 +1784,19 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag) ...@@ -1784,19 +1784,19 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
gcc_assert (!tail || !tail->next); gcc_assert (!tail || !tail->next);
gcc_assert (primary->expr_type == EXPR_VARIABLE); gcc_assert (primary->expr_type == EXPR_VARIABLE);
if (tbp->typebound->is_generic) if (tbp->n.tb->is_generic)
tbp_sym = NULL; tbp_sym = NULL;
else else
tbp_sym = tbp->typebound->u.specific->n.sym; tbp_sym = tbp->n.tb->u.specific->n.sym;
primary->expr_type = EXPR_COMPCALL; primary->expr_type = EXPR_COMPCALL;
primary->value.compcall.tbp = tbp->typebound; primary->value.compcall.tbp = tbp->n.tb;
primary->value.compcall.name = tbp->name; primary->value.compcall.name = tbp->name;
gcc_assert (primary->symtree->n.sym->attr.referenced); gcc_assert (primary->symtree->n.sym->attr.referenced);
if (tbp_sym) if (tbp_sym)
primary->ts = tbp_sym->ts; primary->ts = tbp_sym->ts;
m = gfc_match_actual_arglist (tbp->typebound->subroutine, m = gfc_match_actual_arglist (tbp->n.tb->subroutine,
&primary->value.compcall.actual); &primary->value.compcall.actual);
if (m == MATCH_ERROR) if (m == MATCH_ERROR)
return MATCH_ERROR; return MATCH_ERROR;
...@@ -1811,8 +1811,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag) ...@@ -1811,8 +1811,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
} }
} }
gfc_set_sym_referenced (tbp->n.sym);
break; break;
} }
......
...@@ -101,6 +101,18 @@ static gfc_symbol *changed_syms = NULL; ...@@ -101,6 +101,18 @@ static gfc_symbol *changed_syms = NULL;
gfc_dt_list *gfc_derived_types; gfc_dt_list *gfc_derived_types;
/* List of tentative typebound-procedures. */
typedef struct tentative_tbp
{
gfc_typebound_proc *proc;
struct tentative_tbp *next;
}
tentative_tbp;
static tentative_tbp *tentative_tbp_list = NULL;
/*********** IMPLICIT NONE and IMPLICIT statement handlers ***********/ /*********** IMPLICIT NONE and IMPLICIT statement handlers ***********/
/* The following static variable indicates whether a particular element has /* The following static variable indicates whether a particular element has
...@@ -2191,6 +2203,7 @@ gfc_get_namespace (gfc_namespace *parent, int parent_types) ...@@ -2191,6 +2203,7 @@ gfc_get_namespace (gfc_namespace *parent, int parent_types)
ns = XCNEW (gfc_namespace); ns = XCNEW (gfc_namespace);
ns->sym_root = NULL; ns->sym_root = NULL;
ns->uop_root = NULL; ns->uop_root = NULL;
ns->tb_sym_root = NULL;
ns->finalizers = NULL; ns->finalizers = NULL;
ns->default_access = ACCESS_UNKNOWN; ns->default_access = ACCESS_UNKNOWN;
ns->parent = parent; ns->parent = parent;
...@@ -2258,7 +2271,6 @@ gfc_new_symtree (gfc_symtree **root, const char *name) ...@@ -2258,7 +2271,6 @@ gfc_new_symtree (gfc_symtree **root, const char *name)
st = XCNEW (gfc_symtree); st = XCNEW (gfc_symtree);
st->name = gfc_get_string (name); st->name = gfc_get_string (name);
st->typebound = NULL;
gfc_insert_bbt (root, st, compare_symtree); gfc_insert_bbt (root, st, compare_symtree);
return st; return st;
...@@ -2691,6 +2703,7 @@ void ...@@ -2691,6 +2703,7 @@ void
gfc_undo_symbols (void) gfc_undo_symbols (void)
{ {
gfc_symbol *p, *q, *old; gfc_symbol *p, *q, *old;
tentative_tbp *tbp, *tbq;
for (p = changed_syms; p; p = q) for (p = changed_syms; p; p = q)
{ {
...@@ -2789,6 +2802,14 @@ gfc_undo_symbols (void) ...@@ -2789,6 +2802,14 @@ gfc_undo_symbols (void)
} }
changed_syms = NULL; changed_syms = NULL;
for (tbp = tentative_tbp_list; tbp; tbp = tbq)
{
tbq = tbp->next;
/* Procedure is already marked `error' by default. */
gfc_free (tbp);
}
tentative_tbp_list = NULL;
} }
...@@ -2826,6 +2847,7 @@ void ...@@ -2826,6 +2847,7 @@ void
gfc_commit_symbols (void) gfc_commit_symbols (void)
{ {
gfc_symbol *p, *q; gfc_symbol *p, *q;
tentative_tbp *tbp, *tbq;
for (p = changed_syms; p; p = q) for (p = changed_syms; p; p = q)
{ {
...@@ -2836,6 +2858,14 @@ gfc_commit_symbols (void) ...@@ -2836,6 +2858,14 @@ gfc_commit_symbols (void)
free_old_symbol (p); free_old_symbol (p);
} }
changed_syms = NULL; changed_syms = NULL;
for (tbp = tentative_tbp_list; tbp; tbp = tbq)
{
tbq = tbp->next;
tbp->proc->error = 0;
gfc_free (tbp);
}
tentative_tbp_list = NULL;
} }
...@@ -2867,6 +2897,24 @@ gfc_commit_symbol (gfc_symbol *sym) ...@@ -2867,6 +2897,24 @@ gfc_commit_symbol (gfc_symbol *sym)
} }
/* Recursively free trees containing type-bound procedures. */
static void
free_tb_tree (gfc_symtree *t)
{
if (t == NULL)
return;
free_tb_tree (t->left);
free_tb_tree (t->right);
/* TODO: Free type-bound procedure structs themselves; probably needs some
sort of ref-counting mechanism. */
gfc_free (t);
}
/* Recursive function that deletes an entire tree and all the common /* Recursive function that deletes an entire tree and all the common
head structures it points to. */ head structures it points to. */
...@@ -3055,6 +3103,7 @@ gfc_free_namespace (gfc_namespace *ns) ...@@ -3055,6 +3103,7 @@ gfc_free_namespace (gfc_namespace *ns)
free_sym_tree (ns->sym_root); free_sym_tree (ns->sym_root);
free_uop_tree (ns->uop_root); free_uop_tree (ns->uop_root);
free_common_tree (ns->common_root); free_common_tree (ns->common_root);
free_tb_tree (ns->tb_sym_root);
gfc_free_finalizer_list (ns->finalizers); gfc_free_finalizer_list (ns->finalizers);
gfc_free_charlen (ns->cl_list, NULL); gfc_free_charlen (ns->cl_list, NULL);
free_st_labels (ns->st_labels); free_st_labels (ns->st_labels);
...@@ -4342,6 +4391,27 @@ gfc_check_symbol_typed (gfc_symbol* sym, gfc_namespace* ns, ...@@ -4342,6 +4391,27 @@ gfc_check_symbol_typed (gfc_symbol* sym, gfc_namespace* ns,
} }
/* Construct a typebound-procedure structure. Those are stored in a tentative
list and marked `error' until symbols are committed. */
gfc_typebound_proc*
gfc_get_typebound_proc (void)
{
gfc_typebound_proc *result;
tentative_tbp *list_node;
result = XCNEW (gfc_typebound_proc);
result->error = 1;
list_node = XCNEW (tentative_tbp);
list_node->next = tentative_tbp_list;
list_node->proc = result;
tentative_tbp_list = list_node;
return result;
}
/* Get the super-type of a given derived type. */ /* Get the super-type of a given derived type. */
gfc_symbol* gfc_symbol*
...@@ -4373,15 +4443,15 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t, ...@@ -4373,15 +4443,15 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t,
/* Try to find it in the current type's namespace. */ /* Try to find it in the current type's namespace. */
gcc_assert (derived->f2k_derived); gcc_assert (derived->f2k_derived);
res = gfc_find_symtree (derived->f2k_derived->sym_root, name); res = gfc_find_symtree (derived->f2k_derived->tb_sym_root, name);
if (res && res->typebound) if (res && res->n.tb)
{ {
/* We found one. */ /* We found one. */
if (t) if (t)
*t = SUCCESS; *t = SUCCESS;
if (!noaccess && derived->attr.use_assoc if (!noaccess && derived->attr.use_assoc
&& res->typebound->access == ACCESS_PRIVATE) && res->n.tb->access == ACCESS_PRIVATE)
{ {
gfc_error ("'%s' of '%s' is PRIVATE at %C", name, derived->name); gfc_error ("'%s' of '%s' is PRIVATE at %C", name, derived->name);
if (t) if (t)
...@@ -4403,3 +4473,24 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t, ...@@ -4403,3 +4473,24 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t,
/* Nothing found. */ /* Nothing found. */
return NULL; return NULL;
} }
/* Get a typebound-procedure symtree or create and insert it if not yet
present. This is like a very simplified version of gfc_get_sym_tree for
tbp-symtrees rather than regular ones. */
gfc_symtree*
gfc_get_tbp_symtree (gfc_symtree **root, const char *name)
{
gfc_symtree *result;
result = gfc_find_symtree (*root, name);
if (!result)
{
result = gfc_new_symtree (root, name);
gcc_assert (result);
result->n.tb = NULL;
}
return result;
}
2009-04-24 Daniel Kraft <d@domob.eu>
* gfortran.dg/typebound_generic_1.f03: Change so that no error is
expected on already erraneous symbol (renamed to fresh one).
2009-04-24 Paolo Bonzini <bonzini@gnu.org> 2009-04-24 Paolo Bonzini <bonzini@gnu.org>
PR middle-end/39867 PR middle-end/39867
......
...@@ -28,8 +28,8 @@ MODULE m ...@@ -28,8 +28,8 @@ MODULE m
PROCEDURE, NOPASS :: gen1 => intf1 ! { dg-error "already a procedure" } PROCEDURE, NOPASS :: gen1 => intf1 ! { dg-error "already a procedure" }
GENERIC :: gen3 => ! { dg-error "specific binding" } GENERIC :: gen3 => ! { dg-error "specific binding" }
GENERIC :: gen4 => p1 x ! { dg-error "Junk after" } GENERIC :: gen4 => p1 x ! { dg-error "Junk after" }
GENERIC :: gen4 => p_notthere ! { dg-error "Undefined specific binding" } GENERIC :: gen5 => p_notthere ! { dg-error "Undefined specific binding" }
GENERIC :: gen5 => gen1 ! { dg-error "must target a specific binding" } GENERIC :: gen6 => gen1 ! { dg-error "must target a specific binding" }
GENERIC :: gensubr => p2 ! { dg-error "mixed FUNCTION/SUBROUTINE" } GENERIC :: gensubr => p2 ! { dg-error "mixed FUNCTION/SUBROUTINE" }
GENERIC :: gensubr => subr GENERIC :: gensubr => subr
......
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