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>
PR fortran/39861
......
......@@ -7141,8 +7141,8 @@ match_procedure_in_type (void)
/* 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
already there but then typebound is still NULL. */
stree = gfc_find_symtree (ns->sym_root, name);
if (stree && stree->typebound)
stree = gfc_find_symtree (ns->tb_sym_root, name);
if (stree && stree->n.tb)
{
gfc_error ("There's already a procedure with binding name '%s' for the"
" derived type '%s' at %C", name, block->name);
......@@ -7150,12 +7150,17 @@ match_procedure_in_type (void)
}
/* 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))
return MATCH_ERROR;
gfc_set_sym_referenced (tb->u.specific->n.sym);
stree->typebound = tb;
return MATCH_YES;
}
......@@ -7210,10 +7215,13 @@ gfc_match_generic (void)
/* If there's already something with this name, check that it is another
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->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"
" '%s' for the derived type '%s' at %C",
......@@ -7221,7 +7229,6 @@ gfc_match_generic (void)
goto error;
}
tb = st->typebound;
if (tb->access != tbattr.access)
{
gfc_error ("Binding at %C must have the same access as already"
......@@ -7231,10 +7238,10 @@ gfc_match_generic (void)
}
else
{
if (gfc_get_sym_tree (name, ns, &st))
return MATCH_ERROR;
st = gfc_new_symtree (&ns->tb_sym_root, name);
gcc_assert (st);
st->typebound = tb = gfc_get_typebound_proc ();
st->n.tb = tb = gfc_get_typebound_proc ();
tb->where = gfc_current_locus;
tb->access = tbattr.access;
tb->is_generic = 1;
......@@ -7256,20 +7263,17 @@ gfc_match_generic (void)
goto error;
}
if (gfc_get_sym_tree (name, ns, &target_st))
goto error;
target_st = gfc_get_tbp_symtree (&ns->tb_sym_root, name);
/* See if this is a duplicate specification. */
for (target = tb->u.generic; target; target = target->next)
if (target_st == target->specific_st)
{
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;
}
gfc_set_sym_referenced (target_st->n.sym);
target = gfc_get_tbp_generic ();
target->specific_st = target_st;
target->specific = NULL;
......
......@@ -671,40 +671,40 @@ show_components (gfc_symbol *sym)
static void
show_typebound (gfc_symtree* st)
{
if (!st->typebound)
if (!st->n.tb)
return;
show_indent ();
if (st->typebound->is_generic)
if (st->n.tb->is_generic)
fputs ("GENERIC", dumpfile);
else
{
fputs ("PROCEDURE, ", dumpfile);
if (st->typebound->nopass)
if (st->n.tb->nopass)
fputs ("NOPASS", dumpfile);
else
{
if (st->typebound->pass_arg)
fprintf (dumpfile, "PASS(%s)", st->typebound->pass_arg);
if (st->n.tb->pass_arg)
fprintf (dumpfile, "PASS(%s)", st->n.tb->pass_arg);
else
fputs ("PASS", dumpfile);
}
if (st->typebound->non_overridable)
if (st->n.tb->non_overridable)
fputs (", NON_OVERRIDABLE", dumpfile);
}
if (st->typebound->access == ACCESS_PUBLIC)
if (st->n.tb->access == ACCESS_PUBLIC)
fputs (", PUBLIC", dumpfile);
else
fputs (", PRIVATE", dumpfile);
fprintf (dumpfile, " :: %s => ", st->n.sym->name);
if (st->typebound->is_generic)
if (st->n.tb->is_generic)
{
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);
if (g->next)
......@@ -712,7 +712,7 @@ show_typebound (gfc_symtree* st)
}
}
else
fputs (st->typebound->u.specific->n.sym->name, dumpfile);
fputs (st->n.tb->u.specific->n.sym->name, dumpfile);
}
static void
......
......@@ -577,15 +577,14 @@ substring reference as described in the subsection above.
@node 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}
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
object of the derived-type.
In addition, those and only those symtrees representing a type-bound procedure
have their @code{typebound} member set; @code{typebound} points to a struct of
type @code{gfc_typebound_proc} containing the additional data needed: The
In addition, this type of symtrees stores in @code{n.tb} a struct of type
@code{gfc_typebound_proc} containing the additional data needed: The
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
overrides or extends an inherited binding of the same name, @code{overridden}
......
......@@ -1049,8 +1049,6 @@ typedef struct 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
standard refers to as "entities". The possibly multiple names that
......@@ -1215,11 +1213,9 @@ typedef struct gfc_symtree
gfc_symbol *sym; /* Symbol associated with this node */
gfc_user_op *uop;
gfc_common_head *common;
gfc_typebound_proc *tb;
}
n;
/* Data for type-bound procedures; NULL if no type-bound procedure. */
gfc_typebound_proc* typebound;
}
gfc_symtree;
......@@ -1248,6 +1244,9 @@ typedef struct gfc_namespace
gfc_symtree *uop_root;
/* Tree containing all the common blocks. */
gfc_symtree *common_root;
/* Tree containing type-bound procedures. */
gfc_symtree *tb_sym_root;
/* Linked list of finalizer procedures. */
struct gfc_finalizer *finalizers;
......@@ -2370,8 +2369,10 @@ void gfc_free_dt_list (void);
gfc_gsymbol *gfc_get_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_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_intr (gfc_symbol *, gfc_intrinsic_sym *);
......
......@@ -3251,12 +3251,14 @@ mio_typebound_proc (gfc_typebound_proc** proc)
(*proc)->u.generic = NULL;
while (peek_atom () != ATOM_RPAREN)
{
gfc_symtree** sym_root;
g = gfc_get_tbp_generic ();
g->specific = NULL;
require_atom (ATOM_STRING);
gfc_get_sym_tree (atom_string, current_f2k_derived,
&g->specific_st);
sym_root = &current_f2k_derived->tb_sym_root;
g->specific_st = gfc_get_tbp_symtree (sym_root, atom_string);
gfc_free (atom_string);
g->next = (*proc)->u.generic;
......@@ -3275,7 +3277,7 @@ mio_typebound_proc (gfc_typebound_proc** proc)
static void
mio_typebound_symtree (gfc_symtree* st)
{
if (iomode == IO_OUTPUT && !st->typebound)
if (iomode == IO_OUTPUT && !st->n.tb)
return;
if (iomode == IO_OUTPUT)
......@@ -3285,7 +3287,7 @@ mio_typebound_symtree (gfc_symtree* st)
}
/* For IO_INPUT, the above is done in mio_f2k_derived. */
mio_typebound_proc (&st->typebound);
mio_typebound_proc (&st->n.tb);
mio_rparen ();
}
......@@ -3338,7 +3340,7 @@ mio_f2k_derived (gfc_namespace *f2k)
/* Handle type-bound procedures. */
mio_lparen ();
if (iomode == IO_OUTPUT)
gfc_traverse_symtree (f2k->sym_root, &mio_typebound_symtree);
gfc_traverse_symtree (f2k->tb_sym_root, &mio_typebound_symtree);
else
{
while (peek_atom () == ATOM_LPAREN)
......@@ -3348,7 +3350,7 @@ mio_f2k_derived (gfc_namespace *f2k)
mio_lparen ();
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);
mio_typebound_symtree (st);
......
......@@ -1784,19 +1784,19 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
gcc_assert (!tail || !tail->next);
gcc_assert (primary->expr_type == EXPR_VARIABLE);
if (tbp->typebound->is_generic)
if (tbp->n.tb->is_generic)
tbp_sym = NULL;
else
tbp_sym = tbp->typebound->u.specific->n.sym;
tbp_sym = tbp->n.tb->u.specific->n.sym;
primary->expr_type = EXPR_COMPCALL;
primary->value.compcall.tbp = tbp->typebound;
primary->value.compcall.tbp = tbp->n.tb;
primary->value.compcall.name = tbp->name;
gcc_assert (primary->symtree->n.sym->attr.referenced);
if (tbp_sym)
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);
if (m == MATCH_ERROR)
return MATCH_ERROR;
......@@ -1811,8 +1811,6 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag)
}
}
gfc_set_sym_referenced (tbp->n.sym);
break;
}
......
......@@ -101,6 +101,18 @@ static gfc_symbol *changed_syms = NULL;
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 ***********/
/* The following static variable indicates whether a particular element has
......@@ -2191,6 +2203,7 @@ gfc_get_namespace (gfc_namespace *parent, int parent_types)
ns = XCNEW (gfc_namespace);
ns->sym_root = NULL;
ns->uop_root = NULL;
ns->tb_sym_root = NULL;
ns->finalizers = NULL;
ns->default_access = ACCESS_UNKNOWN;
ns->parent = parent;
......@@ -2258,7 +2271,6 @@ gfc_new_symtree (gfc_symtree **root, const char *name)
st = XCNEW (gfc_symtree);
st->name = gfc_get_string (name);
st->typebound = NULL;
gfc_insert_bbt (root, st, compare_symtree);
return st;
......@@ -2691,6 +2703,7 @@ void
gfc_undo_symbols (void)
{
gfc_symbol *p, *q, *old;
tentative_tbp *tbp, *tbq;
for (p = changed_syms; p; p = q)
{
......@@ -2789,6 +2802,14 @@ gfc_undo_symbols (void)
}
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
gfc_commit_symbols (void)
{
gfc_symbol *p, *q;
tentative_tbp *tbp, *tbq;
for (p = changed_syms; p; p = q)
{
......@@ -2836,6 +2858,14 @@ gfc_commit_symbols (void)
free_old_symbol (p);
}
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)
}
/* 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
head structures it points to. */
......@@ -3055,6 +3103,7 @@ gfc_free_namespace (gfc_namespace *ns)
free_sym_tree (ns->sym_root);
free_uop_tree (ns->uop_root);
free_common_tree (ns->common_root);
free_tb_tree (ns->tb_sym_root);
gfc_free_finalizer_list (ns->finalizers);
gfc_free_charlen (ns->cl_list, NULL);
free_st_labels (ns->st_labels);
......@@ -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. */
gfc_symbol*
......@@ -4373,15 +4443,15 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t,
/* Try to find it in the current type's namespace. */
gcc_assert (derived->f2k_derived);
res = gfc_find_symtree (derived->f2k_derived->sym_root, name);
if (res && res->typebound)
res = gfc_find_symtree (derived->f2k_derived->tb_sym_root, name);
if (res && res->n.tb)
{
/* We found one. */
if (t)
*t = SUCCESS;
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);
if (t)
......@@ -4403,3 +4473,24 @@ gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t,
/* Nothing found. */
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>
PR middle-end/39867
......
......@@ -28,8 +28,8 @@ MODULE m
PROCEDURE, NOPASS :: gen1 => intf1 ! { dg-error "already a procedure" }
GENERIC :: gen3 => ! { dg-error "specific binding" }
GENERIC :: gen4 => p1 x ! { dg-error "Junk after" }
GENERIC :: gen4 => p_notthere ! { dg-error "Undefined specific binding" }
GENERIC :: gen5 => gen1 ! { dg-error "must target a specific binding" }
GENERIC :: gen5 => p_notthere ! { dg-error "Undefined specific binding" }
GENERIC :: gen6 => gen1 ! { dg-error "must target a specific binding" }
GENERIC :: gensubr => p2 ! { dg-error "mixed FUNCTION/SUBROUTINE" }
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