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