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