LCOV - code coverage report
Current view: top level - gcc/fortran - class.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 97.7 % 1775 1734
Test Date: 2024-04-20 14:03:02 Functions: 100.0 % 38 38
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-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.