LCOV - code coverage report
Current view: top level - gcc/fortran - class.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.9 % 1814 1776
Test Date: 2026-10-24 16:24:59 Functions: 100.0 % 38 38
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.