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