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