OSDN Git Service

2009-04-24 Daniel Kraft <d@domob.eu>
authordomob <domob@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Apr 2009 15:20:23 +0000 (15:20 +0000)
committerdomob <domob@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 24 Apr 2009 15:20:23 +0000 (15:20 +0000)
* 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).

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146733 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/fortran/ChangeLog
gcc/fortran/decl.c
gcc/fortran/dump-parse-tree.c
gcc/fortran/gfc-internals.texi
gcc/fortran/gfortran.h
gcc/fortran/module.c
gcc/fortran/primary.c
gcc/fortran/resolve.c
gcc/fortran/symbol.c
gcc/testsuite/ChangeLog
gcc/testsuite/gfortran.dg/typebound_generic_1.f03

index 6af8cbe..769f3c4 100644 (file)
@@ -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
index b99989f..1a2e845 100644 (file)
@@ -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;
index 32c97d0..6c91508 100644 (file)
@@ -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
index 97aec7b..65fc769 100644 (file)
@@ -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}
index 5ee297b..875be95 100644 (file)
@@ -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 *);
index 9c55c2f..12ac966 100644 (file)
@@ -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);
index cab8f82..7e41535 100644 (file)
@@ -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;
        }
 
index 25834f8..3277475 100644 (file)
@@ -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;
     }
index 6aa63be..a82e675 100644 (file)
@@ -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;
+}
index 7fd0f1f..bbe7fba 100644 (file)
@@ -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
index 0830355..1ae08fc 100644 (file)
@@ -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