aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kraft <d@domob.eu>2009-04-24 17:20:23 +0200
committerDaniel Kraft <domob@gcc.gnu.org>2009-04-24 17:20:23 +0200
commite34ccb4cd1f39f31ff1bd7374ece738ec7521d74 (patch)
tree6857c66e3f14011e7afd4f510d84a7d7ded9cc88
parentb178461a93752916e0ff817e7db879aa638ab956 (diff)
downloadgcc-e34ccb4cd1f39f31ff1bd7374ece738ec7521d74.zip
gcc-e34ccb4cd1f39f31ff1bd7374ece738ec7521d74.tar.gz
gcc-e34ccb4cd1f39f31ff1bd7374ece738ec7521d74.tar.bz2
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
-rw-r--r--gcc/fortran/ChangeLog36
-rw-r--r--gcc/fortran/decl.c36
-rw-r--r--gcc/fortran/dump-parse-tree.c20
-rw-r--r--gcc/fortran/gfc-internals.texi7
-rw-r--r--gcc/fortran/gfortran.h11
-rw-r--r--gcc/fortran/module.c14
-rw-r--r--gcc/fortran/primary.c10
-rw-r--r--gcc/fortran/resolve.c140
-rw-r--r--gcc/fortran/symbol.c99
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/typebound_generic_1.f034
11 files changed, 262 insertions, 120 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 6af8cbe..769f3c4 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,39 @@
+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
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index b99989f..1a2e845 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -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;
diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c
index 32c97d0..6c91508 100644
--- a/gcc/fortran/dump-parse-tree.c
+++ b/gcc/fortran/dump-parse-tree.c
@@ -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
diff --git a/gcc/fortran/gfc-internals.texi b/gcc/fortran/gfc-internals.texi
index 97aec7b..65fc769 100644
--- a/gcc/fortran/gfc-internals.texi
+++ b/gcc/fortran/gfc-internals.texi
@@ -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}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 5ee297b..875be95 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -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 *);
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index 9c55c2f..12ac966 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -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);
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index cab8f82..7e41535 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -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;
}
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 25834f8..3277475 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -8283,22 +8283,22 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
gfc_formal_arglist* old_formal;
/* This procedure should only be called for non-GENERIC proc. */
- gcc_assert (!proc->typebound->is_generic);
+ gcc_assert (!proc->n.tb->is_generic);
/* If the overwritten procedure is GENERIC, this is an error. */
- if (old->typebound->is_generic)
+ if (old->n.tb->is_generic)
{
gfc_error ("Can't overwrite GENERIC '%s' at %L",
- old->name, &proc->typebound->where);
+ old->name, &proc->n.tb->where);
return FAILURE;
}
- where = proc->typebound->where;
- proc_target = proc->typebound->u.specific->n.sym;
- old_target = old->typebound->u.specific->n.sym;
+ where = proc->n.tb->where;
+ proc_target = proc->n.tb->u.specific->n.sym;
+ old_target = old->n.tb->u.specific->n.sym;
/* Check that overridden binding is not NON_OVERRIDABLE. */
- if (old->typebound->non_overridable)
+ if (old->n.tb->non_overridable)
{
gfc_error ("'%s' at %L overrides a procedure binding declared"
" NON_OVERRIDABLE", proc->name, &where);
@@ -8306,7 +8306,7 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
}
/* It's an error to override a non-DEFERRED procedure with a DEFERRED one. */
- if (!old->typebound->deferred && proc->typebound->deferred)
+ if (!old->n.tb->deferred && proc->n.tb->deferred)
{
gfc_error ("'%s' at %L must not be DEFERRED as it overrides a"
" non-DEFERRED binding", proc->name, &where);
@@ -8370,8 +8370,8 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
/* If the overridden binding is PUBLIC, the overriding one must not be
PRIVATE. */
- if (old->typebound->access == ACCESS_PUBLIC
- && proc->typebound->access == ACCESS_PRIVATE)
+ if (old->n.tb->access == ACCESS_PUBLIC
+ && proc->n.tb->access == ACCESS_PRIVATE)
{
gfc_error ("'%s' at %L overrides a PUBLIC procedure and must not be"
" PRIVATE", proc->name, &where);
@@ -8383,20 +8383,20 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
bindings as at least the overridden one might not yet be resolved and we
need those positions in the check below. */
proc_pass_arg = old_pass_arg = 0;
- if (!proc->typebound->nopass && !proc->typebound->pass_arg)
+ if (!proc->n.tb->nopass && !proc->n.tb->pass_arg)
proc_pass_arg = 1;
- if (!old->typebound->nopass && !old->typebound->pass_arg)
+ if (!old->n.tb->nopass && !old->n.tb->pass_arg)
old_pass_arg = 1;
argpos = 1;
for (proc_formal = proc_target->formal, old_formal = old_target->formal;
proc_formal && old_formal;
proc_formal = proc_formal->next, old_formal = old_formal->next)
{
- if (proc->typebound->pass_arg
- && !strcmp (proc->typebound->pass_arg, proc_formal->sym->name))
+ if (proc->n.tb->pass_arg
+ && !strcmp (proc->n.tb->pass_arg, proc_formal->sym->name))
proc_pass_arg = argpos;
- if (old->typebound->pass_arg
- && !strcmp (old->typebound->pass_arg, old_formal->sym->name))
+ if (old->n.tb->pass_arg
+ && !strcmp (old->n.tb->pass_arg, old_formal->sym->name))
old_pass_arg = argpos;
/* Check that the names correspond. */
@@ -8432,7 +8432,7 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
/* If the overridden binding is NOPASS, the overriding one must also be
NOPASS. */
- if (old->typebound->nopass && !proc->typebound->nopass)
+ if (old->n.tb->nopass && !proc->n.tb->nopass)
{
gfc_error ("'%s' at %L overrides a NOPASS binding and must also be"
" NOPASS", proc->name, &where);
@@ -8441,9 +8441,9 @@ check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
/* If the overridden binding is PASS(x), the overriding one must also be
PASS and the passed-object dummy arguments must correspond. */
- if (!old->typebound->nopass)
+ if (!old->n.tb->nopass)
{
- if (proc->typebound->nopass)
+ if (proc->n.tb->nopass)
{
gfc_error ("'%s' at %L overrides a binding with PASS and must also be"
" PASS", proc->name, &where);
@@ -8512,26 +8512,26 @@ resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st)
gfc_symtree* inherited;
locus where;
- gcc_assert (st->typebound);
- gcc_assert (st->typebound->is_generic);
+ gcc_assert (st->n.tb);
+ gcc_assert (st->n.tb->is_generic);
- where = st->typebound->where;
+ where = st->n.tb->where;
super_type = gfc_get_derived_super_type (derived);
/* Find the overridden binding if any. */
- st->typebound->overridden = NULL;
+ st->n.tb->overridden = NULL;
if (super_type)
{
gfc_symtree* overridden;
overridden = gfc_find_typebound_proc (super_type, NULL, st->name, true);
- if (overridden && overridden->typebound)
- st->typebound->overridden = overridden->typebound;
+ if (overridden && overridden->n.tb)
+ st->n.tb->overridden = overridden->n.tb;
}
/* Try to find the specific bindings for the symtrees in our target-list. */
- gcc_assert (st->typebound->u.generic);
- for (target = st->typebound->u.generic; target; target = target->next)
+ gcc_assert (st->n.tb->u.generic);
+ for (target = st->n.tb->u.generic; target; target = target->next)
if (!target->specific)
{
gfc_typebound_proc* overridden_tbp;
@@ -8541,9 +8541,9 @@ resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st)
target_name = target->specific_st->name;
/* Defined for this type directly. */
- if (target->specific_st->typebound)
+ if (target->specific_st->n.tb)
{
- target->specific = target->specific_st->typebound;
+ target->specific = target->specific_st->n.tb;
goto specific_found;
}
@@ -8555,8 +8555,8 @@ resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st)
if (inherited)
{
- gcc_assert (inherited->typebound);
- target->specific = inherited->typebound;
+ gcc_assert (inherited->n.tb);
+ target->specific = inherited->n.tb;
goto specific_found;
}
}
@@ -8579,14 +8579,14 @@ specific_found:
}
/* Check those already resolved on this type directly. */
- for (g = st->typebound->u.generic; g; g = g->next)
+ for (g = st->n.tb->u.generic; g; g = g->next)
if (g != target && g->specific
&& check_generic_tbp_ambiguity (target, g, st->name, where)
== FAILURE)
return FAILURE;
/* Check for ambiguity with inherited specific targets. */
- for (overridden_tbp = st->typebound->overridden; overridden_tbp;
+ for (overridden_tbp = st->n.tb->overridden; overridden_tbp;
overridden_tbp = overridden_tbp->overridden)
if (overridden_tbp->is_generic)
{
@@ -8601,7 +8601,7 @@ specific_found:
}
/* If we attempt to "overwrite" a specific binding, this is an error. */
- if (st->typebound->overridden && !st->typebound->overridden->is_generic)
+ if (st->n.tb->overridden && !st->n.tb->overridden->is_generic)
{
gfc_error ("GENERIC '%s' at %L can't overwrite specific binding with"
" the same name", st->name, &where);
@@ -8610,9 +8610,10 @@ specific_found:
/* Take the SUBROUTINE/FUNCTION attributes of the first specific target, as
all must have the same attributes here. */
- first_target = st->typebound->u.generic->specific->u.specific;
- st->typebound->subroutine = first_target->n.sym->attr.subroutine;
- st->typebound->function = first_target->n.sym->attr.function;
+ first_target = st->n.tb->u.generic->specific->u.specific;
+ gcc_assert (first_target);
+ st->n.tb->subroutine = first_target->n.sym->attr.subroutine;
+ st->n.tb->function = first_target->n.sym->attr.function;
return SUCCESS;
}
@@ -8632,12 +8633,17 @@ resolve_typebound_procedure (gfc_symtree* stree)
gfc_symbol* super_type;
gfc_component* comp;
- /* If this is no type-bound procedure, just return. */
- if (!stree->typebound)
+ gcc_assert (stree);
+
+ /* Undefined specific symbol from GENERIC target definition. */
+ if (!stree->n.tb)
+ return;
+
+ if (stree->n.tb->error)
return;
/* If this is a GENERIC binding, use that routine. */
- if (stree->typebound->is_generic)
+ if (stree->n.tb->is_generic)
{
if (resolve_typebound_generic (resolve_bindings_derived, stree)
== FAILURE)
@@ -8646,27 +8652,27 @@ resolve_typebound_procedure (gfc_symtree* stree)
}
/* Get the target-procedure to check it. */
- gcc_assert (!stree->typebound->is_generic);
- gcc_assert (stree->typebound->u.specific);
- proc = stree->typebound->u.specific->n.sym;
- where = stree->typebound->where;
+ gcc_assert (!stree->n.tb->is_generic);
+ gcc_assert (stree->n.tb->u.specific);
+ proc = stree->n.tb->u.specific->n.sym;
+ where = stree->n.tb->where;
/* Default access should already be resolved from the parser. */
- gcc_assert (stree->typebound->access != ACCESS_UNKNOWN);
+ gcc_assert (stree->n.tb->access != ACCESS_UNKNOWN);
/* It should be a module procedure or an external procedure with explicit
interface. For DEFERRED bindings, abstract interfaces are ok as well. */
if ((!proc->attr.subroutine && !proc->attr.function)
|| (proc->attr.proc != PROC_MODULE
&& proc->attr.if_source != IFSRC_IFBODY)
- || (proc->attr.abstract && !stree->typebound->deferred))
+ || (proc->attr.abstract && !stree->n.tb->deferred))
{
gfc_error ("'%s' must be a module procedure or an external procedure with"
" an explicit interface at %L", proc->name, &where);
goto error;
}
- stree->typebound->subroutine = proc->attr.subroutine;
- stree->typebound->function = proc->attr.function;
+ stree->n.tb->subroutine = proc->attr.subroutine;
+ stree->n.tb->function = proc->attr.function;
/* Find the super-type of the current derived type. We could do this once and
store in a global if speed is needed, but as long as not I believe this is
@@ -8675,9 +8681,9 @@ resolve_typebound_procedure (gfc_symtree* stree)
/* If PASS, resolve and check arguments if not already resolved / loaded
from a .mod file. */
- if (!stree->typebound->nopass && stree->typebound->pass_arg_num == 0)
+ if (!stree->n.tb->nopass && stree->n.tb->pass_arg_num == 0)
{
- if (stree->typebound->pass_arg)
+ if (stree->n.tb->pass_arg)
{
gfc_formal_arglist* i;
@@ -8685,23 +8691,23 @@ resolve_typebound_procedure (gfc_symtree* stree)
and look for it. */
me_arg = NULL;
- stree->typebound->pass_arg_num = 1;
+ stree->n.tb->pass_arg_num = 1;
for (i = proc->formal; i; i = i->next)
{
- if (!strcmp (i->sym->name, stree->typebound->pass_arg))
+ if (!strcmp (i->sym->name, stree->n.tb->pass_arg))
{
me_arg = i->sym;
break;
}
- ++stree->typebound->pass_arg_num;
+ ++stree->n.tb->pass_arg_num;
}
if (!me_arg)
{
gfc_error ("Procedure '%s' with PASS(%s) at %L has no"
" argument '%s'",
- proc->name, stree->typebound->pass_arg, &where,
- stree->typebound->pass_arg);
+ proc->name, stree->n.tb->pass_arg, &where,
+ stree->n.tb->pass_arg);
goto error;
}
}
@@ -8709,7 +8715,7 @@ resolve_typebound_procedure (gfc_symtree* stree)
{
/* Otherwise, take the first one; there should in fact be at least
one. */
- stree->typebound->pass_arg_num = 1;
+ stree->n.tb->pass_arg_num = 1;
if (!proc->formal)
{
gfc_error ("Procedure '%s' with PASS at %L must have at"
@@ -8737,15 +8743,15 @@ resolve_typebound_procedure (gfc_symtree* stree)
/* If we are extending some type, check that we don't override a procedure
flagged NON_OVERRIDABLE. */
- stree->typebound->overridden = NULL;
+ stree->n.tb->overridden = NULL;
if (super_type)
{
gfc_symtree* overridden;
overridden = gfc_find_typebound_proc (super_type, NULL,
stree->name, true);
- if (overridden && overridden->typebound)
- stree->typebound->overridden = overridden->typebound;
+ if (overridden && overridden->n.tb)
+ stree->n.tb->overridden = overridden->n.tb;
if (overridden && check_typebound_override (stree, overridden) == FAILURE)
goto error;
@@ -8770,23 +8776,23 @@ resolve_typebound_procedure (gfc_symtree* stree)
goto error;
}
- stree->typebound->error = 0;
+ stree->n.tb->error = 0;
return;
error:
resolve_bindings_result = FAILURE;
- stree->typebound->error = 1;
+ stree->n.tb->error = 1;
}
static gfc_try
resolve_typebound_procedures (gfc_symbol* derived)
{
- if (!derived->f2k_derived || !derived->f2k_derived->sym_root)
+ if (!derived->f2k_derived || !derived->f2k_derived->tb_sym_root)
return SUCCESS;
resolve_bindings_derived = derived;
resolve_bindings_result = SUCCESS;
- gfc_traverse_symtree (derived->f2k_derived->sym_root,
+ gfc_traverse_symtree (derived->f2k_derived->tb_sym_root,
&resolve_typebound_procedure);
return resolve_bindings_result;
@@ -8828,12 +8834,12 @@ ensure_not_abstract_walker (gfc_symbol* sub, gfc_symtree* st)
if (ensure_not_abstract_walker (sub, st->right) == FAILURE)
return FAILURE;
- if (st->typebound && st->typebound->deferred)
+ if (st->n.tb && st->n.tb->deferred)
{
gfc_symtree* overriding;
overriding = gfc_find_typebound_proc (sub, NULL, st->name, true);
- gcc_assert (overriding && overriding->typebound);
- if (overriding->typebound->deferred)
+ gcc_assert (overriding && overriding->n.tb);
+ if (overriding->n.tb->deferred)
{
gfc_error ("Derived-type '%s' declared at %L must be ABSTRACT because"
" '%s' is DEFERRED and not overridden",
@@ -8861,7 +8867,7 @@ ensure_not_abstract (gfc_symbol* sub, gfc_symbol* ancestor)
if (ancestor->f2k_derived)
{
gfc_try t;
- t = ensure_not_abstract_walker (sub, ancestor->f2k_derived->sym_root);
+ t = ensure_not_abstract_walker (sub, ancestor->f2k_derived->tb_sym_root);
if (t == FAILURE)
return FAILURE;
}
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index 6aa63be..a82e675 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -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;
+}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7fd0f1f..bbe7fba 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+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
diff --git a/gcc/testsuite/gfortran.dg/typebound_generic_1.f03 b/gcc/testsuite/gfortran.dg/typebound_generic_1.f03
index 0830355..1ae08fc 100644
--- a/gcc/testsuite/gfortran.dg/typebound_generic_1.f03
+++ b/gcc/testsuite/gfortran.dg/typebound_generic_1.f03
@@ -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