]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/fortran/class.c
tree-ssa-ter.h: Remove duplicate copy of file contents.
[thirdparty/gcc.git] / gcc / fortran / class.c
CommitLineData
d15bac21 1/* Implementation of Fortran 2003 Polymorphism.
d1e082c2 2 Copyright (C) 2009-2013 Free Software Foundation, Inc.
4fa02692
JW
3 Contributed by Paul Richard Thomas <pault@gcc.gnu.org>
4 and Janus Weil <janus@gcc.gnu.org>
d15bac21
JW
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along with GCC; see the file COPYING3. If not see
20<http://www.gnu.org/licenses/>. */
21
22
23/* class.c -- This file contains the front end functions needed to service
24 the implementation of Fortran 2003 polymorphism and other
25 object-oriented features. */
26
27
28/* Outline of the internal representation:
29
30 Each CLASS variable is encapsulated by a class container, which is a
31 structure with two fields:
b04533af 32 * _data: A pointer to the actual data of the variable. This field has the
d15bac21
JW
33 declared type of the class variable and its attributes
34 (pointer/allocatable/dimension/...).
b04533af 35 * _vptr: A pointer to the vtable entry (see below) of the dynamic type.
8e54f139 36
d15bac21
JW
37 For each derived type we set up a "vtable" entry, i.e. a structure with the
38 following fields:
b04533af
JW
39 * _hash: A hash value serving as a unique identifier for this type.
40 * _size: The size in bytes of the derived type.
41 * _extends: A pointer to the vtable entry of the parent derived type.
42 * _def_init: A pointer to a default initialized variable of this type.
43 * _copy: A procedure pointer to a copying procedure.
8e54f139
TB
44 * _final: A procedure pointer to a wrapper function, which frees
45 allocatable components and calls FINAL subroutines.
46
611c64f0
JW
47 After these follow procedure pointer components for the specific
48 type-bound procedures. */
d15bac21
JW
49
50
51#include "config.h"
52#include "system.h"
953bee7c 53#include "coretypes.h"
d15bac21
JW
54#include "gfortran.h"
55#include "constructor.h"
56
37da591f
MM
57/* Inserts a derived type component reference in a data reference chain.
58 TS: base type of the ref chain so far, in which we will pick the component
59 REF: the address of the GFC_REF pointer to update
60 NAME: name of the component to insert
61 Note that component insertion makes sense only if we are at the end of
62 the chain (*REF == NULL) or if we are adding a missing "_data" component
63 to access the actual contents of a class object. */
64
65static void
66insert_component_ref (gfc_typespec *ts, gfc_ref **ref, const char * const name)
67{
68 gfc_symbol *type_sym;
69 gfc_ref *new_ref;
70
71 gcc_assert (ts->type == BT_DERIVED || ts->type == BT_CLASS);
72 type_sym = ts->u.derived;
73
74 new_ref = gfc_get_ref ();
75 new_ref->type = REF_COMPONENT;
76 new_ref->next = *ref;
77 new_ref->u.c.sym = type_sym;
78 new_ref->u.c.component = gfc_find_component (type_sym, name, true, true);
79 gcc_assert (new_ref->u.c.component);
80
81 if (new_ref->next)
82 {
83 gfc_ref *next = NULL;
84
85 /* We need to update the base type in the trailing reference chain to
86 that of the new component. */
87
88 gcc_assert (strcmp (name, "_data") == 0);
89
90 if (new_ref->next->type == REF_COMPONENT)
91 next = new_ref->next;
92 else if (new_ref->next->type == REF_ARRAY
93 && new_ref->next->next
94 && new_ref->next->next->type == REF_COMPONENT)
95 next = new_ref->next->next;
96
97 if (next != NULL)
98 {
99 gcc_assert (new_ref->u.c.component->ts.type == BT_CLASS
100 || new_ref->u.c.component->ts.type == BT_DERIVED);
101 next->u.c.sym = new_ref->u.c.component->ts.u.derived;
102 }
103 }
104
105 *ref = new_ref;
106}
107
108
109/* Tells whether we need to add a "_data" reference to access REF subobject
110 from an object of type TS. If FIRST_REF_IN_CHAIN is set, then the base
111 object accessed by REF is a variable; in other words it is a full object,
112 not a subobject. */
113
114static bool
115class_data_ref_missing (gfc_typespec *ts, gfc_ref *ref, bool first_ref_in_chain)
116{
117 /* Only class containers may need the "_data" reference. */
118 if (ts->type != BT_CLASS)
119 return false;
120
121 /* Accessing a class container with an array reference is certainly wrong. */
122 if (ref->type != REF_COMPONENT)
123 return true;
124
125 /* Accessing the class container's fields is fine. */
126 if (ref->u.c.component->name[0] == '_')
127 return false;
128
129 /* At this point we have a class container with a non class container's field
130 component reference. We don't want to add the "_data" component if we are
131 at the first reference and the symbol's type is an extended derived type.
132 In that case, conv_parent_component_references will do the right thing so
133 it is not absolutely necessary. Omitting it prevents a regression (see
134 class_41.f03) in the interface mapping mechanism. When evaluating string
135 lengths depending on dummy arguments, we create a fake symbol with a type
136 equal to that of the dummy type. However, because of type extension,
137 the backend type (corresponding to the actual argument) can have a
138 different (extended) type. Adding the "_data" component explicitly, using
139 the base type, confuses the gfc_conv_component_ref code which deals with
140 the extended type. */
141 if (first_ref_in_chain && ts->u.derived->attr.extension)
142 return false;
143
144 /* We have a class container with a non class container's field component
145 reference that doesn't fall into the above. */
146 return true;
147}
148
149
150/* Browse through a data reference chain and add the missing "_data" references
151 when a subobject of a class object is accessed without it.
152 Note that it doesn't add the "_data" reference when the class container
153 is the last element in the reference chain. */
154
155void
156gfc_fix_class_refs (gfc_expr *e)
157{
158 gfc_typespec *ts;
159 gfc_ref **ref;
160
161 if ((e->expr_type != EXPR_VARIABLE
162 && e->expr_type != EXPR_FUNCTION)
163 || (e->expr_type == EXPR_FUNCTION
164 && e->value.function.isym != NULL))
165 return;
166
d00be3a3
SK
167 if (e->expr_type == EXPR_VARIABLE)
168 ts = &e->symtree->n.sym->ts;
169 else
170 {
171 gfc_symbol *func;
172
173 gcc_assert (e->expr_type == EXPR_FUNCTION);
174 if (e->value.function.esym != NULL)
175 func = e->value.function.esym;
176 else
177 func = e->symtree->n.sym;
178
179 if (func->result != NULL)
180 ts = &func->result->ts;
181 else
182 ts = &func->ts;
183 }
37da591f
MM
184
185 for (ref = &e->ref; *ref != NULL; ref = &(*ref)->next)
186 {
187 if (class_data_ref_missing (ts, *ref, ref == &e->ref))
188 insert_component_ref (ts, ref, "_data");
189
190 if ((*ref)->type == REF_COMPONENT)
191 ts = &(*ref)->u.c.component->ts;
192 }
193}
194
195
d15bac21 196/* Insert a reference to the component of the given name.
b04533af 197 Only to be used with CLASS containers and vtables. */
d15bac21
JW
198
199void
200gfc_add_component_ref (gfc_expr *e, const char *name)
201{
202 gfc_ref **tail = &(e->ref);
203 gfc_ref *next = NULL;
204 gfc_symbol *derived = e->symtree->n.sym->ts.u.derived;
205 while (*tail != NULL)
206 {
207 if ((*tail)->type == REF_COMPONENT)
c49ea23d
PT
208 {
209 if (strcmp ((*tail)->u.c.component->name, "_data") == 0
210 && (*tail)->next
211 && (*tail)->next->type == REF_ARRAY
212 && (*tail)->next->next == NULL)
213 return;
214 derived = (*tail)->u.c.component->ts.u.derived;
215 }
d15bac21
JW
216 if ((*tail)->type == REF_ARRAY && (*tail)->next == NULL)
217 break;
218 tail = &((*tail)->next);
219 }
b04533af 220 if (*tail != NULL && strcmp (name, "_data") == 0)
d15bac21
JW
221 next = *tail;
222 (*tail) = gfc_get_ref();
223 (*tail)->next = next;
224 (*tail)->type = REF_COMPONENT;
225 (*tail)->u.c.sym = derived;
226 (*tail)->u.c.component = gfc_find_component (derived, name, true, true);
227 gcc_assert((*tail)->u.c.component);
228 if (!next)
229 e->ts = (*tail)->u.c.component->ts;
230}
231
232
c49ea23d
PT
233/* This is used to add both the _data component reference and an array
234 reference to class expressions. Used in translation of intrinsic
235 array inquiry functions. */
236
237void
238gfc_add_class_array_ref (gfc_expr *e)
239{
c62c6622 240 int rank = CLASS_DATA (e)->as->rank;
c49ea23d
PT
241 gfc_array_spec *as = CLASS_DATA (e)->as;
242 gfc_ref *ref = NULL;
243 gfc_add_component_ref (e, "_data");
244 e->rank = rank;
245 for (ref = e->ref; ref; ref = ref->next)
246 if (!ref->next)
247 break;
248 if (ref->type != REF_ARRAY)
249 {
250 ref->next = gfc_get_ref ();
251 ref = ref->next;
252 ref->type = REF_ARRAY;
253 ref->u.ar.type = AR_FULL;
8b704316 254 ref->u.ar.as = as;
c49ea23d
PT
255 }
256}
257
258
259/* Unfortunately, class array expressions can appear in various conditions;
260 with and without both _data component and an arrayspec. This function
261 deals with that variability. The previous reference to 'ref' is to a
262 class array. */
263
264static bool
265class_array_ref_detected (gfc_ref *ref, bool *full_array)
266{
267 bool no_data = false;
268 bool with_data = false;
269
270 /* An array reference with no _data component. */
271 if (ref && ref->type == REF_ARRAY
272 && !ref->next
273 && ref->u.ar.type != AR_ELEMENT)
274 {
275 if (full_array)
276 *full_array = ref->u.ar.type == AR_FULL;
277 no_data = true;
278 }
279
280 /* Cover cases where _data appears, with or without an array ref. */
281 if (ref && ref->type == REF_COMPONENT
282 && strcmp (ref->u.c.component->name, "_data") == 0)
283 {
284 if (!ref->next)
285 {
286 with_data = true;
287 if (full_array)
288 *full_array = true;
289 }
290 else if (ref->next && ref->next->type == REF_ARRAY
291 && !ref->next->next
292 && ref->type == REF_COMPONENT
293 && ref->next->type == REF_ARRAY
294 && ref->next->u.ar.type != AR_ELEMENT)
295 {
296 with_data = true;
297 if (full_array)
298 *full_array = ref->next->u.ar.type == AR_FULL;
299 }
300 }
301
302 return no_data || with_data;
303}
304
305
306/* Returns true if the expression contains a reference to a class
307 array. Notice that class array elements return false. */
308
309bool
310gfc_is_class_array_ref (gfc_expr *e, bool *full_array)
311{
312 gfc_ref *ref;
313
314 if (!e->rank)
315 return false;
316
317 if (full_array)
318 *full_array= false;
319
320 /* Is this a class array object? ie. Is the symbol of type class? */
321 if (e->symtree
322 && e->symtree->n.sym->ts.type == BT_CLASS
323 && CLASS_DATA (e->symtree->n.sym)
324 && CLASS_DATA (e->symtree->n.sym)->attr.dimension
325 && class_array_ref_detected (e->ref, full_array))
326 return true;
327
328 /* Or is this a class array component reference? */
329 for (ref = e->ref; ref; ref = ref->next)
330 {
331 if (ref->type == REF_COMPONENT
332 && ref->u.c.component->ts.type == BT_CLASS
333 && CLASS_DATA (ref->u.c.component)->attr.dimension
334 && class_array_ref_detected (ref->next, full_array))
335 return true;
336 }
337
338 return false;
339}
340
341
342/* Returns true if the expression is a reference to a class
343 scalar. This function is necessary because such expressions
344 can be dressed with a reference to the _data component and so
345 have a type other than BT_CLASS. */
346
347bool
348gfc_is_class_scalar_expr (gfc_expr *e)
349{
350 gfc_ref *ref;
351
352 if (e->rank)
353 return false;
354
355 /* Is this a class object? */
356 if (e->symtree
357 && e->symtree->n.sym->ts.type == BT_CLASS
358 && CLASS_DATA (e->symtree->n.sym)
359 && !CLASS_DATA (e->symtree->n.sym)->attr.dimension
360 && (e->ref == NULL
361 || (strcmp (e->ref->u.c.component->name, "_data") == 0
362 && e->ref->next == NULL)))
363 return true;
364
365 /* Or is the final reference BT_CLASS or _data? */
366 for (ref = e->ref; ref; ref = ref->next)
367 {
368 if (ref->type == REF_COMPONENT
369 && ref->u.c.component->ts.type == BT_CLASS
370 && CLASS_DATA (ref->u.c.component)
371 && !CLASS_DATA (ref->u.c.component)->attr.dimension
372 && (ref->next == NULL
373 || (strcmp (ref->next->u.c.component->name, "_data") == 0
374 && ref->next->next == NULL)))
375 return true;
376 }
377
378 return false;
379}
380
381
5bf5fa56
MM
382/* Tells whether the expression E is a reference to a (scalar) class container.
383 Scalar because array class containers usually have an array reference after
384 them, and gfc_fix_class_refs will add the missing "_data" component reference
385 in that case. */
386
387bool
388gfc_is_class_container_ref (gfc_expr *e)
389{
390 gfc_ref *ref;
391 bool result;
392
393 if (e->expr_type != EXPR_VARIABLE)
394 return e->ts.type == BT_CLASS;
395
396 if (e->symtree->n.sym->ts.type == BT_CLASS)
397 result = true;
398 else
399 result = false;
400
401 for (ref = e->ref; ref; ref = ref->next)
402 {
403 if (ref->type != REF_COMPONENT)
404 result = false;
405 else if (ref->u.c.component->ts.type == BT_CLASS)
8b704316 406 result = true;
5bf5fa56
MM
407 else
408 result = false;
409 }
410
411 return result;
412}
413
414
2cc6320d
JW
415/* Build an initializer for CLASS pointers,
416 initializing the _data component to the init_expr (or NULL) and the _vptr
417 component to the corresponding type (or the declared type, given by ts). */
d15bac21
JW
418
419gfc_expr *
2cc6320d 420gfc_class_initializer (gfc_typespec *ts, gfc_expr *init_expr)
d15bac21
JW
421{
422 gfc_expr *init;
423 gfc_component *comp;
8b704316
PT
424 gfc_symbol *vtab = NULL;
425 bool is_unlimited_polymorphic;
426
427 is_unlimited_polymorphic = ts->u.derived
428 && ts->u.derived->components->ts.u.derived
429 && ts->u.derived->components->ts.u.derived->attr.unlimited_polymorphic;
430
431 if (is_unlimited_polymorphic && init_expr)
15115f7a 432 vtab = gfc_find_intrinsic_vtab (&ts->u.derived->components->ts);
2cc6320d
JW
433 else if (init_expr && init_expr->expr_type != EXPR_NULL)
434 vtab = gfc_find_derived_vtab (init_expr->ts.u.derived);
8b704316
PT
435 else
436 vtab = gfc_find_derived_vtab (ts->u.derived);
437
d15bac21
JW
438 init = gfc_get_structure_constructor_expr (ts->type, ts->kind,
439 &ts->u.derived->declared_at);
440 init->ts = *ts;
8b704316 441
d15bac21
JW
442 for (comp = ts->u.derived->components; comp; comp = comp->next)
443 {
444 gfc_constructor *ctor = gfc_constructor_get();
8b704316
PT
445 if (strcmp (comp->name, "_vptr") == 0 && vtab)
446 ctor->expr = gfc_lval_expr_from_sym (vtab);
2cc6320d
JW
447 else if (init_expr && init_expr->expr_type != EXPR_NULL)
448 ctor->expr = gfc_copy_expr (init_expr);
0d87fa8c
JW
449 else
450 ctor->expr = gfc_get_null_expr (NULL);
d15bac21
JW
451 gfc_constructor_append (&init->value.constructor, ctor);
452 }
453
454 return init;
455}
456
457
b04533af
JW
458/* Create a unique string identifier for a derived type, composed of its name
459 and module name. This is used to construct unique names for the class
460 containers and vtab symbols. */
461
462static void
463get_unique_type_string (char *string, gfc_symbol *derived)
b52956be
JW
464{
465 char dt_name[GFC_MAX_SYMBOL_LEN+1];
8b704316 466 if (derived->attr.unlimited_polymorphic)
f5acf0f2 467 strcpy (dt_name, "STAR");
8b704316 468 else
f5acf0f2 469 strcpy (dt_name, derived->name);
b52956be 470 dt_name[0] = TOUPPER (dt_name[0]);
8b704316
PT
471 if (derived->attr.unlimited_polymorphic)
472 sprintf (string, "_%s", dt_name);
473 else if (derived->module)
b52956be 474 sprintf (string, "%s_%s", derived->module, dt_name);
4fa02692 475 else if (derived->ns->proc_name)
b52956be 476 sprintf (string, "%s_%s", derived->ns->proc_name->name, dt_name);
4fa02692 477 else
b52956be 478 sprintf (string, "_%s", dt_name);
4fa02692
JW
479}
480
481
482/* A relative of 'get_unique_type_string' which makes sure the generated
483 string will not be too long (replacing it by a hash string if needed). */
484
485static void
486get_unique_hashed_string (char *string, gfc_symbol *derived)
487{
488 char tmp[2*GFC_MAX_SYMBOL_LEN+2];
489 get_unique_type_string (&tmp[0], derived);
cb83a137 490 /* If string is too long, use hash value in hex representation (allow for
2419ff64
TB
491 extra decoration, cf. gfc_build_class_symbol & gfc_find_derived_vtab).
492 We need space to for 15 characters "__class_" + symbol name + "_%d_%da",
493 where %d is the (co)rank which can be up to n = 15. */
494 if (strlen (tmp) > GFC_MAX_SYMBOL_LEN - 15)
4fa02692
JW
495 {
496 int h = gfc_hash_value (derived);
497 sprintf (string, "%X", h);
498 }
499 else
500 strcpy (string, tmp);
501}
502
503
504/* Assign a hash value for a derived type. The algorithm is that of SDBM. */
505
506unsigned int
507gfc_hash_value (gfc_symbol *sym)
508{
509 unsigned int hash = 0;
510 char c[2*(GFC_MAX_SYMBOL_LEN+1)];
511 int i, len;
8b704316 512
4fa02692
JW
513 get_unique_type_string (&c[0], sym);
514 len = strlen (c);
8b704316
PT
515
516 for (i = 0; i < len; i++)
517 hash = (hash << 6) + (hash << 16) - hash + c[i];
518
519 /* Return the hash but take the modulus for the sake of module read,
520 even though this slightly increases the chance of collision. */
521 return (hash % 100000000);
522}
523
524
525/* Assign a hash value for an intrinsic type. The algorithm is that of SDBM. */
526
527unsigned int
528gfc_intrinsic_hash_value (gfc_typespec *ts)
529{
530 unsigned int hash = 0;
531 const char *c = gfc_typename (ts);
532 int i, len;
533
534 len = strlen (c);
535
4fa02692
JW
536 for (i = 0; i < len; i++)
537 hash = (hash << 6) + (hash << 16) - hash + c[i];
538
539 /* Return the hash but take the modulus for the sake of module read,
540 even though this slightly increases the chance of collision. */
541 return (hash % 100000000);
b04533af
JW
542}
543
544
d15bac21
JW
545/* Build a polymorphic CLASS entity, using the symbol that comes from
546 build_sym. A CLASS entity is represented by an encapsulating type,
b04533af
JW
547 which contains the declared type as '_data' component, plus a pointer
548 component '_vptr' which determines the dynamic type. */
d15bac21 549
524af0d6 550bool
d15bac21
JW
551gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
552 gfc_array_spec **as, bool delayed_vtab)
553{
4fa02692 554 char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
d15bac21
JW
555 gfc_symbol *fclass;
556 gfc_symbol *vtab;
557 gfc_component *c;
8b704316 558 gfc_namespace *ns;
c62c6622 559 int rank;
c49ea23d 560
fc2655fb
TB
561 gcc_assert (as);
562
563 if (*as && (*as)->type == AS_ASSUMED_SIZE)
c49ea23d
PT
564 {
565 gfc_error ("Assumed size polymorphic objects or components, such "
566 "as that at %C, have not yet been implemented");
524af0d6 567 return false;
c49ea23d
PT
568 }
569
528622fd
JW
570 if (attr->class_ok)
571 /* Class container has already been built. */
524af0d6 572 return true;
528622fd 573
7d40e49f 574 attr->class_ok = attr->dummy || attr->pointer || attr->allocatable
aa271860 575 || attr->select_type_temporary || attr->associate_var;
8b704316 576
528622fd
JW
577 if (!attr->class_ok)
578 /* We can not build the class container yet. */
524af0d6 579 return true;
d15bac21
JW
580
581 /* Determine the name of the encapsulating type. */
c62c6622 582 rank = !(*as) || (*as)->rank == -1 ? GFC_MAX_DIMENSIONS : (*as)->rank;
4fa02692 583 get_unique_hashed_string (tname, ts->u.derived);
2419ff64 584 if ((*as) && attr->allocatable)
c62c6622
TB
585 sprintf (name, "__class_%s_%d_%da", tname, rank, (*as)->corank);
586 else if ((*as) && attr->pointer)
587 sprintf (name, "__class_%s_%d_%dp", tname, rank, (*as)->corank);
2419ff64 588 else if ((*as))
c62c6622 589 sprintf (name, "__class_%s_%d_%d", tname, rank, (*as)->corank);
d15bac21 590 else if (attr->pointer)
b04533af 591 sprintf (name, "__class_%s_p", tname);
d15bac21 592 else if (attr->allocatable)
b04533af 593 sprintf (name, "__class_%s_a", tname);
d15bac21 594 else
b04533af 595 sprintf (name, "__class_%s", tname);
d15bac21 596
8b704316
PT
597 if (ts->u.derived->attr.unlimited_polymorphic)
598 {
599 /* Find the top-level namespace. */
600 for (ns = gfc_current_ns; ns; ns = ns->parent)
601 if (!ns->parent)
602 break;
603 }
604 else
605 ns = ts->u.derived->ns;
606
607 gfc_find_symbol (name, ns, 0, &fclass);
d15bac21
JW
608 if (fclass == NULL)
609 {
610 gfc_symtree *st;
611 /* If not there, create a new symbol. */
8b704316
PT
612 fclass = gfc_new_symbol (name, ns);
613 st = gfc_new_symtree (&ns->sym_root, name);
d15bac21
JW
614 st->n.sym = fclass;
615 gfc_set_sym_referenced (fclass);
616 fclass->refs++;
617 fclass->ts.type = BT_UNKNOWN;
8b704316 618 if (!ts->u.derived->attr.unlimited_polymorphic)
94241120 619 fclass->attr.abstract = ts->u.derived->attr.abstract;
42ff605a 620 fclass->f2k_derived = gfc_get_namespace (NULL, 0);
524af0d6
JB
621 if (!gfc_add_flavor (&fclass->attr, FL_DERIVED, NULL,
622 &gfc_current_locus))
623 return false;
d15bac21 624
b04533af 625 /* Add component '_data'. */
524af0d6
JB
626 if (!gfc_add_component (fclass, "_data", &c))
627 return false;
d15bac21
JW
628 c->ts = *ts;
629 c->ts.type = BT_DERIVED;
630 c->attr.access = ACCESS_PRIVATE;
631 c->ts.u.derived = ts->u.derived;
632 c->attr.class_pointer = attr->pointer;
7d40e49f
TB
633 c->attr.pointer = attr->pointer || (attr->dummy && !attr->allocatable)
634 || attr->select_type_temporary;
d15bac21
JW
635 c->attr.allocatable = attr->allocatable;
636 c->attr.dimension = attr->dimension;
637 c->attr.codimension = attr->codimension;
8b704316 638 c->attr.abstract = fclass->attr.abstract;
d15bac21
JW
639 c->as = (*as);
640 c->initializer = NULL;
641
b04533af 642 /* Add component '_vptr'. */
524af0d6
JB
643 if (!gfc_add_component (fclass, "_vptr", &c))
644 return false;
d15bac21 645 c->ts.type = BT_DERIVED;
8e54f139
TB
646 if (delayed_vtab
647 || (ts->u.derived->f2k_derived
648 && ts->u.derived->f2k_derived->finalizers))
d15bac21
JW
649 c->ts.u.derived = NULL;
650 else
651 {
88ce8031 652 vtab = gfc_find_derived_vtab (ts->u.derived);
d15bac21
JW
653 gcc_assert (vtab);
654 c->ts.u.derived = vtab->ts.u.derived;
655 }
f3f98a1e 656 c->attr.access = ACCESS_PRIVATE;
d15bac21
JW
657 c->attr.pointer = 1;
658 }
659
8b704316 660 if (!ts->u.derived->attr.unlimited_polymorphic)
d15bac21 661 {
8b704316
PT
662 /* Since the extension field is 8 bit wide, we can only have
663 up to 255 extension levels. */
664 if (ts->u.derived->attr.extension == 255)
665 {
666 gfc_error ("Maximum extension level reached with type '%s' at %L",
667 ts->u.derived->name, &ts->u.derived->declared_at);
524af0d6 668 return false;
8b704316
PT
669 }
670
671 fclass->attr.extension = ts->u.derived->attr.extension + 1;
672 fclass->attr.alloc_comp = ts->u.derived->attr.alloc_comp;
558f3755 673 fclass->attr.coarray_comp = ts->u.derived->attr.coarray_comp;
d15bac21 674 }
8b704316 675
d15bac21
JW
676 fclass->attr.is_class = 1;
677 ts->u.derived = fclass;
c49ea23d
PT
678 attr->allocatable = attr->pointer = attr->dimension = attr->codimension = 0;
679 (*as) = NULL;
524af0d6 680 return true;
d15bac21
JW
681}
682
683
88ce8031
JW
684/* Add a procedure pointer component to the vtype
685 to represent a specific type-bound procedure. */
686
d15bac21 687static void
88ce8031 688add_proc_comp (gfc_symbol *vtype, const char *name, gfc_typebound_proc *tb)
d15bac21 689{
88ce8031 690 gfc_component *c;
fd83db3d
JW
691
692 if (tb->non_overridable)
693 return;
8b704316 694
88ce8031
JW
695 c = gfc_find_component (vtype, name, true, true);
696
697 if (c == NULL)
d15bac21 698 {
88ce8031 699 /* Add procedure component. */
524af0d6 700 if (!gfc_add_component (vtype, name, &c))
d15bac21 701 return;
d15bac21 702
88ce8031
JW
703 if (!c->tb)
704 c->tb = XCNEW (gfc_typebound_proc);
705 *c->tb = *tb;
706 c->tb->ppc = 1;
707 c->attr.procedure = 1;
708 c->attr.proc_pointer = 1;
709 c->attr.flavor = FL_PROCEDURE;
710 c->attr.access = ACCESS_PRIVATE;
711 c->attr.external = 1;
712 c->attr.untyped = 1;
713 c->attr.if_source = IFSRC_IFBODY;
d15bac21
JW
714 }
715 else if (c->attr.proc_pointer && c->tb)
716 {
88ce8031 717 *c->tb = *tb;
d15bac21 718 c->tb->ppc = 1;
1d0134b3
JW
719 }
720
721 if (tb->u.specific)
722 {
723 c->ts.interface = tb->u.specific->n.sym;
724 if (!tb->deferred)
725 c->initializer = gfc_get_variable_expr (tb->u.specific);
d15bac21
JW
726 }
727}
728
88ce8031
JW
729
730/* Add all specific type-bound procedures in the symtree 'st' to a vtype. */
731
d15bac21 732static void
88ce8031 733add_procs_to_declared_vtab1 (gfc_symtree *st, gfc_symbol *vtype)
d15bac21 734{
d15bac21
JW
735 if (!st)
736 return;
737
738 if (st->left)
88ce8031 739 add_procs_to_declared_vtab1 (st->left, vtype);
d15bac21
JW
740
741 if (st->right)
88ce8031 742 add_procs_to_declared_vtab1 (st->right, vtype);
d15bac21 743
8b704316 744 if (st->n.tb && !st->n.tb->error
aea18e92 745 && !st->n.tb->is_generic && st->n.tb->u.specific)
88ce8031 746 add_proc_comp (vtype, st->name, st->n.tb);
d15bac21
JW
747}
748
749
88ce8031
JW
750/* Copy procedure pointers components from the parent type. */
751
d15bac21 752static void
88ce8031 753copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol *vtype)
d15bac21 754{
88ce8031 755 gfc_component *cmp;
d15bac21
JW
756 gfc_symbol *vtab;
757
88ce8031 758 vtab = gfc_find_derived_vtab (declared);
d15bac21
JW
759
760 for (cmp = vtab->ts.u.derived->components; cmp; cmp = cmp->next)
761 {
762 if (gfc_find_component (vtype, cmp->name, true, true))
763 continue;
764
88ce8031 765 add_proc_comp (vtype, cmp->name, cmp->tb);
d15bac21
JW
766 }
767}
768
d15bac21 769
8e54f139
TB
770/* Returns true if any of its nonpointer nonallocatable components or
771 their nonpointer nonallocatable subcomponents has a finalization
772 subroutine. */
773
774static bool
775has_finalizer_component (gfc_symbol *derived)
776{
777 gfc_component *c;
778
779 for (c = derived->components; c; c = c->next)
780 {
781 if (c->ts.type == BT_DERIVED && c->ts.u.derived->f2k_derived
782 && c->ts.u.derived->f2k_derived->finalizers)
783 return true;
784
785 if (c->ts.type == BT_DERIVED
786 && !c->attr.pointer && !c->attr.allocatable
787 && has_finalizer_component (c->ts.u.derived))
788 return true;
789 }
790 return false;
791}
792
793
794/* Call DEALLOCATE for the passed component if it is allocatable, if it is
795 neither allocatable nor a pointer but has a finalizer, call it. If it
bc7a2337
TB
796 is a nonpointer component with allocatable components or has finalizers, walk
797 them. Either of them is required; other nonallocatables and pointers aren't
8e54f139
TB
798 handled gracefully.
799 Note: If the component is allocatable, the DEALLOCATE handling takes care
800 of calling the appropriate finalizers, coarray deregistering, and
801 deallocation of allocatable subcomponents. */
802
803static void
804finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
29a7d776 805 gfc_symbol *stat, gfc_symbol *fini_coarray, gfc_code **code)
8e54f139
TB
806{
807 gfc_expr *e;
808 gfc_ref *ref;
809
810 if (comp->ts.type != BT_DERIVED && comp->ts.type != BT_CLASS
811 && !comp->attr.allocatable)
812 return;
813
814 if ((comp->ts.type == BT_DERIVED && comp->attr.pointer)
815 || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
816 && CLASS_DATA (comp)->attr.pointer))
817 return;
818
819 if (comp->ts.type == BT_DERIVED && !comp->attr.allocatable
820 && (comp->ts.u.derived->f2k_derived == NULL
821 || comp->ts.u.derived->f2k_derived->finalizers == NULL)
822 && !has_finalizer_component (comp->ts.u.derived))
823 return;
824
825 e = gfc_copy_expr (expr);
826 if (!e->ref)
827 e->ref = ref = gfc_get_ref ();
828 else
829 {
830 for (ref = e->ref; ref->next; ref = ref->next)
831 ;
832 ref->next = gfc_get_ref ();
833 ref = ref->next;
834 }
835 ref->type = REF_COMPONENT;
836 ref->u.c.sym = derived;
837 ref->u.c.component = comp;
838 e->ts = comp->ts;
839
16023efc 840 if (comp->attr.dimension || comp->attr.codimension
8e54f139 841 || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
16023efc
TB
842 && (CLASS_DATA (comp)->attr.dimension
843 || CLASS_DATA (comp)->attr.codimension)))
8e54f139
TB
844 {
845 ref->next = gfc_get_ref ();
846 ref->next->type = REF_ARRAY;
8e54f139
TB
847 ref->next->u.ar.dimen = 0;
848 ref->next->u.ar.as = comp->ts.type == BT_CLASS ? CLASS_DATA (comp)->as
849 : comp->as;
850 e->rank = ref->next->u.ar.as->rank;
16023efc 851 ref->next->u.ar.type = e->rank ? AR_FULL : AR_ELEMENT;
8e54f139
TB
852 }
853
29a7d776 854 /* Call DEALLOCATE (comp, stat=ignore). */
8e54f139
TB
855 if (comp->attr.allocatable
856 || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
857 && CLASS_DATA (comp)->attr.allocatable))
858 {
29a7d776
TB
859 gfc_code *dealloc, *block = NULL;
860
861 /* Add IF (fini_coarray). */
862 if (comp->attr.codimension
863 || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
864 && CLASS_DATA (comp)->attr.allocatable))
865 {
11e5274a 866 block = gfc_get_code (EXEC_IF);
29a7d776
TB
867 if (*code)
868 {
869 (*code)->next = block;
870 (*code) = (*code)->next;
871 }
872 else
873 (*code) = block;
874
11e5274a 875 block->block = gfc_get_code (EXEC_IF);
29a7d776 876 block = block->block;
29a7d776
TB
877 block->expr1 = gfc_lval_expr_from_sym (fini_coarray);
878 }
8e54f139 879
11e5274a 880 dealloc = gfc_get_code (EXEC_DEALLOCATE);
8e54f139
TB
881
882 dealloc->ext.alloc.list = gfc_get_alloc ();
883 dealloc->ext.alloc.list->expr = e;
29a7d776 884 dealloc->expr1 = gfc_lval_expr_from_sym (stat);
8e54f139 885
29a7d776
TB
886 if (block)
887 block->next = dealloc;
888 else if (*code)
8e54f139
TB
889 {
890 (*code)->next = dealloc;
891 (*code) = (*code)->next;
892 }
893 else
894 (*code) = dealloc;
895 }
896 else if (comp->ts.type == BT_DERIVED
897 && comp->ts.u.derived->f2k_derived
898 && comp->ts.u.derived->f2k_derived->finalizers)
899 {
900 /* Call FINAL_WRAPPER (comp); */
901 gfc_code *final_wrap;
902 gfc_symbol *vtab;
903 gfc_component *c;
904
905 vtab = gfc_find_derived_vtab (comp->ts.u.derived);
906 for (c = vtab->ts.u.derived->components; c; c = c->next)
907 if (strcmp (c->name, "_final") == 0)
908 break;
909
910 gcc_assert (c);
11e5274a 911 final_wrap = gfc_get_code (EXEC_CALL);
8e54f139
TB
912 final_wrap->symtree = c->initializer->symtree;
913 final_wrap->resolved_sym = c->initializer->symtree->n.sym;
914 final_wrap->ext.actual = gfc_get_actual_arglist ();
915 final_wrap->ext.actual->expr = e;
916
917 if (*code)
918 {
919 (*code)->next = final_wrap;
920 (*code) = (*code)->next;
921 }
922 else
923 (*code) = final_wrap;
924 }
925 else
926 {
927 gfc_component *c;
928
929 for (c = comp->ts.u.derived->components; c; c = c->next)
29a7d776 930 finalize_component (e, comp->ts.u.derived, c, stat, fini_coarray, code);
fc2655fb 931 gfc_free_expr (e);
8e54f139
TB
932 }
933}
934
935
936/* Generate code equivalent to
937 CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
9e04287b 938 + offset, c_ptr), ptr). */
8e54f139
TB
939
940static gfc_code *
9e04287b
TB
941finalization_scalarizer (gfc_symbol *array, gfc_symbol *ptr,
942 gfc_expr *offset, gfc_namespace *sub_ns)
8e54f139
TB
943{
944 gfc_code *block;
9e04287b 945 gfc_expr *expr, *expr2;
8e54f139
TB
946
947 /* C_F_POINTER(). */
11e5274a 948 block = gfc_get_code (EXEC_CALL);
8e54f139
TB
949 gfc_get_sym_tree ("c_f_pointer", sub_ns, &block->symtree, true);
950 block->resolved_sym = block->symtree->n.sym;
951 block->resolved_sym->attr.flavor = FL_PROCEDURE;
952 block->resolved_sym->attr.intrinsic = 1;
cbde6c0f 953 block->resolved_sym->attr.subroutine = 1;
8e54f139
TB
954 block->resolved_sym->from_intmod = INTMOD_ISO_C_BINDING;
955 block->resolved_sym->intmod_sym_id = ISOCBINDING_F_POINTER;
cbde6c0f 956 block->resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_C_F_POINTER);
8e54f139
TB
957 gfc_commit_symbol (block->resolved_sym);
958
959 /* C_F_POINTER's first argument: TRANSFER ( <addr>, c_intptr_t). */
960 block->ext.actual = gfc_get_actual_arglist ();
961 block->ext.actual->next = gfc_get_actual_arglist ();
962 block->ext.actual->next->expr = gfc_get_int_expr (gfc_index_integer_kind,
963 NULL, 0);
cbde6c0f 964 block->ext.actual->next->next = gfc_get_actual_arglist (); /* SIZE. */
8e54f139
TB
965
966 /* The <addr> part: TRANSFER (C_LOC (array), c_intptr_t). */
967
8e54f139
TB
968 /* TRANSFER's first argument: C_LOC (array). */
969 expr = gfc_get_expr ();
970 expr->expr_type = EXPR_FUNCTION;
971 gfc_get_sym_tree ("c_loc", sub_ns, &expr->symtree, false);
972 expr->symtree->n.sym->attr.flavor = FL_PROCEDURE;
973 expr->symtree->n.sym->intmod_sym_id = ISOCBINDING_LOC;
974 expr->symtree->n.sym->attr.intrinsic = 1;
975 expr->symtree->n.sym->from_intmod = INTMOD_ISO_C_BINDING;
cbde6c0f 976 expr->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_C_LOC);
8e54f139
TB
977 expr->value.function.actual = gfc_get_actual_arglist ();
978 expr->value.function.actual->expr
979 = gfc_lval_expr_from_sym (array);
980 expr->symtree->n.sym->result = expr->symtree->n.sym;
981 gfc_commit_symbol (expr->symtree->n.sym);
982 expr->ts.type = BT_INTEGER;
983 expr->ts.kind = gfc_index_integer_kind;
6838c137
TB
984
985 /* TRANSFER. */
986 expr2 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_TRANSFER, "transfer",
cbde6c0f 987 gfc_current_locus, 3, expr,
6838c137 988 gfc_get_int_expr (gfc_index_integer_kind,
cbde6c0f 989 NULL, 0), NULL);
6838c137
TB
990 expr2->ts.type = BT_INTEGER;
991 expr2->ts.kind = gfc_index_integer_kind;
8e54f139 992
8e54f139
TB
993 /* <array addr> + <offset>. */
994 block->ext.actual->expr = gfc_get_expr ();
995 block->ext.actual->expr->expr_type = EXPR_OP;
996 block->ext.actual->expr->value.op.op = INTRINSIC_PLUS;
997 block->ext.actual->expr->value.op.op1 = expr2;
9e04287b 998 block->ext.actual->expr->value.op.op2 = offset;
8e54f139
TB
999 block->ext.actual->expr->ts = expr->ts;
1000
1001 /* C_F_POINTER's 2nd arg: ptr -- and its absent shape=. */
1002 block->ext.actual->next = gfc_get_actual_arglist ();
1003 block->ext.actual->next->expr = gfc_lval_expr_from_sym (ptr);
1004 block->ext.actual->next->next = gfc_get_actual_arglist ();
1005
1006 return block;
1007}
1008
1009
9e04287b
TB
1010/* Calculates the offset to the (idx+1)th element of an array, taking the
1011 stride into account. It generates the code:
1012 offset = 0
1013 do idx2 = 1, rank
1014 offset = offset + mod (idx, sizes(idx2)) / sizes(idx2-1) * strides(idx2)
1015 end do
1016 offset = offset * byte_stride. */
1017
1018static gfc_code*
1019finalization_get_offset (gfc_symbol *idx, gfc_symbol *idx2, gfc_symbol *offset,
1020 gfc_symbol *strides, gfc_symbol *sizes,
1021 gfc_symbol *byte_stride, gfc_expr *rank,
1022 gfc_code *block, gfc_namespace *sub_ns)
1023{
1024 gfc_iterator *iter;
1025 gfc_expr *expr, *expr2;
1026
1027 /* offset = 0. */
11e5274a 1028 block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1029 block = block->next;
9e04287b
TB
1030 block->expr1 = gfc_lval_expr_from_sym (offset);
1031 block->expr2 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1032
1033 /* Create loop. */
1034 iter = gfc_get_iterator ();
1035 iter->var = gfc_lval_expr_from_sym (idx2);
1036 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1037 iter->end = gfc_copy_expr (rank);
1038 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
11e5274a 1039 block->next = gfc_get_code (EXEC_DO);
9e04287b 1040 block = block->next;
9e04287b 1041 block->ext.iterator = iter;
11e5274a 1042 block->block = gfc_get_code (EXEC_DO);
9e04287b
TB
1043
1044 /* Loop body: offset = offset + mod (idx, sizes(idx2)) / sizes(idx2-1)
1045 * strides(idx2). */
1046
1047 /* mod (idx, sizes(idx2)). */
6838c137
TB
1048 expr = gfc_lval_expr_from_sym (sizes);
1049 expr->ref = gfc_get_ref ();
1050 expr->ref->type = REF_ARRAY;
1051 expr->ref->u.ar.as = sizes->as;
1052 expr->ref->u.ar.type = AR_ELEMENT;
1053 expr->ref->u.ar.dimen = 1;
1054 expr->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1055 expr->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx2);
1056
1057 expr = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_MOD, "mod",
1058 gfc_current_locus, 2,
1059 gfc_lval_expr_from_sym (idx), expr);
9e04287b
TB
1060 expr->ts = idx->ts;
1061
1062 /* (...) / sizes(idx2-1). */
1063 expr2 = gfc_get_expr ();
1064 expr2->expr_type = EXPR_OP;
1065 expr2->value.op.op = INTRINSIC_DIVIDE;
1066 expr2->value.op.op1 = expr;
1067 expr2->value.op.op2 = gfc_lval_expr_from_sym (sizes);
1068 expr2->value.op.op2->ref = gfc_get_ref ();
1069 expr2->value.op.op2->ref->type = REF_ARRAY;
1070 expr2->value.op.op2->ref->u.ar.as = sizes->as;
1071 expr2->value.op.op2->ref->u.ar.type = AR_ELEMENT;
1072 expr2->value.op.op2->ref->u.ar.dimen = 1;
1073 expr2->value.op.op2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1074 expr2->value.op.op2->ref->u.ar.start[0] = gfc_get_expr ();
1075 expr2->value.op.op2->ref->u.ar.start[0]->expr_type = EXPR_OP;
1076 expr2->value.op.op2->ref->u.ar.start[0]->value.op.op = INTRINSIC_MINUS;
1077 expr2->value.op.op2->ref->u.ar.start[0]->value.op.op1
1078 = gfc_lval_expr_from_sym (idx2);
1079 expr2->value.op.op2->ref->u.ar.start[0]->value.op.op2
1080 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1081 expr2->value.op.op2->ref->u.ar.start[0]->ts
1082 = expr2->value.op.op2->ref->u.ar.start[0]->value.op.op1->ts;
1083 expr2->ts = idx->ts;
1084
1085 /* ... * strides(idx2). */
1086 expr = gfc_get_expr ();
1087 expr->expr_type = EXPR_OP;
1088 expr->value.op.op = INTRINSIC_TIMES;
1089 expr->value.op.op1 = expr2;
1090 expr->value.op.op2 = gfc_lval_expr_from_sym (strides);
1091 expr->value.op.op2->ref = gfc_get_ref ();
1092 expr->value.op.op2->ref->type = REF_ARRAY;
1093 expr->value.op.op2->ref->u.ar.type = AR_ELEMENT;
1094 expr->value.op.op2->ref->u.ar.dimen = 1;
1095 expr->value.op.op2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1096 expr->value.op.op2->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx2);
1097 expr->value.op.op2->ref->u.ar.as = strides->as;
1098 expr->ts = idx->ts;
1099
1100 /* offset = offset + ... */
11e5274a 1101 block->block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b
TB
1102 block->block->next->expr1 = gfc_lval_expr_from_sym (offset);
1103 block->block->next->expr2 = gfc_get_expr ();
1104 block->block->next->expr2->expr_type = EXPR_OP;
1105 block->block->next->expr2->value.op.op = INTRINSIC_PLUS;
1106 block->block->next->expr2->value.op.op1 = gfc_lval_expr_from_sym (offset);
1107 block->block->next->expr2->value.op.op2 = expr;
1108 block->block->next->expr2->ts = idx->ts;
1109
1110 /* After the loop: offset = offset * byte_stride. */
11e5274a 1111 block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1112 block = block->next;
9e04287b
TB
1113 block->expr1 = gfc_lval_expr_from_sym (offset);
1114 block->expr2 = gfc_get_expr ();
1115 block->expr2->expr_type = EXPR_OP;
1116 block->expr2->value.op.op = INTRINSIC_TIMES;
1117 block->expr2->value.op.op1 = gfc_lval_expr_from_sym (offset);
1118 block->expr2->value.op.op2 = gfc_lval_expr_from_sym (byte_stride);
1119 block->expr2->ts = block->expr2->value.op.op1->ts;
1120 return block;
1121}
1122
1123
29a7d776
TB
1124/* Insert code of the following form:
1125
9e04287b
TB
1126 block
1127 integer(c_intptr_t) :: i
1128
1129 if ((byte_stride == STORAGE_SIZE (array)/NUMERIC_STORAGE_SIZE
1130 && (is_contiguous || !final_rank3->attr.contiguous
1131 || final_rank3->as->type != AS_ASSUMED_SHAPE))
1132 || 0 == STORAGE_SIZE (array)) then
1133 call final_rank3 (array)
1134 else
1135 block
1136 integer(c_intptr_t) :: offset, j
1137 type(t) :: tmp(shape (array))
1138
1139 do i = 0, size (array)-1
1140 offset = obtain_offset(i, strides, sizes, byte_stride)
1141 addr = transfer (c_loc (array), addr) + offset
1142 call c_f_pointer (transfer (addr, cptr), ptr)
1143
1144 addr = transfer (c_loc (tmp), addr)
1145 + i * STORAGE_SIZE (array)/NUMERIC_STORAGE_SIZE
1146 call c_f_pointer (transfer (addr, cptr), ptr2)
1147 ptr2 = ptr
1148 end do
1149 call final_rank3 (tmp)
1150 end block
1151 end if
1152 block */
29a7d776
TB
1153
1154static void
1155finalizer_insert_packed_call (gfc_code *block, gfc_finalizer *fini,
9e04287b 1156 gfc_symbol *array, gfc_symbol *byte_stride,
29a7d776 1157 gfc_symbol *idx, gfc_symbol *ptr,
6838c137 1158 gfc_symbol *nelem,
9e04287b
TB
1159 gfc_symbol *strides, gfc_symbol *sizes,
1160 gfc_symbol *idx2, gfc_symbol *offset,
1161 gfc_symbol *is_contiguous, gfc_expr *rank,
29a7d776
TB
1162 gfc_namespace *sub_ns)
1163{
1164 gfc_symbol *tmp_array, *ptr2;
9e04287b 1165 gfc_expr *size_expr, *offset2, *expr;
29a7d776
TB
1166 gfc_namespace *ns;
1167 gfc_iterator *iter;
9e04287b 1168 gfc_code *block2;
29a7d776
TB
1169 int i;
1170
11e5274a 1171 block->next = gfc_get_code (EXEC_IF);
29a7d776 1172 block = block->next;
29a7d776 1173
11e5274a 1174 block->block = gfc_get_code (EXEC_IF);
29a7d776 1175 block = block->block;
29a7d776
TB
1176
1177 /* size_expr = STORAGE_SIZE (...) / NUMERIC_STORAGE_SIZE. */
1178 size_expr = gfc_get_expr ();
1179 size_expr->where = gfc_current_locus;
1180 size_expr->expr_type = EXPR_OP;
1181 size_expr->value.op.op = INTRINSIC_DIVIDE;
1182
1183 /* STORAGE_SIZE (array,kind=c_intptr_t). */
6838c137
TB
1184 size_expr->value.op.op1
1185 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_STORAGE_SIZE,
1186 "storage_size", gfc_current_locus, 2,
cbde6c0f 1187 gfc_lval_expr_from_sym (array),
6838c137 1188 gfc_get_int_expr (gfc_index_integer_kind,
cbde6c0f 1189 NULL, 0));
29a7d776
TB
1190
1191 /* NUMERIC_STORAGE_SIZE. */
1192 size_expr->value.op.op2 = gfc_get_int_expr (gfc_index_integer_kind, NULL,
1193 gfc_character_storage_size);
1194 size_expr->value.op.op1->ts = size_expr->value.op.op2->ts;
1195 size_expr->ts = size_expr->value.op.op1->ts;
1196
9e04287b
TB
1197 /* IF condition: (stride == size_expr
1198 && ((fini's as->ASSUMED_SIZE && !fini's attr.contiguous)
1199 || is_contiguous)
1200 || 0 == size_expr. */
29a7d776 1201 block->expr1 = gfc_get_expr ();
29a7d776 1202 block->expr1->ts.type = BT_LOGICAL;
9e04287b 1203 block->expr1->ts.kind = gfc_default_logical_kind;
29a7d776
TB
1204 block->expr1->expr_type = EXPR_OP;
1205 block->expr1->where = gfc_current_locus;
1206
1207 block->expr1->value.op.op = INTRINSIC_OR;
1208
9e04287b
TB
1209 /* byte_stride == size_expr */
1210 expr = gfc_get_expr ();
1211 expr->ts.type = BT_LOGICAL;
1212 expr->ts.kind = gfc_default_logical_kind;
1213 expr->expr_type = EXPR_OP;
1214 expr->where = gfc_current_locus;
1215 expr->value.op.op = INTRINSIC_EQ;
1216 expr->value.op.op1
1217 = gfc_lval_expr_from_sym (byte_stride);
1218 expr->value.op.op2 = size_expr;
1219
cbde6c0f 1220 /* If strides aren't allowed (not assumed shape or CONTIGUOUS),
9e04287b 1221 add is_contiguous check. */
cbde6c0f 1222
9e04287b
TB
1223 if (fini->proc_tree->n.sym->formal->sym->as->type != AS_ASSUMED_SHAPE
1224 || fini->proc_tree->n.sym->formal->sym->attr.contiguous)
1225 {
1226 gfc_expr *expr2;
1227 expr2 = gfc_get_expr ();
1228 expr2->ts.type = BT_LOGICAL;
1229 expr2->ts.kind = gfc_default_logical_kind;
1230 expr2->expr_type = EXPR_OP;
1231 expr2->where = gfc_current_locus;
1232 expr2->value.op.op = INTRINSIC_AND;
1233 expr2->value.op.op1 = expr;
1234 expr2->value.op.op2 = gfc_lval_expr_from_sym (is_contiguous);
1235 expr = expr2;
1236 }
1237
1238 block->expr1->value.op.op1 = expr;
29a7d776
TB
1239
1240 /* 0 == size_expr */
1241 block->expr1->value.op.op2 = gfc_get_expr ();
29a7d776 1242 block->expr1->value.op.op2->ts.type = BT_LOGICAL;
9e04287b 1243 block->expr1->value.op.op2->ts.kind = gfc_default_logical_kind;
29a7d776
TB
1244 block->expr1->value.op.op2->expr_type = EXPR_OP;
1245 block->expr1->value.op.op2->where = gfc_current_locus;
1246 block->expr1->value.op.op2->value.op.op = INTRINSIC_EQ;
1247 block->expr1->value.op.op2->value.op.op1 =
1248 gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1249 block->expr1->value.op.op2->value.op.op2 = gfc_copy_expr (size_expr);
1250
1251 /* IF body: call final subroutine. */
11e5274a 1252 block->next = gfc_get_code (EXEC_CALL);
29a7d776
TB
1253 block->next->symtree = fini->proc_tree;
1254 block->next->resolved_sym = fini->proc_tree->n.sym;
1255 block->next->ext.actual = gfc_get_actual_arglist ();
1256 block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
1257
1258 /* ELSE. */
1259
11e5274a 1260 block->block = gfc_get_code (EXEC_IF);
29a7d776 1261 block = block->block;
29a7d776 1262
11e5274a
JW
1263 /* BLOCK ... END BLOCK. */
1264 block->next = gfc_get_code (EXEC_BLOCK);
29a7d776
TB
1265 block = block->next;
1266
29a7d776
TB
1267 ns = gfc_build_block_ns (sub_ns);
1268 block->ext.block.ns = ns;
1269 block->ext.block.assoc = NULL;
1270
1271 gfc_get_symbol ("ptr2", ns, &ptr2);
1272 ptr2->ts.type = BT_DERIVED;
1273 ptr2->ts.u.derived = array->ts.u.derived;
1274 ptr2->attr.flavor = FL_VARIABLE;
1275 ptr2->attr.pointer = 1;
1276 ptr2->attr.artificial = 1;
1277 gfc_set_sym_referenced (ptr2);
1278 gfc_commit_symbol (ptr2);
1279
1280 gfc_get_symbol ("tmp_array", ns, &tmp_array);
1281 tmp_array->ts.type = BT_DERIVED;
1282 tmp_array->ts.u.derived = array->ts.u.derived;
1283 tmp_array->attr.flavor = FL_VARIABLE;
29a7d776
TB
1284 tmp_array->attr.dimension = 1;
1285 tmp_array->attr.artificial = 1;
1286 tmp_array->as = gfc_get_array_spec();
1287 tmp_array->attr.intent = INTENT_INOUT;
1288 tmp_array->as->type = AS_EXPLICIT;
1289 tmp_array->as->rank = fini->proc_tree->n.sym->formal->sym->as->rank;
1290
1291 for (i = 0; i < tmp_array->as->rank; i++)
1292 {
1293 gfc_expr *shape_expr;
1294 tmp_array->as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind,
1295 NULL, 1);
cbde6c0f 1296 /* SIZE (array, dim=i+1, kind=gfc_index_integer_kind). */
6838c137
TB
1297 shape_expr
1298 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_SIZE, "size",
1299 gfc_current_locus, 3,
1300 gfc_lval_expr_from_sym (array),
1301 gfc_get_int_expr (gfc_default_integer_kind,
1302 NULL, i+1),
1303 gfc_get_int_expr (gfc_default_integer_kind,
cbde6c0f
TB
1304 NULL,
1305 gfc_index_integer_kind));
1306 shape_expr->ts.kind = gfc_index_integer_kind;
29a7d776
TB
1307 tmp_array->as->upper[i] = shape_expr;
1308 }
1309 gfc_set_sym_referenced (tmp_array);
1310 gfc_commit_symbol (tmp_array);
1311
1312 /* Create loop. */
1313 iter = gfc_get_iterator ();
1314 iter->var = gfc_lval_expr_from_sym (idx);
1315 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1316 iter->end = gfc_lval_expr_from_sym (nelem);
1317 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1318
11e5274a 1319 block = gfc_get_code (EXEC_DO);
29a7d776 1320 ns->code = block;
29a7d776 1321 block->ext.iterator = iter;
11e5274a 1322 block->block = gfc_get_code (EXEC_DO);
29a7d776 1323
9e04287b
TB
1324 /* Offset calculation for the new array: idx * size of type (in bytes). */
1325 offset2 = gfc_get_expr ();
9e04287b
TB
1326 offset2->expr_type = EXPR_OP;
1327 offset2->value.op.op = INTRINSIC_TIMES;
1328 offset2->value.op.op1 = gfc_lval_expr_from_sym (idx);
1329 offset2->value.op.op2 = gfc_copy_expr (size_expr);
1330 offset2->ts = byte_stride->ts;
1331
1332 /* Offset calculation of "array". */
1333 block2 = finalization_get_offset (idx, idx2, offset, strides, sizes,
1334 byte_stride, rank, block->block, sub_ns);
1335
29a7d776
TB
1336 /* Create code for
1337 CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
1338 + idx * stride, c_ptr), ptr). */
9e04287b
TB
1339 block2->next = finalization_scalarizer (array, ptr,
1340 gfc_lval_expr_from_sym (offset),
1341 sub_ns);
1342 block2 = block2->next;
1343 block2->next = finalization_scalarizer (tmp_array, ptr2, offset2, sub_ns);
cbde6c0f 1344 block2 = block2->next;
9e04287b 1345
29a7d776 1346 /* ptr2 = ptr. */
11e5274a 1347 block2->next = gfc_get_code (EXEC_ASSIGN);
cbde6c0f 1348 block2 = block2->next;
cbde6c0f
TB
1349 block2->expr1 = gfc_lval_expr_from_sym (ptr2);
1350 block2->expr2 = gfc_lval_expr_from_sym (ptr);
29a7d776 1351
9e04287b 1352 /* Call now the user's final subroutine. */
11e5274a 1353 block->next = gfc_get_code (EXEC_CALL);
29a7d776 1354 block = block->next;
29a7d776
TB
1355 block->symtree = fini->proc_tree;
1356 block->resolved_sym = fini->proc_tree->n.sym;
1357 block->ext.actual = gfc_get_actual_arglist ();
1358 block->ext.actual->expr = gfc_lval_expr_from_sym (tmp_array);
1359
1360 if (fini->proc_tree->n.sym->formal->sym->attr.intent == INTENT_IN)
1361 return;
1362
1363 /* Copy back. */
1364
1365 /* Loop. */
1366 iter = gfc_get_iterator ();
1367 iter->var = gfc_lval_expr_from_sym (idx);
1368 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1369 iter->end = gfc_lval_expr_from_sym (nelem);
1370 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1371
11e5274a 1372 block->next = gfc_get_code (EXEC_DO);
29a7d776 1373 block = block->next;
29a7d776 1374 block->ext.iterator = iter;
11e5274a 1375 block->block = gfc_get_code (EXEC_DO);
29a7d776 1376
9e04287b
TB
1377 /* Offset calculation of "array". */
1378 block2 = finalization_get_offset (idx, idx2, offset, strides, sizes,
1379 byte_stride, rank, block->block, sub_ns);
1380
29a7d776
TB
1381 /* Create code for
1382 CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
9e04287b
TB
1383 + offset, c_ptr), ptr). */
1384 block2->next = finalization_scalarizer (array, ptr,
1385 gfc_lval_expr_from_sym (offset),
1386 sub_ns);
1387 block2 = block2->next;
cbde6c0f
TB
1388 block2->next = finalization_scalarizer (tmp_array, ptr2,
1389 gfc_copy_expr (offset2), sub_ns);
9e04287b
TB
1390 block2 = block2->next;
1391
29a7d776 1392 /* ptr = ptr2. */
11e5274a 1393 block2->next = gfc_get_code (EXEC_ASSIGN);
9e04287b
TB
1394 block2->next->expr1 = gfc_lval_expr_from_sym (ptr);
1395 block2->next->expr2 = gfc_lval_expr_from_sym (ptr2);
29a7d776
TB
1396}
1397
1398
8e54f139
TB
1399/* Generate the finalization/polymorphic freeing wrapper subroutine for the
1400 derived type "derived". The function first calls the approriate FINAL
1401 subroutine, then it DEALLOCATEs (finalizes/frees) the allocatable
1402 components (but not the inherited ones). Last, it calls the wrapper
1403 subroutine of the parent. The generated wrapper procedure takes as argument
1404 an assumed-rank array.
1405 If neither allocatable components nor FINAL subroutines exists, the vtab
29a7d776
TB
1406 will contain a NULL pointer.
1407 The generated function has the form
1408 _final(assumed-rank array, stride, skip_corarray)
1409 where the array has to be contiguous (except of the lowest dimension). The
1410 stride (in bytes) is used to allow different sizes for ancestor types by
1411 skipping over the additionally added components in the scalarizer. If
1412 "fini_coarray" is false, coarray components are not finalized to allow for
1413 the correct semantic with intrinsic assignment. */
8e54f139
TB
1414
1415static void
1416generate_finalization_wrapper (gfc_symbol *derived, gfc_namespace *ns,
1417 const char *tname, gfc_component *vtab_final)
1418{
9e04287b
TB
1419 gfc_symbol *final, *array, *fini_coarray, *byte_stride, *sizes, *strides;
1420 gfc_symbol *ptr = NULL, *idx, *idx2, *is_contiguous, *offset, *nelem;
8e54f139
TB
1421 gfc_component *comp;
1422 gfc_namespace *sub_ns;
9e04287b 1423 gfc_code *last_code, *block;
8e54f139
TB
1424 char name[GFC_MAX_SYMBOL_LEN+1];
1425 bool finalizable_comp = false;
29a7d776 1426 bool expr_null_wrapper = false;
9e04287b
TB
1427 gfc_expr *ancestor_wrapper = NULL, *rank;
1428 gfc_iterator *iter;
8e54f139 1429
7017a7a9
TB
1430 if (derived->attr.unlimited_polymorphic)
1431 {
1432 vtab_final->initializer = gfc_get_null_expr (NULL);
1433 return;
1434 }
1435
8e54f139
TB
1436 /* Search for the ancestor's finalizers. */
1437 if (derived->attr.extension && derived->components
1438 && (!derived->components->ts.u.derived->attr.abstract
1439 || has_finalizer_component (derived)))
1440 {
1441 gfc_symbol *vtab;
1442 gfc_component *comp;
1443
1444 vtab = gfc_find_derived_vtab (derived->components->ts.u.derived);
1445 for (comp = vtab->ts.u.derived->components; comp; comp = comp->next)
1446 if (comp->name[0] == '_' && comp->name[1] == 'f')
1447 {
1448 ancestor_wrapper = comp->initializer;
1449 break;
1450 }
1451 }
1452
29a7d776
TB
1453 /* No wrapper of the ancestor and no own FINAL subroutines and allocatable
1454 components: Return a NULL() expression; we defer this a bit to have have
1455 an interface declaration. */
8e54f139
TB
1456 if ((!ancestor_wrapper || ancestor_wrapper->expr_type == EXPR_NULL)
1457 && !derived->attr.alloc_comp
1458 && (!derived->f2k_derived || !derived->f2k_derived->finalizers)
1459 && !has_finalizer_component (derived))
29a7d776
TB
1460 expr_null_wrapper = true;
1461 else
1462 /* Check whether there are new allocatable components. */
1463 for (comp = derived->components; comp; comp = comp->next)
1464 {
1465 if (comp == derived->components && derived->attr.extension
1466 && ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
8e54f139
TB
1467 continue;
1468
29a7d776
TB
1469 if (comp->ts.type != BT_CLASS && !comp->attr.pointer
1470 && (comp->attr.allocatable
1471 || (comp->ts.type == BT_DERIVED
1472 && (comp->ts.u.derived->attr.alloc_comp
1473 || has_finalizer_component (comp->ts.u.derived)
1474 || (comp->ts.u.derived->f2k_derived
1475 && comp->ts.u.derived->f2k_derived->finalizers)))))
1476 finalizable_comp = true;
1477 else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
1478 && CLASS_DATA (comp)->attr.allocatable)
1479 finalizable_comp = true;
1480 }
8e54f139
TB
1481
1482 /* If there is no new finalizer and no new allocatable, return with
1483 an expr to the ancestor's one. */
29a7d776
TB
1484 if (!expr_null_wrapper && !finalizable_comp
1485 && (!derived->f2k_derived || !derived->f2k_derived->finalizers))
8e54f139 1486 {
29a7d776
TB
1487 gcc_assert (ancestor_wrapper && ancestor_wrapper->ref == NULL
1488 && ancestor_wrapper->expr_type == EXPR_VARIABLE);
8e54f139 1489 vtab_final->initializer = gfc_copy_expr (ancestor_wrapper);
29a7d776 1490 vtab_final->ts.interface = vtab_final->initializer->symtree->n.sym;
8e54f139
TB
1491 return;
1492 }
1493
1494 /* We now create a wrapper, which does the following:
1495 1. Call the suitable finalization subroutine for this type
1496 2. Loop over all noninherited allocatable components and noninherited
1497 components with allocatable components and DEALLOCATE those; this will
1498 take care of finalizers, coarray deregistering and allocatable
1499 nested components.
1500 3. Call the ancestor's finalizer. */
1501
1502 /* Declare the wrapper function; it takes an assumed-rank array
29a7d776 1503 and a VALUE logical as arguments. */
8e54f139
TB
1504
1505 /* Set up the namespace. */
1506 sub_ns = gfc_get_namespace (ns, 0);
1507 sub_ns->sibling = ns->contained;
29a7d776
TB
1508 if (!expr_null_wrapper)
1509 ns->contained = sub_ns;
8e54f139
TB
1510 sub_ns->resolved = 1;
1511
1512 /* Set up the procedure symbol. */
1513 sprintf (name, "__final_%s", tname);
1514 gfc_get_symbol (name, sub_ns, &final);
1515 sub_ns->proc_name = final;
1516 final->attr.flavor = FL_PROCEDURE;
29a7d776
TB
1517 final->attr.function = 1;
1518 final->attr.pure = 0;
1519 final->result = final;
1520 final->ts.type = BT_INTEGER;
1521 final->ts.kind = 4;
8e54f139 1522 final->attr.artificial = 1;
29a7d776 1523 final->attr.if_source = expr_null_wrapper ? IFSRC_IFBODY : IFSRC_DECL;
8e54f139
TB
1524 if (ns->proc_name->attr.flavor == FL_MODULE)
1525 final->module = ns->proc_name->name;
1526 gfc_set_sym_referenced (final);
29a7d776 1527 gfc_commit_symbol (final);
8e54f139
TB
1528
1529 /* Set up formal argument. */
1530 gfc_get_symbol ("array", sub_ns, &array);
1531 array->ts.type = BT_DERIVED;
1532 array->ts.u.derived = derived;
1533 array->attr.flavor = FL_VARIABLE;
1534 array->attr.dummy = 1;
1535 array->attr.contiguous = 1;
1536 array->attr.dimension = 1;
1537 array->attr.artificial = 1;
1538 array->as = gfc_get_array_spec();
1539 array->as->type = AS_ASSUMED_RANK;
1540 array->as->rank = -1;
1541 array->attr.intent = INTENT_INOUT;
1542 gfc_set_sym_referenced (array);
1543 final->formal = gfc_get_formal_arglist ();
1544 final->formal->sym = array;
1545 gfc_commit_symbol (array);
1546
29a7d776 1547 /* Set up formal argument. */
9e04287b
TB
1548 gfc_get_symbol ("byte_stride", sub_ns, &byte_stride);
1549 byte_stride->ts.type = BT_INTEGER;
1550 byte_stride->ts.kind = gfc_index_integer_kind;
1551 byte_stride->attr.flavor = FL_VARIABLE;
1552 byte_stride->attr.dummy = 1;
1553 byte_stride->attr.value = 1;
1554 byte_stride->attr.artificial = 1;
1555 gfc_set_sym_referenced (byte_stride);
29a7d776 1556 final->formal->next = gfc_get_formal_arglist ();
9e04287b
TB
1557 final->formal->next->sym = byte_stride;
1558 gfc_commit_symbol (byte_stride);
29a7d776
TB
1559
1560 /* Set up formal argument. */
1561 gfc_get_symbol ("fini_coarray", sub_ns, &fini_coarray);
1562 fini_coarray->ts.type = BT_LOGICAL;
9e04287b 1563 fini_coarray->ts.kind = 1;
29a7d776
TB
1564 fini_coarray->attr.flavor = FL_VARIABLE;
1565 fini_coarray->attr.dummy = 1;
1566 fini_coarray->attr.value = 1;
1567 fini_coarray->attr.artificial = 1;
1568 gfc_set_sym_referenced (fini_coarray);
1569 final->formal->next->next = gfc_get_formal_arglist ();
1570 final->formal->next->next->sym = fini_coarray;
1571 gfc_commit_symbol (fini_coarray);
1572
1573 /* Return with a NULL() expression but with an interface which has
1574 the formal arguments. */
1575 if (expr_null_wrapper)
1576 {
1577 vtab_final->initializer = gfc_get_null_expr (NULL);
1578 vtab_final->ts.interface = final;
1579 return;
1580 }
1581
9e04287b
TB
1582 /* Local variables. */
1583
1584 gfc_get_symbol ("idx", sub_ns, &idx);
1585 idx->ts.type = BT_INTEGER;
1586 idx->ts.kind = gfc_index_integer_kind;
1587 idx->attr.flavor = FL_VARIABLE;
1588 idx->attr.artificial = 1;
1589 gfc_set_sym_referenced (idx);
1590 gfc_commit_symbol (idx);
1591
1592 gfc_get_symbol ("idx2", sub_ns, &idx2);
1593 idx2->ts.type = BT_INTEGER;
1594 idx2->ts.kind = gfc_index_integer_kind;
1595 idx2->attr.flavor = FL_VARIABLE;
1596 idx2->attr.artificial = 1;
1597 gfc_set_sym_referenced (idx2);
1598 gfc_commit_symbol (idx2);
1599
1600 gfc_get_symbol ("offset", sub_ns, &offset);
1601 offset->ts.type = BT_INTEGER;
1602 offset->ts.kind = gfc_index_integer_kind;
1603 offset->attr.flavor = FL_VARIABLE;
1604 offset->attr.artificial = 1;
1605 gfc_set_sym_referenced (offset);
1606 gfc_commit_symbol (offset);
1607
1608 /* Create RANK expression. */
6838c137
TB
1609 rank = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_RANK, "rank",
1610 gfc_current_locus, 1,
1611 gfc_lval_expr_from_sym (array));
16023efc
TB
1612 if (rank->ts.kind != idx->ts.kind)
1613 gfc_convert_type_warn (rank, &idx->ts, 2, 0);
9e04287b
TB
1614
1615 /* Create is_contiguous variable. */
1616 gfc_get_symbol ("is_contiguous", sub_ns, &is_contiguous);
1617 is_contiguous->ts.type = BT_LOGICAL;
1618 is_contiguous->ts.kind = gfc_default_logical_kind;
1619 is_contiguous->attr.flavor = FL_VARIABLE;
1620 is_contiguous->attr.artificial = 1;
1621 gfc_set_sym_referenced (is_contiguous);
1622 gfc_commit_symbol (is_contiguous);
1623
1624 /* Create "sizes(0..rank)" variable, which contains the multiplied
1625 up extent of the dimensions, i.e. sizes(0) = 1, sizes(1) = extent(dim=1),
1626 sizes(2) = sizes(1) * extent(dim=2) etc. */
1627 gfc_get_symbol ("sizes", sub_ns, &sizes);
1628 sizes->ts.type = BT_INTEGER;
1629 sizes->ts.kind = gfc_index_integer_kind;
1630 sizes->attr.flavor = FL_VARIABLE;
1631 sizes->attr.dimension = 1;
1632 sizes->attr.artificial = 1;
1633 sizes->as = gfc_get_array_spec();
1634 sizes->attr.intent = INTENT_INOUT;
1635 sizes->as->type = AS_EXPLICIT;
1636 sizes->as->rank = 1;
1637 sizes->as->lower[0] = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1638 sizes->as->upper[0] = gfc_copy_expr (rank);
1639 gfc_set_sym_referenced (sizes);
1640 gfc_commit_symbol (sizes);
1641
1642 /* Create "strides(1..rank)" variable, which contains the strides per
1643 dimension. */
1644 gfc_get_symbol ("strides", sub_ns, &strides);
1645 strides->ts.type = BT_INTEGER;
1646 strides->ts.kind = gfc_index_integer_kind;
1647 strides->attr.flavor = FL_VARIABLE;
1648 strides->attr.dimension = 1;
1649 strides->attr.artificial = 1;
1650 strides->as = gfc_get_array_spec();
1651 strides->attr.intent = INTENT_INOUT;
1652 strides->as->type = AS_EXPLICIT;
1653 strides->as->rank = 1;
1654 strides->as->lower[0] = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1655 strides->as->upper[0] = gfc_copy_expr (rank);
1656 gfc_set_sym_referenced (strides);
1657 gfc_commit_symbol (strides);
1658
29a7d776
TB
1659
1660 /* Set return value to 0. */
11e5274a 1661 last_code = gfc_get_code (EXEC_ASSIGN);
29a7d776
TB
1662 last_code->expr1 = gfc_lval_expr_from_sym (final);
1663 last_code->expr2 = gfc_get_int_expr (4, NULL, 0);
1664 sub_ns->code = last_code;
1665
9e04287b 1666 /* Set: is_contiguous = .true. */
11e5274a 1667 last_code->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1668 last_code = last_code->next;
9e04287b
TB
1669 last_code->expr1 = gfc_lval_expr_from_sym (is_contiguous);
1670 last_code->expr2 = gfc_get_logical_expr (gfc_default_logical_kind,
1671 &gfc_current_locus, true);
1672
1673 /* Set: sizes(0) = 1. */
11e5274a 1674 last_code->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1675 last_code = last_code->next;
9e04287b
TB
1676 last_code->expr1 = gfc_lval_expr_from_sym (sizes);
1677 last_code->expr1->ref = gfc_get_ref ();
1678 last_code->expr1->ref->type = REF_ARRAY;
1679 last_code->expr1->ref->u.ar.type = AR_ELEMENT;
1680 last_code->expr1->ref->u.ar.dimen = 1;
1681 last_code->expr1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1682 last_code->expr1->ref->u.ar.start[0]
1683 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1684 last_code->expr1->ref->u.ar.as = sizes->as;
1685 last_code->expr2 = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1);
1686
1687 /* Create:
1688 DO idx = 1, rank
1689 strides(idx) = _F._stride (array, dim=idx)
1690 sizes(idx) = sizes(i-1) * size(array, dim=idx, kind=index_kind)
524af0d6 1691 if (strides (idx) /= sizes(i-1)) is_contiguous = .false.
9e04287b
TB
1692 END DO. */
1693
1694 /* Create loop. */
1695 iter = gfc_get_iterator ();
1696 iter->var = gfc_lval_expr_from_sym (idx);
1697 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1698 iter->end = gfc_copy_expr (rank);
1699 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
11e5274a 1700 last_code->next = gfc_get_code (EXEC_DO);
9e04287b 1701 last_code = last_code->next;
9e04287b 1702 last_code->ext.iterator = iter;
11e5274a 1703 last_code->block = gfc_get_code (EXEC_DO);
9e04287b
TB
1704
1705 /* strides(idx) = _F._stride(array,dim=idx). */
11e5274a 1706 last_code->block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1707 block = last_code->block->next;
9e04287b
TB
1708
1709 block->expr1 = gfc_lval_expr_from_sym (strides);
1710 block->expr1->ref = gfc_get_ref ();
1711 block->expr1->ref->type = REF_ARRAY;
1712 block->expr1->ref->u.ar.type = AR_ELEMENT;
1713 block->expr1->ref->u.ar.dimen = 1;
1714 block->expr1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1715 block->expr1->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx);
1716 block->expr1->ref->u.ar.as = strides->as;
1717
6838c137
TB
1718 block->expr2 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_STRIDE, "stride",
1719 gfc_current_locus, 2,
1720 gfc_lval_expr_from_sym (array),
1721 gfc_lval_expr_from_sym (idx));
9e04287b
TB
1722
1723 /* sizes(idx) = sizes(idx-1) * size(array,dim=idx, kind=index_kind). */
11e5274a 1724 block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1725 block = block->next;
9e04287b
TB
1726
1727 /* sizes(idx) = ... */
1728 block->expr1 = gfc_lval_expr_from_sym (sizes);
1729 block->expr1->ref = gfc_get_ref ();
1730 block->expr1->ref->type = REF_ARRAY;
1731 block->expr1->ref->u.ar.type = AR_ELEMENT;
1732 block->expr1->ref->u.ar.dimen = 1;
1733 block->expr1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1734 block->expr1->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx);
1735 block->expr1->ref->u.ar.as = sizes->as;
1736
1737 block->expr2 = gfc_get_expr ();
1738 block->expr2->expr_type = EXPR_OP;
1739 block->expr2->value.op.op = INTRINSIC_TIMES;
1740
1741 /* sizes(idx-1). */
1742 block->expr2->value.op.op1 = gfc_lval_expr_from_sym (sizes);
1743 block->expr2->value.op.op1->ref = gfc_get_ref ();
1744 block->expr2->value.op.op1->ref->type = REF_ARRAY;
1745 block->expr2->value.op.op1->ref->u.ar.as = sizes->as;
1746 block->expr2->value.op.op1->ref->u.ar.type = AR_ELEMENT;
1747 block->expr2->value.op.op1->ref->u.ar.dimen = 1;
1748 block->expr2->value.op.op1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1749 block->expr2->value.op.op1->ref->u.ar.start[0] = gfc_get_expr ();
1750 block->expr2->value.op.op1->ref->u.ar.start[0]->expr_type = EXPR_OP;
1751 block->expr2->value.op.op1->ref->u.ar.start[0]->value.op.op = INTRINSIC_MINUS;
1752 block->expr2->value.op.op1->ref->u.ar.start[0]->value.op.op1
1753 = gfc_lval_expr_from_sym (idx);
1754 block->expr2->value.op.op1->ref->u.ar.start[0]->value.op.op2
1755 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1756 block->expr2->value.op.op1->ref->u.ar.start[0]->ts
1757 = block->expr2->value.op.op1->ref->u.ar.start[0]->value.op.op1->ts;
1758
1759 /* size(array, dim=idx, kind=index_kind). */
6838c137
TB
1760 block->expr2->value.op.op2
1761 = gfc_build_intrinsic_call (sub_ns, GFC_ISYM_SIZE, "size",
1762 gfc_current_locus, 3,
1763 gfc_lval_expr_from_sym (array),
1764 gfc_lval_expr_from_sym (idx),
1765 gfc_get_int_expr (gfc_index_integer_kind,
cbde6c0f
TB
1766 NULL,
1767 gfc_index_integer_kind));
1768 block->expr2->value.op.op2->ts.kind = gfc_index_integer_kind;
9e04287b
TB
1769 block->expr2->ts = idx->ts;
1770
524af0d6 1771 /* if (strides (idx) /= sizes(idx-1)) is_contiguous = .false. */
11e5274a 1772 block->next = gfc_get_code (EXEC_IF);
9e04287b 1773 block = block->next;
9e04287b 1774
11e5274a 1775 block->block = gfc_get_code (EXEC_IF);
9e04287b 1776 block = block->block;
9e04287b
TB
1777
1778 /* if condition: strides(idx) /= sizes(idx-1). */
1779 block->expr1 = gfc_get_expr ();
1780 block->expr1->ts.type = BT_LOGICAL;
1781 block->expr1->ts.kind = gfc_default_logical_kind;
1782 block->expr1->expr_type = EXPR_OP;
1783 block->expr1->where = gfc_current_locus;
1784 block->expr1->value.op.op = INTRINSIC_NE;
1785
1786 block->expr1->value.op.op1 = gfc_lval_expr_from_sym (strides);
1787 block->expr1->value.op.op1->ref = gfc_get_ref ();
1788 block->expr1->value.op.op1->ref->type = REF_ARRAY;
1789 block->expr1->value.op.op1->ref->u.ar.type = AR_ELEMENT;
1790 block->expr1->value.op.op1->ref->u.ar.dimen = 1;
1791 block->expr1->value.op.op1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1792 block->expr1->value.op.op1->ref->u.ar.start[0] = gfc_lval_expr_from_sym (idx);
1793 block->expr1->value.op.op1->ref->u.ar.as = strides->as;
1794
1795 block->expr1->value.op.op2 = gfc_lval_expr_from_sym (sizes);
1796 block->expr1->value.op.op2->ref = gfc_get_ref ();
1797 block->expr1->value.op.op2->ref->type = REF_ARRAY;
1798 block->expr1->value.op.op2->ref->u.ar.as = sizes->as;
1799 block->expr1->value.op.op2->ref->u.ar.type = AR_ELEMENT;
1800 block->expr1->value.op.op2->ref->u.ar.dimen = 1;
1801 block->expr1->value.op.op2->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1802 block->expr1->value.op.op2->ref->u.ar.start[0] = gfc_get_expr ();
1803 block->expr1->value.op.op2->ref->u.ar.start[0]->expr_type = EXPR_OP;
1804 block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op = INTRINSIC_MINUS;
1805 block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op1
1806 = gfc_lval_expr_from_sym (idx);
1807 block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op2
1808 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1809 block->expr1->value.op.op2->ref->u.ar.start[0]->ts
1810 = block->expr1->value.op.op2->ref->u.ar.start[0]->value.op.op1->ts;
1811
1812 /* if body: is_contiguous = .false. */
11e5274a 1813 block->next = gfc_get_code (EXEC_ASSIGN);
9e04287b 1814 block = block->next;
9e04287b
TB
1815 block->expr1 = gfc_lval_expr_from_sym (is_contiguous);
1816 block->expr2 = gfc_get_logical_expr (gfc_default_logical_kind,
1817 &gfc_current_locus, false);
1818
8e54f139
TB
1819 /* Obtain the size (number of elements) of "array" MINUS ONE,
1820 which is used in the scalarization. */
1821 gfc_get_symbol ("nelem", sub_ns, &nelem);
1822 nelem->ts.type = BT_INTEGER;
1823 nelem->ts.kind = gfc_index_integer_kind;
1824 nelem->attr.flavor = FL_VARIABLE;
1825 nelem->attr.artificial = 1;
1826 gfc_set_sym_referenced (nelem);
1827 gfc_commit_symbol (nelem);
1828
9e04287b 1829 /* nelem = sizes (rank) - 1. */
11e5274a 1830 last_code->next = gfc_get_code (EXEC_ASSIGN);
29a7d776 1831 last_code = last_code->next;
8e54f139
TB
1832
1833 last_code->expr1 = gfc_lval_expr_from_sym (nelem);
1834
1835 last_code->expr2 = gfc_get_expr ();
1836 last_code->expr2->expr_type = EXPR_OP;
1837 last_code->expr2->value.op.op = INTRINSIC_MINUS;
1838 last_code->expr2->value.op.op2
1839 = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
1840 last_code->expr2->ts = last_code->expr2->value.op.op2->ts;
1841
9e04287b
TB
1842 last_code->expr2->value.op.op1 = gfc_lval_expr_from_sym (sizes);
1843 last_code->expr2->value.op.op1->ref = gfc_get_ref ();
1844 last_code->expr2->value.op.op1->ref->type = REF_ARRAY;
1845 last_code->expr2->value.op.op1->ref->u.ar.type = AR_ELEMENT;
1846 last_code->expr2->value.op.op1->ref->u.ar.dimen = 1;
1847 last_code->expr2->value.op.op1->ref->u.ar.dimen_type[0] = DIMEN_ELEMENT;
1848 last_code->expr2->value.op.op1->ref->u.ar.start[0] = gfc_copy_expr (rank);
1849 last_code->expr2->value.op.op1->ref->u.ar.as = sizes->as;
8e54f139
TB
1850
1851 /* Call final subroutines. We now generate code like:
1852 use iso_c_binding
1853 integer, pointer :: ptr
1854 type(c_ptr) :: cptr
1855 integer(c_intptr_t) :: i, addr
1856
1857 select case (rank (array))
1858 case (3)
29a7d776 1859 ! If needed, the array is packed
8e54f139
TB
1860 call final_rank3 (array)
1861 case default:
1862 do i = 0, size (array)-1
29a7d776 1863 addr = transfer (c_loc (array), addr) + i * stride
8e54f139
TB
1864 call c_f_pointer (transfer (addr, cptr), ptr)
1865 call elemental_final (ptr)
1866 end do
1867 end select */
1868
1869 if (derived->f2k_derived && derived->f2k_derived->finalizers)
1870 {
1871 gfc_finalizer *fini, *fini_elem = NULL;
29a7d776
TB
1872
1873 gfc_get_symbol ("ptr", sub_ns, &ptr);
1874 ptr->ts.type = BT_DERIVED;
1875 ptr->ts.u.derived = derived;
1876 ptr->attr.flavor = FL_VARIABLE;
1877 ptr->attr.pointer = 1;
1878 ptr->attr.artificial = 1;
1879 gfc_set_sym_referenced (ptr);
1880 gfc_commit_symbol (ptr);
1881
8e54f139 1882 /* SELECT CASE (RANK (array)). */
11e5274a 1883 last_code->next = gfc_get_code (EXEC_SELECT);
8e54f139 1884 last_code = last_code->next;
9e04287b
TB
1885 last_code->expr1 = gfc_copy_expr (rank);
1886 block = NULL;
8e54f139
TB
1887
1888 for (fini = derived->f2k_derived->finalizers; fini; fini = fini->next)
1889 {
0ebdf3ae
TB
1890 if (!fini->proc_tree)
1891 fini->proc_tree = gfc_find_sym_in_symtree (fini->proc_sym);
8e54f139
TB
1892 if (fini->proc_tree->n.sym->attr.elemental)
1893 {
1894 fini_elem = fini;
1895 continue;
1896 }
1897
1898 /* CASE (fini_rank). */
1899 if (block)
1900 {
11e5274a 1901 block->block = gfc_get_code (EXEC_SELECT);
8e54f139
TB
1902 block = block->block;
1903 }
1904 else
1905 {
11e5274a 1906 block = gfc_get_code (EXEC_SELECT);
8e54f139
TB
1907 last_code->block = block;
1908 }
8e54f139
TB
1909 block->ext.block.case_list = gfc_get_case ();
1910 block->ext.block.case_list->where = gfc_current_locus;
1911 if (fini->proc_tree->n.sym->formal->sym->attr.dimension)
1912 block->ext.block.case_list->low
1913 = gfc_get_int_expr (gfc_default_integer_kind, NULL,
1914 fini->proc_tree->n.sym->formal->sym->as->rank);
1915 else
1916 block->ext.block.case_list->low
1917 = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
1918 block->ext.block.case_list->high
cbde6c0f 1919 = gfc_copy_expr (block->ext.block.case_list->low);
8e54f139 1920
29a7d776
TB
1921 /* CALL fini_rank (array) - possibly with packing. */
1922 if (fini->proc_tree->n.sym->formal->sym->attr.dimension)
9e04287b 1923 finalizer_insert_packed_call (block, fini, array, byte_stride,
6838c137 1924 idx, ptr, nelem, strides,
9e04287b
TB
1925 sizes, idx2, offset, is_contiguous,
1926 rank, sub_ns);
29a7d776
TB
1927 else
1928 {
11e5274a 1929 block->next = gfc_get_code (EXEC_CALL);
29a7d776
TB
1930 block->next->symtree = fini->proc_tree;
1931 block->next->resolved_sym = fini->proc_tree->n.sym;
1932 block->next->ext.actual = gfc_get_actual_arglist ();
1933 block->next->ext.actual->expr = gfc_lval_expr_from_sym (array);
1934 }
8e54f139
TB
1935 }
1936
1937 /* Elemental call - scalarized. */
1938 if (fini_elem)
1939 {
8e54f139
TB
1940 /* CASE DEFAULT. */
1941 if (block)
1942 {
11e5274a 1943 block->block = gfc_get_code (EXEC_SELECT);
8e54f139
TB
1944 block = block->block;
1945 }
1946 else
1947 {
11e5274a 1948 block = gfc_get_code (EXEC_SELECT);
8e54f139
TB
1949 last_code->block = block;
1950 }
8e54f139
TB
1951 block->ext.block.case_list = gfc_get_case ();
1952
8e54f139
TB
1953 /* Create loop. */
1954 iter = gfc_get_iterator ();
1955 iter->var = gfc_lval_expr_from_sym (idx);
1956 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
1957 iter->end = gfc_lval_expr_from_sym (nelem);
1958 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
11e5274a 1959 block->next = gfc_get_code (EXEC_DO);
8e54f139 1960 block = block->next;
8e54f139 1961 block->ext.iterator = iter;
11e5274a 1962 block->block = gfc_get_code (EXEC_DO);
8e54f139 1963
9e04287b
TB
1964 /* Offset calculation. */
1965 block = finalization_get_offset (idx, idx2, offset, strides, sizes,
1966 byte_stride, rank, block->block,
1967 sub_ns);
1968
8e54f139
TB
1969 /* Create code for
1970 CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
9e04287b
TB
1971 + offset, c_ptr), ptr). */
1972 block->next
1973 = finalization_scalarizer (array, ptr,
1974 gfc_lval_expr_from_sym (offset),
1975 sub_ns);
1976 block = block->next;
8e54f139
TB
1977
1978 /* CALL final_elemental (array). */
11e5274a 1979 block->next = gfc_get_code (EXEC_CALL);
8e54f139 1980 block = block->next;
8e54f139
TB
1981 block->symtree = fini_elem->proc_tree;
1982 block->resolved_sym = fini_elem->proc_sym;
1983 block->ext.actual = gfc_get_actual_arglist ();
1984 block->ext.actual->expr = gfc_lval_expr_from_sym (ptr);
1985 }
1986 }
1987
1988 /* Finalize and deallocate allocatable components. The same manual
1989 scalarization is used as above. */
1990
1991 if (finalizable_comp)
1992 {
1993 gfc_symbol *stat;
1994 gfc_code *block = NULL;
8e54f139
TB
1995
1996 if (!ptr)
1997 {
1998 gfc_get_symbol ("ptr", sub_ns, &ptr);
1999 ptr->ts.type = BT_DERIVED;
2000 ptr->ts.u.derived = derived;
2001 ptr->attr.flavor = FL_VARIABLE;
2002 ptr->attr.pointer = 1;
2003 ptr->attr.artificial = 1;
2004 gfc_set_sym_referenced (ptr);
2005 gfc_commit_symbol (ptr);
2006 }
2007
2008 gfc_get_symbol ("ignore", sub_ns, &stat);
2009 stat->attr.flavor = FL_VARIABLE;
2010 stat->attr.artificial = 1;
2011 stat->ts.type = BT_INTEGER;
2012 stat->ts.kind = gfc_default_integer_kind;
2013 gfc_set_sym_referenced (stat);
2014 gfc_commit_symbol (stat);
2015
2016 /* Create loop. */
2017 iter = gfc_get_iterator ();
2018 iter->var = gfc_lval_expr_from_sym (idx);
2019 iter->start = gfc_get_int_expr (gfc_index_integer_kind, NULL, 0);
2020 iter->end = gfc_lval_expr_from_sym (nelem);
2021 iter->step = gfc_get_int_expr (gfc_index_integer_kind, NULL, 1);
11e5274a 2022 last_code->next = gfc_get_code (EXEC_DO);
8e54f139 2023 last_code = last_code->next;
8e54f139 2024 last_code->ext.iterator = iter;
11e5274a 2025 last_code->block = gfc_get_code (EXEC_DO);
8e54f139 2026
9e04287b
TB
2027 /* Offset calculation. */
2028 block = finalization_get_offset (idx, idx2, offset, strides, sizes,
2029 byte_stride, rank, last_code->block,
2030 sub_ns);
2031
8e54f139
TB
2032 /* Create code for
2033 CALL C_F_POINTER (TRANSFER (TRANSFER (C_LOC (array, cptr), c_intptr)
29a7d776 2034 + idx * stride, c_ptr), ptr). */
9e04287b
TB
2035 block->next = finalization_scalarizer (array, ptr,
2036 gfc_lval_expr_from_sym(offset),
2037 sub_ns);
2038 block = block->next;
8e54f139
TB
2039
2040 for (comp = derived->components; comp; comp = comp->next)
2041 {
2042 if (comp == derived->components && derived->attr.extension
2043 && ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
2044 continue;
2045
2046 finalize_component (gfc_lval_expr_from_sym (ptr), derived, comp,
29a7d776 2047 stat, fini_coarray, &block);
8e54f139
TB
2048 if (!last_code->block->next)
2049 last_code->block->next = block;
2050 }
2051
2052 }
2053
2054 /* Call the finalizer of the ancestor. */
2055 if (ancestor_wrapper && ancestor_wrapper->expr_type != EXPR_NULL)
2056 {
11e5274a 2057 last_code->next = gfc_get_code (EXEC_CALL);
8e54f139 2058 last_code = last_code->next;
8e54f139
TB
2059 last_code->symtree = ancestor_wrapper->symtree;
2060 last_code->resolved_sym = ancestor_wrapper->symtree->n.sym;
2061
2062 last_code->ext.actual = gfc_get_actual_arglist ();
2063 last_code->ext.actual->expr = gfc_lval_expr_from_sym (array);
29a7d776 2064 last_code->ext.actual->next = gfc_get_actual_arglist ();
9e04287b 2065 last_code->ext.actual->next->expr = gfc_lval_expr_from_sym (byte_stride);
29a7d776
TB
2066 last_code->ext.actual->next->next = gfc_get_actual_arglist ();
2067 last_code->ext.actual->next->next->expr
2068 = gfc_lval_expr_from_sym (fini_coarray);
8e54f139
TB
2069 }
2070
9e04287b 2071 gfc_free_expr (rank);
8e54f139
TB
2072 vtab_final->initializer = gfc_lval_expr_from_sym (final);
2073 vtab_final->ts.interface = final;
2074}
2075
2076
88ce8031 2077/* Add procedure pointers for all type-bound procedures to a vtab. */
d15bac21
JW
2078
2079static void
88ce8031 2080add_procs_to_declared_vtab (gfc_symbol *derived, gfc_symbol *vtype)
d15bac21 2081{
d15bac21
JW
2082 gfc_symbol* super_type;
2083
88ce8031 2084 super_type = gfc_get_derived_super_type (derived);
d15bac21 2085
88ce8031 2086 if (super_type && (super_type != derived))
d15bac21 2087 {
88ce8031
JW
2088 /* Make sure that the PPCs appear in the same order as in the parent. */
2089 copy_vtab_proc_comps (super_type, vtype);
1d0134b3 2090 /* Only needed to get the PPC initializers right. */
88ce8031
JW
2091 add_procs_to_declared_vtab (super_type, vtype);
2092 }
d15bac21 2093
88ce8031
JW
2094 if (derived->f2k_derived && derived->f2k_derived->tb_sym_root)
2095 add_procs_to_declared_vtab1 (derived->f2k_derived->tb_sym_root, vtype);
d15bac21 2096
88ce8031
JW
2097 if (derived->f2k_derived && derived->f2k_derived->tb_uop_root)
2098 add_procs_to_declared_vtab1 (derived->f2k_derived->tb_uop_root, vtype);
d15bac21
JW
2099}
2100
2101
29a7d776 2102/* Find or generate the symbol for a derived type's vtab. */
d15bac21
JW
2103
2104gfc_symbol *
88ce8031 2105gfc_find_derived_vtab (gfc_symbol *derived)
d15bac21
JW
2106{
2107 gfc_namespace *ns;
50f30801 2108 gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL, *def_init = NULL;
611c64f0 2109 gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
c49ea23d 2110
8b704316 2111 /* Find the top-level namespace. */
e10f52d0 2112 for (ns = gfc_current_ns; ns; ns = ns->parent)
d15bac21
JW
2113 if (!ns->parent)
2114 break;
2115
e10f52d0 2116 /* If the type is a class container, use the underlying derived type. */
8b704316 2117 if (!derived->attr.unlimited_polymorphic && derived->attr.is_class)
e10f52d0 2118 derived = gfc_get_derived_super_type (derived);
8b704316 2119
d15bac21
JW
2120 if (ns)
2121 {
4fa02692 2122 char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
29a7d776 2123
4fa02692 2124 get_unique_hashed_string (tname, derived);
b04533af 2125 sprintf (name, "__vtab_%s", tname);
611c64f0
JW
2126
2127 /* Look for the vtab symbol in various namespaces. */
2128 gfc_find_symbol (name, gfc_current_ns, 0, &vtab);
2129 if (vtab == NULL)
2130 gfc_find_symbol (name, ns, 0, &vtab);
2131 if (vtab == NULL)
2132 gfc_find_symbol (name, derived->ns, 0, &vtab);
d15bac21
JW
2133
2134 if (vtab == NULL)
2135 {
2136 gfc_get_symbol (name, ns, &vtab);
2137 vtab->ts.type = BT_DERIVED;
524af0d6
JB
2138 if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
2139 &gfc_current_locus))
e10f52d0 2140 goto cleanup;
d15bac21 2141 vtab->attr.target = 1;
95f5c775 2142 vtab->attr.save = SAVE_IMPLICIT;
d15bac21 2143 vtab->attr.vtab = 1;
f3f98a1e 2144 vtab->attr.access = ACCESS_PUBLIC;
d15bac21 2145 gfc_set_sym_referenced (vtab);
b04533af 2146 sprintf (name, "__vtype_%s", tname);
29a7d776 2147
d15bac21
JW
2148 gfc_find_symbol (name, ns, 0, &vtype);
2149 if (vtype == NULL)
2150 {
2151 gfc_component *c;
2152 gfc_symbol *parent = NULL, *parent_vtab = NULL;
2153
2154 gfc_get_symbol (name, ns, &vtype);
524af0d6
JB
2155 if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
2156 &gfc_current_locus))
81fb8a48 2157 goto cleanup;
f3f98a1e 2158 vtype->attr.access = ACCESS_PUBLIC;
611c64f0 2159 vtype->attr.vtype = 1;
d15bac21
JW
2160 gfc_set_sym_referenced (vtype);
2161
b04533af 2162 /* Add component '_hash'. */
524af0d6 2163 if (!gfc_add_component (vtype, "_hash", &c))
81fb8a48 2164 goto cleanup;
d15bac21
JW
2165 c->ts.type = BT_INTEGER;
2166 c->ts.kind = 4;
2167 c->attr.access = ACCESS_PRIVATE;
2168 c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
2169 NULL, derived->hash_value);
2170
b04533af 2171 /* Add component '_size'. */
524af0d6 2172 if (!gfc_add_component (vtype, "_size", &c))
81fb8a48 2173 goto cleanup;
d15bac21
JW
2174 c->ts.type = BT_INTEGER;
2175 c->ts.kind = 4;
2176 c->attr.access = ACCESS_PRIVATE;
2177 /* Remember the derived type in ts.u.derived,
2178 so that the correct initializer can be set later on
2179 (in gfc_conv_structure). */
2180 c->ts.u.derived = derived;
2181 c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
2182 NULL, 0);
2183
b04533af 2184 /* Add component _extends. */
524af0d6 2185 if (!gfc_add_component (vtype, "_extends", &c))
81fb8a48 2186 goto cleanup;
d15bac21
JW
2187 c->attr.pointer = 1;
2188 c->attr.access = ACCESS_PRIVATE;
8b704316
PT
2189 if (!derived->attr.unlimited_polymorphic)
2190 parent = gfc_get_derived_super_type (derived);
2191 else
2192 parent = NULL;
2193
d15bac21
JW
2194 if (parent)
2195 {
88ce8031 2196 parent_vtab = gfc_find_derived_vtab (parent);
d15bac21
JW
2197 c->ts.type = BT_DERIVED;
2198 c->ts.u.derived = parent_vtab->ts.u.derived;
2199 c->initializer = gfc_get_expr ();
2200 c->initializer->expr_type = EXPR_VARIABLE;
2201 gfc_find_sym_tree (parent_vtab->name, parent_vtab->ns,
2202 0, &c->initializer->symtree);
2203 }
2204 else
2205 {
2206 c->ts.type = BT_DERIVED;
2207 c->ts.u.derived = vtype;
2208 c->initializer = gfc_get_null_expr (NULL);
2209 }
2210
8b704316
PT
2211 if (!derived->attr.unlimited_polymorphic
2212 && derived->components == NULL
2213 && !derived->attr.zero_comp)
611c64f0
JW
2214 {
2215 /* At this point an error must have occurred.
2216 Prevent further errors on the vtype components. */
2217 found_sym = vtab;
2218 goto have_vtype;
2219 }
2220
b04533af 2221 /* Add component _def_init. */
524af0d6 2222 if (!gfc_add_component (vtype, "_def_init", &c))
50f30801
JW
2223 goto cleanup;
2224 c->attr.pointer = 1;
8e54f139 2225 c->attr.artificial = 1;
50f30801
JW
2226 c->attr.access = ACCESS_PRIVATE;
2227 c->ts.type = BT_DERIVED;
2228 c->ts.u.derived = derived;
8b704316
PT
2229 if (derived->attr.unlimited_polymorphic
2230 || derived->attr.abstract)
611c64f0 2231 c->initializer = gfc_get_null_expr (NULL);
50f30801
JW
2232 else
2233 {
2234 /* Construct default initialization variable. */
b04533af 2235 sprintf (name, "__def_init_%s", tname);
50f30801
JW
2236 gfc_get_symbol (name, ns, &def_init);
2237 def_init->attr.target = 1;
8e54f139 2238 def_init->attr.artificial = 1;
95f5c775 2239 def_init->attr.save = SAVE_IMPLICIT;
50f30801 2240 def_init->attr.access = ACCESS_PUBLIC;
22c30bc0 2241 def_init->attr.flavor = FL_VARIABLE;
50f30801
JW
2242 gfc_set_sym_referenced (def_init);
2243 def_init->ts.type = BT_DERIVED;
2244 def_init->ts.u.derived = derived;
2245 def_init->value = gfc_default_initializer (&def_init->ts);
2246
2247 c->initializer = gfc_lval_expr_from_sym (def_init);
2248 }
2249
b04533af 2250 /* Add component _copy. */
524af0d6 2251 if (!gfc_add_component (vtype, "_copy", &c))
611c64f0
JW
2252 goto cleanup;
2253 c->attr.proc_pointer = 1;
2254 c->attr.access = ACCESS_PRIVATE;
2255 c->tb = XCNEW (gfc_typebound_proc);
2256 c->tb->ppc = 1;
8b704316
PT
2257 if (derived->attr.unlimited_polymorphic
2258 || derived->attr.abstract)
611c64f0
JW
2259 c->initializer = gfc_get_null_expr (NULL);
2260 else
2261 {
2262 /* Set up namespace. */
2263 gfc_namespace *sub_ns = gfc_get_namespace (ns, 0);
2264 sub_ns->sibling = ns->contained;
2265 ns->contained = sub_ns;
2266 sub_ns->resolved = 1;
2267 /* Set up procedure symbol. */
b04533af 2268 sprintf (name, "__copy_%s", tname);
611c64f0
JW
2269 gfc_get_symbol (name, sub_ns, &copy);
2270 sub_ns->proc_name = copy;
2271 copy->attr.flavor = FL_PROCEDURE;
cf651ca2 2272 copy->attr.subroutine = 1;
0b73eb81 2273 copy->attr.pure = 1;
8e54f139 2274 copy->attr.artificial = 1;
611c64f0 2275 copy->attr.if_source = IFSRC_DECL;
c49ea23d
PT
2276 /* This is elemental so that arrays are automatically
2277 treated correctly by the scalarizer. */
2278 copy->attr.elemental = 1;
844ba455
JW
2279 if (ns->proc_name->attr.flavor == FL_MODULE)
2280 copy->module = ns->proc_name->name;
611c64f0
JW
2281 gfc_set_sym_referenced (copy);
2282 /* Set up formal arguments. */
2283 gfc_get_symbol ("src", sub_ns, &src);
2284 src->ts.type = BT_DERIVED;
2285 src->ts.u.derived = derived;
2286 src->attr.flavor = FL_VARIABLE;
2287 src->attr.dummy = 1;
8e54f139
TB
2288 src->attr.artificial = 1;
2289 src->attr.intent = INTENT_IN;
611c64f0
JW
2290 gfc_set_sym_referenced (src);
2291 copy->formal = gfc_get_formal_arglist ();
2292 copy->formal->sym = src;
2293 gfc_get_symbol ("dst", sub_ns, &dst);
2294 dst->ts.type = BT_DERIVED;
2295 dst->ts.u.derived = derived;
2296 dst->attr.flavor = FL_VARIABLE;
2297 dst->attr.dummy = 1;
8e54f139 2298 dst->attr.artificial = 1;
16023efc 2299 dst->attr.intent = INTENT_INOUT;
611c64f0
JW
2300 gfc_set_sym_referenced (dst);
2301 copy->formal->next = gfc_get_formal_arglist ();
2302 copy->formal->next->sym = dst;
2303 /* Set up code. */
11e5274a 2304 sub_ns->code = gfc_get_code (EXEC_INIT_ASSIGN);
611c64f0
JW
2305 sub_ns->code->expr1 = gfc_lval_expr_from_sym (dst);
2306 sub_ns->code->expr2 = gfc_lval_expr_from_sym (src);
2307 /* Set initializer. */
2308 c->initializer = gfc_lval_expr_from_sym (copy);
2309 c->ts.interface = copy;
2310 }
2311
8e54f139
TB
2312 /* Add component _final, which contains a procedure pointer to
2313 a wrapper which handles both the freeing of allocatable
2314 components and the calls to finalization subroutines.
2315 Note: The actual wrapper function can only be generated
2316 at resolution time. */
524af0d6 2317 if (!gfc_add_component (vtype, "_final", &c))
8e54f139
TB
2318 goto cleanup;
2319 c->attr.proc_pointer = 1;
2320 c->attr.access = ACCESS_PRIVATE;
2321 c->tb = XCNEW (gfc_typebound_proc);
2322 c->tb->ppc = 1;
2323 generate_finalization_wrapper (derived, ns, tname, c);
2324
50f30801 2325 /* Add procedure pointers for type-bound procedures. */
8b704316
PT
2326 if (!derived->attr.unlimited_polymorphic)
2327 add_procs_to_declared_vtab (derived, vtype);
d6cd8711 2328 }
d15bac21 2329
611c64f0 2330have_vtype:
d15bac21
JW
2331 vtab->ts.u.derived = vtype;
2332 vtab->value = gfc_default_initializer (&vtab->ts);
2333 }
2334 }
2335
81fb8a48
MM
2336 found_sym = vtab;
2337
2338cleanup:
2339 /* It is unexpected to have some symbols added at resolution or code
2340 generation time. We commit the changes in order to keep a clean state. */
2341 if (found_sym)
e10f52d0
JW
2342 {
2343 gfc_commit_symbol (vtab);
2344 if (vtype)
2345 gfc_commit_symbol (vtype);
50f30801
JW
2346 if (def_init)
2347 gfc_commit_symbol (def_init);
611c64f0
JW
2348 if (copy)
2349 gfc_commit_symbol (copy);
2350 if (src)
2351 gfc_commit_symbol (src);
2352 if (dst)
2353 gfc_commit_symbol (dst);
e10f52d0 2354 }
81fb8a48
MM
2355 else
2356 gfc_undo_symbols ();
2357
2358 return found_sym;
d15bac21
JW
2359}
2360
2361
86035eec
TB
2362/* Check if a derived type is finalizable. That is the case if it
2363 (1) has a FINAL subroutine or
2364 (2) has a nonpointer nonallocatable component of finalizable type.
2365 If it is finalizable, return an expression containing the
2366 finalization wrapper. */
2367
2368bool
2369gfc_is_finalizable (gfc_symbol *derived, gfc_expr **final_expr)
2370{
2371 gfc_symbol *vtab;
2372 gfc_component *c;
2373
2374 /* (1) Check for FINAL subroutines. */
2375 if (derived->f2k_derived && derived->f2k_derived->finalizers)
2376 goto yes;
2377
2378 /* (2) Check for components of finalizable type. */
2379 for (c = derived->components; c; c = c->next)
2380 if (c->ts.type == BT_DERIVED
2381 && !c->attr.pointer && !c->attr.proc_pointer && !c->attr.allocatable
2382 && gfc_is_finalizable (c->ts.u.derived, NULL))
2383 goto yes;
2384
2385 return false;
2386
2387yes:
2388 /* Make sure vtab is generated. */
2389 vtab = gfc_find_derived_vtab (derived);
2390 if (final_expr)
2391 {
2392 /* Return finalizer expression. */
2393 gfc_component *final;
2394 final = vtab->ts.u.derived->components->next->next->next->next->next;
2395 gcc_assert (strcmp (final->name, "_final") == 0);
2396 gcc_assert (final->initializer
2397 && final->initializer->expr_type != EXPR_NULL);
2398 *final_expr = final->initializer;
2399 }
2400 return true;
2401}
2402
2403
8b704316
PT
2404/* Find (or generate) the symbol for an intrinsic type's vtab. This is
2405 need to support unlimited polymorphism. */
2406
2407gfc_symbol *
2408gfc_find_intrinsic_vtab (gfc_typespec *ts)
2409{
2410 gfc_namespace *ns;
adede54c 2411 gfc_symbol *vtab = NULL, *vtype = NULL, *found_sym = NULL;
8b704316
PT
2412 gfc_symbol *copy = NULL, *src = NULL, *dst = NULL;
2413 int charlen = 0;
2414
2415 if (ts->type == BT_CHARACTER && ts->deferred)
2416 {
2417 gfc_error ("TODO: Deferred character length variable at %C cannot "
2418 "yet be associated with unlimited polymorphic entities");
2419 return NULL;
2420 }
2421
2422 if (ts->type == BT_UNKNOWN)
2423 return NULL;
2424
2425 /* Sometimes the typespec is passed from a single call. */
2426 if (ts->type == BT_DERIVED)
2427 return gfc_find_derived_vtab (ts->u.derived);
2428
2429 /* Find the top-level namespace. */
2430 for (ns = gfc_current_ns; ns; ns = ns->parent)
2431 if (!ns->parent)
2432 break;
2433
2434 if (ts->type == BT_CHARACTER && ts->u.cl && ts->u.cl->length
2435 && ts->u.cl->length->expr_type == EXPR_CONSTANT)
2436 charlen = mpz_get_si (ts->u.cl->length->value.integer);
2437
2438 if (ns)
2439 {
2440 char name[GFC_MAX_SYMBOL_LEN+1], tname[GFC_MAX_SYMBOL_LEN+1];
2441
2442 if (ts->type == BT_CHARACTER)
2443 sprintf (tname, "%s_%d_%d", gfc_basic_typename (ts->type),
2444 charlen, ts->kind);
2445 else
2446 sprintf (tname, "%s_%d_", gfc_basic_typename (ts->type), ts->kind);
2447
2448 sprintf (name, "__vtab_%s", tname);
2449
2450 /* Look for the vtab symbol in various namespaces. */
2451 gfc_find_symbol (name, gfc_current_ns, 0, &vtab);
2452 if (vtab == NULL)
2453 gfc_find_symbol (name, ns, 0, &vtab);
2454
2455 if (vtab == NULL)
2456 {
2457 gfc_get_symbol (name, ns, &vtab);
2458 vtab->ts.type = BT_DERIVED;
524af0d6
JB
2459 if (!gfc_add_flavor (&vtab->attr, FL_VARIABLE, NULL,
2460 &gfc_current_locus))
8b704316
PT
2461 goto cleanup;
2462 vtab->attr.target = 1;
2463 vtab->attr.save = SAVE_IMPLICIT;
2464 vtab->attr.vtab = 1;
2465 vtab->attr.access = ACCESS_PUBLIC;
2466 gfc_set_sym_referenced (vtab);
2467 sprintf (name, "__vtype_%s", tname);
2468
2469 gfc_find_symbol (name, ns, 0, &vtype);
2470 if (vtype == NULL)
2471 {
2472 gfc_component *c;
2473 int hash;
2474 gfc_namespace *sub_ns;
2475 gfc_namespace *contained;
2476
2477 gfc_get_symbol (name, ns, &vtype);
524af0d6
JB
2478 if (!gfc_add_flavor (&vtype->attr, FL_DERIVED, NULL,
2479 &gfc_current_locus))
8b704316
PT
2480 goto cleanup;
2481 vtype->attr.access = ACCESS_PUBLIC;
2482 vtype->attr.vtype = 1;
2483 gfc_set_sym_referenced (vtype);
2484
2485 /* Add component '_hash'. */
524af0d6 2486 if (!gfc_add_component (vtype, "_hash", &c))
8b704316
PT
2487 goto cleanup;
2488 c->ts.type = BT_INTEGER;
2489 c->ts.kind = 4;
2490 c->attr.access = ACCESS_PRIVATE;
2491 hash = gfc_intrinsic_hash_value (ts);
2492 c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
2493 NULL, hash);
2494
2495 /* Add component '_size'. */
524af0d6 2496 if (!gfc_add_component (vtype, "_size", &c))
8b704316
PT
2497 goto cleanup;
2498 c->ts.type = BT_INTEGER;
2499 c->ts.kind = 4;
2500 c->attr.access = ACCESS_PRIVATE;
2501 if (ts->type == BT_CHARACTER)
2502 c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
2503 NULL, charlen*ts->kind);
2504 else
2505 c->initializer = gfc_get_int_expr (gfc_default_integer_kind,
2506 NULL, ts->kind);
2507
2508 /* Add component _extends. */
524af0d6 2509 if (!gfc_add_component (vtype, "_extends", &c))
8b704316
PT
2510 goto cleanup;
2511 c->attr.pointer = 1;
2512 c->attr.access = ACCESS_PRIVATE;
15115f7a 2513 c->ts.type = BT_VOID;
8b704316
PT
2514 c->initializer = gfc_get_null_expr (NULL);
2515
2516 /* Add component _def_init. */
524af0d6 2517 if (!gfc_add_component (vtype, "_def_init", &c))
8b704316
PT
2518 goto cleanup;
2519 c->attr.pointer = 1;
2520 c->attr.access = ACCESS_PRIVATE;
15115f7a 2521 c->ts.type = BT_VOID;
8b704316
PT
2522 c->initializer = gfc_get_null_expr (NULL);
2523
2524 /* Add component _copy. */
524af0d6 2525 if (!gfc_add_component (vtype, "_copy", &c))
8b704316
PT
2526 goto cleanup;
2527 c->attr.proc_pointer = 1;
2528 c->attr.access = ACCESS_PRIVATE;
2529 c->tb = XCNEW (gfc_typebound_proc);
2530 c->tb->ppc = 1;
2531
2532 /* Check to see if copy function already exists. Note
2533 that this is only used for characters of different
2534 lengths. */
2535 contained = ns->contained;
2536 for (; contained; contained = contained->sibling)
2537 if (contained->proc_name
2538 && strcmp (name, contained->proc_name->name) == 0)
2539 {
2540 copy = contained->proc_name;
2541 goto got_char_copy;
2542 }
2543
2544 /* Set up namespace. */
2545 sub_ns = gfc_get_namespace (ns, 0);
2546 sub_ns->sibling = ns->contained;
2547 ns->contained = sub_ns;
2548 sub_ns->resolved = 1;
2549 /* Set up procedure symbol. */
2550 if (ts->type != BT_CHARACTER)
2551 sprintf (name, "__copy_%s", tname);
2552 else
2553 /* __copy is always the same for characters. */
2554 sprintf (name, "__copy_character_%d", ts->kind);
2555 gfc_get_symbol (name, sub_ns, &copy);
2556 sub_ns->proc_name = copy;
2557 copy->attr.flavor = FL_PROCEDURE;
2558 copy->attr.subroutine = 1;
2559 copy->attr.pure = 1;
2560 copy->attr.if_source = IFSRC_DECL;
2561 /* This is elemental so that arrays are automatically
2562 treated correctly by the scalarizer. */
2563 copy->attr.elemental = 1;
2564 if (ns->proc_name->attr.flavor == FL_MODULE)
2565 copy->module = ns->proc_name->name;
2566 gfc_set_sym_referenced (copy);
2567 /* Set up formal arguments. */
2568 gfc_get_symbol ("src", sub_ns, &src);
2569 src->ts.type = ts->type;
2570 src->ts.kind = ts->kind;
2571 src->attr.flavor = FL_VARIABLE;
2572 src->attr.dummy = 1;
2573 src->attr.intent = INTENT_IN;
2574 gfc_set_sym_referenced (src);
2575 copy->formal = gfc_get_formal_arglist ();
2576 copy->formal->sym = src;
2577 gfc_get_symbol ("dst", sub_ns, &dst);
2578 dst->ts.type = ts->type;
2579 dst->ts.kind = ts->kind;
2580 dst->attr.flavor = FL_VARIABLE;
2581 dst->attr.dummy = 1;
16023efc 2582 dst->attr.intent = INTENT_INOUT;
8b704316
PT
2583 gfc_set_sym_referenced (dst);
2584 copy->formal->next = gfc_get_formal_arglist ();
2585 copy->formal->next->sym = dst;
2586 /* Set up code. */
11e5274a 2587 sub_ns->code = gfc_get_code (EXEC_INIT_ASSIGN);
8b704316
PT
2588 sub_ns->code->expr1 = gfc_lval_expr_from_sym (dst);
2589 sub_ns->code->expr2 = gfc_lval_expr_from_sym (src);
2590 got_char_copy:
2591 /* Set initializer. */
2592 c->initializer = gfc_lval_expr_from_sym (copy);
2593 c->ts.interface = copy;
94241120
TB
2594
2595 /* Add component _final. */
524af0d6 2596 if (!gfc_add_component (vtype, "_final", &c))
94241120
TB
2597 goto cleanup;
2598 c->attr.proc_pointer = 1;
2599 c->attr.access = ACCESS_PRIVATE;
2600 c->tb = XCNEW (gfc_typebound_proc);
2601 c->tb->ppc = 1;
2602 c->initializer = gfc_get_null_expr (NULL);
8b704316
PT
2603 }
2604 vtab->ts.u.derived = vtype;
2605 vtab->value = gfc_default_initializer (&vtab->ts);
2606 }
2607 }
2608
2609 found_sym = vtab;
2610
2611cleanup:
2612 /* It is unexpected to have some symbols added at resolution or code
2613 generation time. We commit the changes in order to keep a clean state. */
2614 if (found_sym)
2615 {
2616 gfc_commit_symbol (vtab);
2617 if (vtype)
2618 gfc_commit_symbol (vtype);
8b704316
PT
2619 if (copy)
2620 gfc_commit_symbol (copy);
2621 if (src)
2622 gfc_commit_symbol (src);
2623 if (dst)
2624 gfc_commit_symbol (dst);
2625 }
2626 else
2627 gfc_undo_symbols ();
2628
2629 return found_sym;
2630}
2631
2632
d15bac21
JW
2633/* General worker function to find either a type-bound procedure or a
2634 type-bound user operator. */
2635
2636static gfc_symtree*
524af0d6 2637find_typebound_proc_uop (gfc_symbol* derived, bool* t,
d15bac21
JW
2638 const char* name, bool noaccess, bool uop,
2639 locus* where)
2640{
2641 gfc_symtree* res;
2642 gfc_symtree* root;
2643
d15bac21
JW
2644 /* Set default to failure. */
2645 if (t)
524af0d6 2646 *t = false;
d15bac21 2647
9b940c6d
JW
2648 if (derived->f2k_derived)
2649 /* Set correct symbol-root. */
2650 root = (uop ? derived->f2k_derived->tb_uop_root
2651 : derived->f2k_derived->tb_sym_root);
2652 else
2653 return NULL;
2654
d15bac21
JW
2655 /* Try to find it in the current type's namespace. */
2656 res = gfc_find_symtree (root, name);
2657 if (res && res->n.tb && !res->n.tb->error)
2658 {
2659 /* We found one. */
2660 if (t)
524af0d6 2661 *t = true;
d15bac21
JW
2662
2663 if (!noaccess && derived->attr.use_assoc
2664 && res->n.tb->access == ACCESS_PRIVATE)
2665 {
2666 if (where)
2667 gfc_error ("'%s' of '%s' is PRIVATE at %L",
2668 name, derived->name, where);
2669 if (t)
524af0d6 2670 *t = false;
d15bac21
JW
2671 }
2672
2673 return res;
2674 }
2675
2676 /* Otherwise, recurse on parent type if derived is an extension. */
2677 if (derived->attr.extension)
2678 {
2679 gfc_symbol* super_type;
2680 super_type = gfc_get_derived_super_type (derived);
2681 gcc_assert (super_type);
2682
2683 return find_typebound_proc_uop (super_type, t, name,
2684 noaccess, uop, where);
2685 }
2686
2687 /* Nothing found. */
2688 return NULL;
2689}
2690
2691
2692/* Find a type-bound procedure or user operator by name for a derived-type
2693 (looking recursively through the super-types). */
2694
2695gfc_symtree*
524af0d6 2696gfc_find_typebound_proc (gfc_symbol* derived, bool* t,
d15bac21
JW
2697 const char* name, bool noaccess, locus* where)
2698{
2699 return find_typebound_proc_uop (derived, t, name, noaccess, false, where);
2700}
2701
2702gfc_symtree*
524af0d6 2703gfc_find_typebound_user_op (gfc_symbol* derived, bool* t,
d15bac21
JW
2704 const char* name, bool noaccess, locus* where)
2705{
2706 return find_typebound_proc_uop (derived, t, name, noaccess, true, where);
2707}
2708
2709
2710/* Find a type-bound intrinsic operator looking recursively through the
2711 super-type hierarchy. */
2712
2713gfc_typebound_proc*
524af0d6 2714gfc_find_typebound_intrinsic_op (gfc_symbol* derived, bool* t,
d15bac21
JW
2715 gfc_intrinsic_op op, bool noaccess,
2716 locus* where)
2717{
2718 gfc_typebound_proc* res;
2719
2720 /* Set default to failure. */
2721 if (t)
524af0d6 2722 *t = false;
d15bac21
JW
2723
2724 /* Try to find it in the current type's namespace. */
2725 if (derived->f2k_derived)
2726 res = derived->f2k_derived->tb_op[op];
8b704316 2727 else
d15bac21
JW
2728 res = NULL;
2729
2730 /* Check access. */
2731 if (res && !res->error)
2732 {
2733 /* We found one. */
2734 if (t)
524af0d6 2735 *t = true;
d15bac21
JW
2736
2737 if (!noaccess && derived->attr.use_assoc
2738 && res->access == ACCESS_PRIVATE)
2739 {
2740 if (where)
2741 gfc_error ("'%s' of '%s' is PRIVATE at %L",
2742 gfc_op2string (op), derived->name, where);
2743 if (t)
524af0d6 2744 *t = false;
d15bac21
JW
2745 }
2746
2747 return res;
2748 }
2749
2750 /* Otherwise, recurse on parent type if derived is an extension. */
2751 if (derived->attr.extension)
2752 {
2753 gfc_symbol* super_type;
2754 super_type = gfc_get_derived_super_type (derived);
2755 gcc_assert (super_type);
2756
2757 return gfc_find_typebound_intrinsic_op (super_type, t, op,
2758 noaccess, where);
2759 }
2760
2761 /* Nothing found. */
2762 return NULL;
2763}
2764
2765
2766/* Get a typebound-procedure symtree or create and insert it if not yet
2767 present. This is like a very simplified version of gfc_get_sym_tree for
2768 tbp-symtrees rather than regular ones. */
2769
2770gfc_symtree*
2771gfc_get_tbp_symtree (gfc_symtree **root, const char *name)
2772{
2773 gfc_symtree *result;
2774
2775 result = gfc_find_symtree (*root, name);
2776 if (!result)
2777 {
2778 result = gfc_new_symtree (root, name);
2779 gcc_assert (result);
2780 result->n.tb = NULL;
2781 }
2782
2783 return result;
2784}