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