OSDN Git Service

2011-01-07 Janus Weil <janus@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / class.c
1 /* Implementation of Fortran 2003 Polymorphism.
2    Copyright (C) 2009, 2010
3    Free Software Foundation, Inc.
4    Contributed by Paul Richard Thomas <pault@gcc.gnu.org>
5    and Janus Weil <janus@gcc.gnu.org>
6
7 This file is part of GCC.
8
9 GCC is free software; you can redistribute it and/or modify it under
10 the terms of the GNU General Public License as published by the Free
11 Software Foundation; either version 3, or (at your option) any later
12 version.
13
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
17 for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with GCC; see the file COPYING3.  If not see
21 <http://www.gnu.org/licenses/>.  */
22
23
24 /* class.c -- This file contains the front end functions needed to service
25               the implementation of Fortran 2003 polymorphism and other
26               object-oriented features.  */
27
28
29 /* Outline of the internal representation:
30
31    Each CLASS variable is encapsulated by a class container, which is a
32    structure with two fields:
33     * _data: A pointer to the actual data of the variable. This field has the
34              declared type of the class variable and its attributes
35              (pointer/allocatable/dimension/...).
36     * _vptr: A pointer to the vtable entry (see below) of the dynamic type.
37     
38    For each derived type we set up a "vtable" entry, i.e. a structure with the
39    following fields:
40     * _hash:     A hash value serving as a unique identifier for this type.
41     * _size:     The size in bytes of the derived type.
42     * _extends:  A pointer to the vtable entry of the parent derived type.
43     * _def_init: A pointer to a default initialized variable of this type.
44     * _copy:     A procedure pointer to a copying procedure.
45    After these follow procedure pointer components for the specific
46    type-bound procedures.  */
47
48
49 #include "config.h"
50 #include "system.h"
51 #include "gfortran.h"
52 #include "constructor.h"
53
54
55 /* Insert a reference to the component of the given name.
56    Only to be used with CLASS containers and vtables.  */
57
58 void
59 gfc_add_component_ref (gfc_expr *e, const char *name)
60 {
61   gfc_ref **tail = &(e->ref);
62   gfc_ref *next = NULL;
63   gfc_symbol *derived = e->symtree->n.sym->ts.u.derived;
64   while (*tail != NULL)
65     {
66       if ((*tail)->type == REF_COMPONENT)
67         derived = (*tail)->u.c.component->ts.u.derived;
68       if ((*tail)->type == REF_ARRAY && (*tail)->next == NULL)
69         break;
70       tail = &((*tail)->next);
71     }
72   if (*tail != NULL && strcmp (name, "_data") == 0)
73     next = *tail;
74   (*tail) = gfc_get_ref();
75   (*tail)->next = next;
76   (*tail)->type = REF_COMPONENT;
77   (*tail)->u.c.sym = derived;
78   (*tail)->u.c.component = gfc_find_component (derived, name, true, true);
79   gcc_assert((*tail)->u.c.component);
80   if (!next)
81     e->ts = (*tail)->u.c.component->ts;
82 }
83
84
85 /* Build a NULL initializer for CLASS pointers,
86    initializing the _data component to NULL and
87    the _vptr component to the declared type.  */
88
89 gfc_expr *
90 gfc_class_null_initializer (gfc_typespec *ts)
91 {
92   gfc_expr *init;
93   gfc_component *comp;
94   
95   init = gfc_get_structure_constructor_expr (ts->type, ts->kind,
96                                              &ts->u.derived->declared_at);
97   init->ts = *ts;
98   
99   for (comp = ts->u.derived->components; comp; comp = comp->next)
100     {
101       gfc_constructor *ctor = gfc_constructor_get();
102       if (strcmp (comp->name, "_vptr") == 0)
103         ctor->expr = gfc_lval_expr_from_sym (gfc_find_derived_vtab (ts->u.derived));
104       else
105         ctor->expr = gfc_get_null_expr (NULL);
106       gfc_constructor_append (&init->value.constructor, ctor);
107     }
108
109   return init;
110 }
111
112
113 /* Create a unique string identifier for a derived type, composed of its name
114    and module name. This is used to construct unique names for the class
115    containers and vtab symbols.  */
116
117 static void
118 get_unique_type_string (char *string, gfc_symbol *derived)
119 {  
120   if (derived->module)
121     sprintf (string, "%s_%s", derived->module, derived->name);
122   else if (derived->ns->proc_name)
123     sprintf (string, "%s_%s", derived->ns->proc_name->name, derived->name);
124   else
125     sprintf (string, "_%s", derived->name);
126 }
127
128
129 /* A relative of 'get_unique_type_string' which makes sure the generated
130    string will not be too long (replacing it by a hash string if needed).  */
131
132 static void
133 get_unique_hashed_string (char *string, gfc_symbol *derived)
134 {
135   char tmp[2*GFC_MAX_SYMBOL_LEN+2];
136   get_unique_type_string (&tmp[0], derived);
137   /* If string is too long, use hash value in hex representation
138      (allow for extra decoration, cf. gfc_build_class_symbol)*/
139   if (strlen (tmp) > GFC_MAX_SYMBOL_LEN - 10)
140     {
141       int h = gfc_hash_value (derived);
142       sprintf (string, "%X", h);
143     }
144   else
145     strcpy (string, tmp);
146 }
147
148
149 /* Assign a hash value for a derived type. The algorithm is that of SDBM.  */
150
151 unsigned int
152 gfc_hash_value (gfc_symbol *sym)
153 {
154   unsigned int hash = 0;
155   char c[2*(GFC_MAX_SYMBOL_LEN+1)];
156   int i, len;
157   
158   get_unique_type_string (&c[0], sym);
159   len = strlen (c);
160   
161   for (i = 0; i < len; i++)
162     hash = (hash << 6) + (hash << 16) - hash + c[i];
163
164   /* Return the hash but take the modulus for the sake of module read,
165      even though this slightly increases the chance of collision.  */
166   return (hash % 100000000);
167 }
168
169
170 /* Build a polymorphic CLASS entity, using the symbol that comes from
171    build_sym. A CLASS entity is represented by an encapsulating type,
172    which contains the declared type as '_data' component, plus a pointer
173    component '_vptr' which determines the dynamic type.  */
174
175 gfc_try
176 gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
177                         gfc_array_spec **as, bool delayed_vtab)
178 {
179   char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
180   gfc_symbol *fclass;
181   gfc_symbol *vtab;
182   gfc_component *c;
183
184   /* Determine the name of the encapsulating type.  */
185   get_unique_hashed_string (tname, ts->u.derived);
186   if ((*as) && (*as)->rank && attr->allocatable)
187     sprintf (name, "__class_%s_%d_a", tname, (*as)->rank);
188   else if ((*as) && (*as)->rank)
189     sprintf (name, "__class_%s_%d", tname, (*as)->rank);
190   else if (attr->pointer)
191     sprintf (name, "__class_%s_p", tname);
192   else if (attr->allocatable)
193     sprintf (name, "__class_%s_a", tname);
194   else
195     sprintf (name, "__class_%s", tname);
196
197   gfc_find_symbol (name, ts->u.derived->ns, 0, &fclass);
198   if (fclass == NULL)
199     {
200       gfc_symtree *st;
201       /* If not there, create a new symbol.  */
202       fclass = gfc_new_symbol (name, ts->u.derived->ns);
203       st = gfc_new_symtree (&ts->u.derived->ns->sym_root, name);
204       st->n.sym = fclass;
205       gfc_set_sym_referenced (fclass);
206       fclass->refs++;
207       fclass->ts.type = BT_UNKNOWN;
208       fclass->attr.abstract = ts->u.derived->attr.abstract;
209       if (ts->u.derived->f2k_derived)
210         fclass->f2k_derived = gfc_get_namespace (NULL, 0);
211       if (gfc_add_flavor (&fclass->attr, FL_DERIVED,
212           NULL, &gfc_current_locus) == FAILURE)
213         return FAILURE;
214
215       /* Add component '_data'.  */
216       if (gfc_add_component (fclass, "_data", &c) == FAILURE)
217         return FAILURE;
218       c->ts = *ts;
219       c->ts.type = BT_DERIVED;
220       c->attr.access = ACCESS_PRIVATE;
221       c->ts.u.derived = ts->u.derived;
222       c->attr.class_pointer = attr->pointer;
223       c->attr.pointer = attr->pointer || attr->dummy;
224       c->attr.allocatable = attr->allocatable;
225       c->attr.dimension = attr->dimension;
226       c->attr.codimension = attr->codimension;
227       c->attr.abstract = ts->u.derived->attr.abstract;
228       c->as = (*as);
229       c->initializer = NULL;
230
231       /* Add component '_vptr'.  */
232       if (gfc_add_component (fclass, "_vptr", &c) == FAILURE)
233         return FAILURE;
234       c->ts.type = BT_DERIVED;
235       if (delayed_vtab)
236         c->ts.u.derived = NULL;
237       else
238         {
239           vtab = gfc_find_derived_vtab (ts->u.derived);
240           gcc_assert (vtab);
241           c->ts.u.derived = vtab->ts.u.derived;
242         }
243       c->attr.access = ACCESS_PRIVATE;
244       c->attr.pointer = 1;
245     }
246
247   /* Since the extension field is 8 bit wide, we can only have
248      up to 255 extension levels.  */
249   if (ts->u.derived->attr.extension == 255)
250     {
251       gfc_error ("Maximum extension level reached with type '%s' at %L",
252                  ts->u.derived->name, &ts->u.derived->declared_at);
253       return FAILURE;
254     }
255     
256   fclass->attr.extension = ts->u.derived->attr.extension + 1;
257   fclass->attr.is_class = 1;
258   ts->u.derived = fclass;
259   attr->allocatable = attr->pointer = attr->dimension = 0;
260   (*as) = NULL;  /* XXX */
261   return SUCCESS;
262 }
263
264
265 /* Add a procedure pointer component to the vtype
266    to represent a specific type-bound procedure.  */
267
268 static void
269 add_proc_comp (gfc_symbol *vtype, const char *name, gfc_typebound_proc *tb)
270 {
271   gfc_component *c;
272   c = gfc_find_component (vtype, name, true, true);
273
274   if (c == NULL)
275     {
276       /* Add procedure component.  */
277       if (gfc_add_component (vtype, name, &c) == FAILURE)
278         return;
279
280       if (!c->tb)
281         c->tb = XCNEW (gfc_typebound_proc);
282       *c->tb = *tb;
283       c->tb->ppc = 1;
284       c->attr.procedure = 1;
285       c->attr.proc_pointer = 1;
286       c->attr.flavor = FL_PROCEDURE;
287       c->attr.access = ACCESS_PRIVATE;
288       c->attr.external = 1;
289       c->attr.untyped = 1;
290       c->attr.if_source = IFSRC_IFBODY;
291     }
292   else if (c->attr.proc_pointer && c->tb)
293     {
294       *c->tb = *tb;
295       c->tb->ppc = 1;
296     }
297
298   if (tb->u.specific)
299     {
300       c->ts.interface = tb->u.specific->n.sym;
301       if (!tb->deferred)
302         c->initializer = gfc_get_variable_expr (tb->u.specific);
303     }
304 }
305
306
307 /* Add all specific type-bound procedures in the symtree 'st' to a vtype.  */
308
309 static void
310 add_procs_to_declared_vtab1 (gfc_symtree *st, gfc_symbol *vtype)
311 {
312   if (!st)
313     return;
314
315   if (st->left)
316     add_procs_to_declared_vtab1 (st->left, vtype);
317
318   if (st->right)
319     add_procs_to_declared_vtab1 (st->right, vtype);
320
321   if (st->n.tb && !st->n.tb->error 
322       && !st->n.tb->is_generic && st->n.tb->u.specific)
323     add_proc_comp (vtype, st->name, st->n.tb);
324 }
325
326
327 /* Copy procedure pointers components from the parent type.  */
328
329 static void
330 copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol *vtype)
331 {
332   gfc_component *cmp;
333   gfc_symbol *vtab;
334
335   vtab = gfc_find_derived_vtab (declared);
336
337   for (cmp = vtab->ts.u.derived->components; cmp; cmp = cmp->next)
338     {
339       if (gfc_find_component (vtype, cmp->name, true, true))
340         continue;
341
342       add_proc_comp (vtype, cmp->name, cmp->tb);
343     }
344 }
345
346
347 /* Add procedure pointers for all type-bound procedures to a vtab.  */
348
349 static void
350 add_procs_to_declared_vtab (gfc_symbol *derived, gfc_symbol *vtype)
351 {
352   gfc_symbol* super_type;
353
354   super_type = gfc_get_derived_super_type (derived);
355
356   if (super_type && (super_type != derived))
357     {
358       /* Make sure that the PPCs appear in the same order as in the parent.  */
359       copy_vtab_proc_comps (super_type, vtype);
360       /* Only needed to get the PPC initializers right.  */
361       add_procs_to_declared_vtab (super_type, vtype);
362     }
363
364   if (derived->f2k_derived && derived->f2k_derived->tb_sym_root)
365     add_procs_to_declared_vtab1 (derived->f2k_derived->tb_sym_root, vtype);
366
367   if (derived->f2k_derived && derived->f2k_derived->tb_uop_root)
368     add_procs_to_declared_vtab1 (derived->f2k_derived->tb_uop_root, vtype);
369 }
370
371
372 /* Find (or generate) the symbol for a derived type's vtab.  */
373
374 gfc_symbol *
375 gfc_find_derived_vtab (gfc_symbol *derived)
376 {
377   gfc_namespace *ns;
378   gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL, *def_init = NULL;
379   gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
380   
381   /* Find the top-level namespace (MODULE or PROGRAM).  */
382   for (ns = gfc_current_ns; ns; ns = ns->parent)
383     if (!ns->parent)
384       break;
385
386   /* If the type is a class container, use the underlying derived type.  */
387   if (derived->attr.is_class)
388     derived = gfc_get_derived_super_type (derived);
389     
390   if (ns)
391     {
392       char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
393       
394       get_unique_hashed_string (tname, derived);
395       sprintf (name, "__vtab_%s", tname);
396
397       /* Look for the vtab symbol in various namespaces.  */
398       gfc_find_symbol (name, gfc_current_ns, 0, &vtab);
399       if (vtab == NULL)
400         gfc_find_symbol (name, ns, 0, &vtab);
401       if (vtab == NULL)
402         gfc_find_symbol (name, derived->ns, 0, &vtab);
403
404       if (vtab == NULL)
405         {
406           gfc_get_symbol (name, ns, &vtab);
407           vtab->ts.type = BT_DERIVED;
408           if (gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
409                               &gfc_current_locus) == FAILURE)
410             goto cleanup;
411           vtab->attr.target = 1;
412           vtab->attr.save = SAVE_EXPLICIT;
413           vtab->attr.vtab = 1;
414           vtab->attr.access = ACCESS_PUBLIC;
415           gfc_set_sym_referenced (vtab);
416           sprintf (name, "__vtype_%s", tname);
417           
418           gfc_find_symbol (name, ns, 0, &vtype);
419           if (vtype == NULL)
420             {
421               gfc_component *c;
422               gfc_symbol *parent = NULL, *parent_vtab = NULL;
423
424               gfc_get_symbol (name, ns, &vtype);
425               if (gfc_add_flavor (&vtype->attr, FL_DERIVED,
426                                   NULL, &gfc_current_locus) == FAILURE)
427                 goto cleanup;
428               vtype->attr.access = ACCESS_PUBLIC;
429               vtype->attr.vtype = 1;
430               gfc_set_sym_referenced (vtype);
431
432               /* Add component '_hash'.  */
433               if (gfc_add_component (vtype, "_hash", &c) == FAILURE)
434                 goto cleanup;
435               c->ts.type = BT_INTEGER;
436               c->ts.kind = 4;
437               c->attr.access = ACCESS_PRIVATE;
438               c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
439                                                  NULL, derived->hash_value);
440
441               /* Add component '_size'.  */
442               if (gfc_add_component (vtype, "_size", &c) == FAILURE)
443                 goto cleanup;
444               c->ts.type = BT_INTEGER;
445               c->ts.kind = 4;
446               c->attr.access = ACCESS_PRIVATE;
447               /* Remember the derived type in ts.u.derived,
448                  so that the correct initializer can be set later on
449                  (in gfc_conv_structure).  */
450               c->ts.u.derived = derived;
451               c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
452                                                  NULL, 0);
453
454               /* Add component _extends.  */
455               if (gfc_add_component (vtype, "_extends", &c) == FAILURE)
456                 goto cleanup;
457               c->attr.pointer = 1;
458               c->attr.access = ACCESS_PRIVATE;
459               parent = gfc_get_derived_super_type (derived);
460               if (parent)
461                 {
462                   parent_vtab = gfc_find_derived_vtab (parent);
463                   c->ts.type = BT_DERIVED;
464                   c->ts.u.derived = parent_vtab->ts.u.derived;
465                   c->initializer = gfc_get_expr ();
466                   c->initializer->expr_type = EXPR_VARIABLE;
467                   gfc_find_sym_tree (parent_vtab->name, parent_vtab->ns,
468                                      0, &c->initializer->symtree);
469                 }
470               else
471                 {
472                   c->ts.type = BT_DERIVED;
473                   c->ts.u.derived = vtype;
474                   c->initializer = gfc_get_null_expr (NULL);
475                 }
476
477               if (derived->components == NULL && !derived->attr.zero_comp)
478                 {
479                   /* At this point an error must have occurred.
480                      Prevent further errors on the vtype components.  */
481                   found_sym = vtab;
482                   goto have_vtype;
483                 }
484
485               /* Add component _def_init.  */
486               if (gfc_add_component (vtype, "_def_init", &c) == FAILURE)
487                 goto cleanup;
488               c->attr.pointer = 1;
489               c->attr.access = ACCESS_PRIVATE;
490               c->ts.type = BT_DERIVED;
491               c->ts.u.derived = derived;
492               if (derived->attr.abstract)
493                 c->initializer = gfc_get_null_expr (NULL);
494               else
495                 {
496                   /* Construct default initialization variable.  */
497                   sprintf (name, "__def_init_%s", tname);
498                   gfc_get_symbol (name, ns, &def_init);
499                   def_init->attr.target = 1;
500                   def_init->attr.save = SAVE_EXPLICIT;
501                   def_init->attr.access = ACCESS_PUBLIC;
502                   def_init->attr.flavor = FL_VARIABLE;
503                   gfc_set_sym_referenced (def_init);
504                   def_init->ts.type = BT_DERIVED;
505                   def_init->ts.u.derived = derived;
506                   def_init->value = gfc_default_initializer (&def_init->ts);
507
508                   c->initializer = gfc_lval_expr_from_sym (def_init);
509                 }
510
511               /* Add component _copy.  */
512               if (gfc_add_component (vtype, "_copy", &c) == FAILURE)
513                 goto cleanup;
514               c->attr.proc_pointer = 1;
515               c->attr.access = ACCESS_PRIVATE;
516               c->tb = XCNEW (gfc_typebound_proc);
517               c->tb->ppc = 1;
518               if (derived->attr.abstract)
519                 c->initializer = gfc_get_null_expr (NULL);
520               else
521                 {
522                   /* Set up namespace.  */
523                   gfc_namespace *sub_ns = gfc_get_namespace (ns, 0);
524                   sub_ns->sibling = ns->contained;
525                   ns->contained = sub_ns;
526                   sub_ns->resolved = 1;
527                   /* Set up procedure symbol.  */
528                   sprintf (name, "__copy_%s", tname);
529                   gfc_get_symbol (name, sub_ns, &copy);
530                   sub_ns->proc_name = copy;
531                   copy->attr.flavor = FL_PROCEDURE;
532                   copy->attr.if_source = IFSRC_DECL;
533                   if (ns->proc_name->attr.flavor == FL_MODULE)
534                     copy->module = ns->proc_name->name;
535                   gfc_set_sym_referenced (copy);
536                   /* Set up formal arguments.  */
537                   gfc_get_symbol ("src", sub_ns, &src);
538                   src->ts.type = BT_DERIVED;
539                   src->ts.u.derived = derived;
540                   src->attr.flavor = FL_VARIABLE;
541                   src->attr.dummy = 1;
542                   gfc_set_sym_referenced (src);
543                   copy->formal = gfc_get_formal_arglist ();
544                   copy->formal->sym = src;
545                   gfc_get_symbol ("dst", sub_ns, &dst);
546                   dst->ts.type = BT_DERIVED;
547                   dst->ts.u.derived = derived;
548                   dst->attr.flavor = FL_VARIABLE;
549                   dst->attr.dummy = 1;
550                   gfc_set_sym_referenced (dst);
551                   copy->formal->next = gfc_get_formal_arglist ();
552                   copy->formal->next->sym = dst;
553                   /* Set up code.  */
554                   sub_ns->code = gfc_get_code ();
555                   sub_ns->code->op = EXEC_INIT_ASSIGN;
556                   sub_ns->code->expr1 = gfc_lval_expr_from_sym (dst);
557                   sub_ns->code->expr2 = gfc_lval_expr_from_sym (src);
558                   /* Set initializer.  */
559                   c->initializer = gfc_lval_expr_from_sym (copy);
560                   c->ts.interface = copy;
561                 }
562
563               /* Add procedure pointers for type-bound procedures.  */
564               add_procs_to_declared_vtab (derived, vtype);
565             }
566
567 have_vtype:
568           vtab->ts.u.derived = vtype;
569           vtab->value = gfc_default_initializer (&vtab->ts);
570         }
571     }
572
573   found_sym = vtab;
574
575 cleanup:
576   /* It is unexpected to have some symbols added at resolution or code
577      generation time. We commit the changes in order to keep a clean state.  */
578   if (found_sym)
579     {
580       gfc_commit_symbol (vtab);
581       if (vtype)
582         gfc_commit_symbol (vtype);
583       if (def_init)
584         gfc_commit_symbol (def_init);
585       if (copy)
586         gfc_commit_symbol (copy);
587       if (src)
588         gfc_commit_symbol (src);
589       if (dst)
590         gfc_commit_symbol (dst);
591     }
592   else
593     gfc_undo_symbols ();
594
595   return found_sym;
596 }
597
598
599 /* General worker function to find either a type-bound procedure or a
600    type-bound user operator.  */
601
602 static gfc_symtree*
603 find_typebound_proc_uop (gfc_symbol* derived, gfc_try* t,
604                          const char* name, bool noaccess, bool uop,
605                          locus* where)
606 {
607   gfc_symtree* res;
608   gfc_symtree* root;
609
610   /* Set correct symbol-root.  */
611   gcc_assert (derived->f2k_derived);
612   root = (uop ? derived->f2k_derived->tb_uop_root
613               : derived->f2k_derived->tb_sym_root);
614
615   /* Set default to failure.  */
616   if (t)
617     *t = FAILURE;
618
619   /* Try to find it in the current type's namespace.  */
620   res = gfc_find_symtree (root, name);
621   if (res && res->n.tb && !res->n.tb->error)
622     {
623       /* We found one.  */
624       if (t)
625         *t = SUCCESS;
626
627       if (!noaccess && derived->attr.use_assoc
628           && res->n.tb->access == ACCESS_PRIVATE)
629         {
630           if (where)
631             gfc_error ("'%s' of '%s' is PRIVATE at %L",
632                        name, derived->name, where);
633           if (t)
634             *t = FAILURE;
635         }
636
637       return res;
638     }
639
640   /* Otherwise, recurse on parent type if derived is an extension.  */
641   if (derived->attr.extension)
642     {
643       gfc_symbol* super_type;
644       super_type = gfc_get_derived_super_type (derived);
645       gcc_assert (super_type);
646
647       return find_typebound_proc_uop (super_type, t, name,
648                                       noaccess, uop, where);
649     }
650
651   /* Nothing found.  */
652   return NULL;
653 }
654
655
656 /* Find a type-bound procedure or user operator by name for a derived-type
657    (looking recursively through the super-types).  */
658
659 gfc_symtree*
660 gfc_find_typebound_proc (gfc_symbol* derived, gfc_try* t,
661                          const char* name, bool noaccess, locus* where)
662 {
663   return find_typebound_proc_uop (derived, t, name, noaccess, false, where);
664 }
665
666 gfc_symtree*
667 gfc_find_typebound_user_op (gfc_symbol* derived, gfc_try* t,
668                             const char* name, bool noaccess, locus* where)
669 {
670   return find_typebound_proc_uop (derived, t, name, noaccess, true, where);
671 }
672
673
674 /* Find a type-bound intrinsic operator looking recursively through the
675    super-type hierarchy.  */
676
677 gfc_typebound_proc*
678 gfc_find_typebound_intrinsic_op (gfc_symbol* derived, gfc_try* t,
679                                  gfc_intrinsic_op op, bool noaccess,
680                                  locus* where)
681 {
682   gfc_typebound_proc* res;
683
684   /* Set default to failure.  */
685   if (t)
686     *t = FAILURE;
687
688   /* Try to find it in the current type's namespace.  */
689   if (derived->f2k_derived)
690     res = derived->f2k_derived->tb_op[op];
691   else  
692     res = NULL;
693
694   /* Check access.  */
695   if (res && !res->error)
696     {
697       /* We found one.  */
698       if (t)
699         *t = SUCCESS;
700
701       if (!noaccess && derived->attr.use_assoc
702           && res->access == ACCESS_PRIVATE)
703         {
704           if (where)
705             gfc_error ("'%s' of '%s' is PRIVATE at %L",
706                        gfc_op2string (op), derived->name, where);
707           if (t)
708             *t = FAILURE;
709         }
710
711       return res;
712     }
713
714   /* Otherwise, recurse on parent type if derived is an extension.  */
715   if (derived->attr.extension)
716     {
717       gfc_symbol* super_type;
718       super_type = gfc_get_derived_super_type (derived);
719       gcc_assert (super_type);
720
721       return gfc_find_typebound_intrinsic_op (super_type, t, op,
722                                               noaccess, where);
723     }
724
725   /* Nothing found.  */
726   return NULL;
727 }
728
729
730 /* Get a typebound-procedure symtree or create and insert it if not yet
731    present.  This is like a very simplified version of gfc_get_sym_tree for
732    tbp-symtrees rather than regular ones.  */
733
734 gfc_symtree*
735 gfc_get_tbp_symtree (gfc_symtree **root, const char *name)
736 {
737   gfc_symtree *result;
738
739   result = gfc_find_symtree (*root, name);
740   if (!result)
741     {
742       result = gfc_new_symtree (root, name);
743       gcc_assert (result);
744       result->n.tb = NULL;
745     }
746
747   return result;
748 }