LCOV - code coverage report
Current view: top level - gcc/fortran - trans-common.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 96.6 % 645 623
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 25 25
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Common block and equivalence list handling
       2              :    Copyright (C) 2000-2026 Free Software Foundation, Inc.
       3              :    Contributed by Canqun Yang <canqun@nudt.edu.cn>
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : /* The core algorithm is based on Andy Vaught's g95 tree.  Also the
      22              :    way to build UNION_TYPE is borrowed from Richard Henderson.
      23              : 
      24              :    Transform common blocks.  An integral part of this is processing
      25              :    equivalence variables.  Equivalenced variables that are not in a
      26              :    common block end up in a private block of their own.
      27              : 
      28              :    Each common block or local equivalence list is declared as a union.
      29              :    Variables within the block are represented as a field within the
      30              :    block with the proper offset.
      31              : 
      32              :    So if two variables are equivalenced, they just point to a common
      33              :    area in memory.
      34              : 
      35              :    Mathematically, laying out an equivalence block is equivalent to
      36              :    solving a linear system of equations.  The matrix is usually a
      37              :    sparse matrix in which each row contains all zero elements except
      38              :    for a +1 and a -1, a sort of a generalized Vandermonde matrix.  The
      39              :    matrix is usually block diagonal.  The system can be
      40              :    overdetermined, underdetermined or have a unique solution.  If the
      41              :    system is inconsistent, the program is not standard conforming.
      42              :    The solution vector is integral, since all of the pivots are +1 or -1.
      43              : 
      44              :    How we lay out an equivalence block is a little less complicated.
      45              :    In an equivalence list with n elements, there are n-1 conditions to
      46              :    be satisfied.  The conditions partition the variables into what we
      47              :    will call segments.  If A and B are equivalenced then A and B are
      48              :    in the same segment.  If B and C are equivalenced as well, then A,
      49              :    B and C are in a segment and so on.  Each segment is a block of
      50              :    memory that has one or more variables equivalenced in some way.  A
      51              :    common block is made up of a series of segments that are joined one
      52              :    after the other.  In the linear system, a segment is a block
      53              :    diagonal.
      54              : 
      55              :    To lay out a segment we first start with some variable and
      56              :    determine its length.  The first variable is assumed to start at
      57              :    offset one and extends to however long it is.  We then traverse the
      58              :    list of equivalences to find an unused condition that involves at
      59              :    least one of the variables currently in the segment.
      60              : 
      61              :    Each equivalence condition amounts to the condition B+b=C+c where B
      62              :    and C are the offsets of the B and C variables, and b and c are
      63              :    constants which are nonzero for array elements, substrings or
      64              :    structure components.  So for
      65              : 
      66              :      EQUIVALENCE(B(2), C(3))
      67              :    we have
      68              :      B + 2*size of B's elements = C + 3*size of C's elements.
      69              : 
      70              :    If B and C are known we check to see if the condition already
      71              :    holds.  If B is known we can solve for C.  Since we know the length
      72              :    of C, we can see if the minimum and maximum extents of the segment
      73              :    are affected.  Eventually, we make a full pass through the
      74              :    equivalence list without finding any new conditions and the segment
      75              :    is fully specified.
      76              : 
      77              :    At this point, the segment is added to the current common block.
      78              :    Since we know the minimum extent of the segment, everything in the
      79              :    segment is translated to its position in the common block.  The
      80              :    usual case here is that there are no equivalence statements and the
      81              :    common block is series of segments with one variable each, which is
      82              :    a diagonal matrix in the matrix formulation.
      83              : 
      84              :    Each segment is described by a chain of segment_info structures.  Each
      85              :    segment_info structure describes the extents of a single variable within
      86              :    the segment.  This list is maintained in the order the elements are
      87              :    positioned within the segment.  If two elements have the same starting
      88              :    offset the smaller will come first.  If they also have the same size their
      89              :    ordering is undefined.
      90              : 
      91              :    Once all common blocks have been created, the list of equivalences
      92              :    is examined for still-unused equivalence conditions.  We create a
      93              :    block for each merged equivalence list.  */
      94              : 
      95              : #include "config.h"
      96              : #define INCLUDE_MAP
      97              : #include "system.h"
      98              : #include "coretypes.h"
      99              : #include "tm.h"
     100              : #include "tree.h"
     101              : #include "cgraph.h"
     102              : #include "context.h"
     103              : #include "omp-offload.h"
     104              : #include "gfortran.h"
     105              : #include "trans.h"
     106              : #include "stringpool.h"
     107              : #include "fold-const.h"
     108              : #include "stor-layout.h"
     109              : #include "varasm.h"
     110              : #include "trans-types.h"
     111              : #include "trans-const.h"
     112              : #include "target-memory.h"
     113              : 
     114              : 
     115              : /* Holds a single variable in an equivalence set.  */
     116              : typedef struct segment_info
     117              : {
     118              :   gfc_symbol *sym;
     119              :   HOST_WIDE_INT offset;
     120              :   HOST_WIDE_INT length;
     121              :   /* This will contain the field type until the field is created.  */
     122              :   tree field;
     123              :   struct segment_info *next;
     124              : } segment_info;
     125              : 
     126              : static segment_info * current_segment;
     127              : 
     128              : /* Store decl of all common blocks in this translation unit; the first
     129              :    tree is the identifier.  */
     130              : static std::map<tree, tree> gfc_map_of_all_commons;
     131              : 
     132              : 
     133              : /* Make a segment_info based on a symbol.  */
     134              : 
     135              : static segment_info *
     136         8115 : get_segment_info (gfc_symbol * sym, HOST_WIDE_INT offset)
     137              : {
     138         8115 :   segment_info *s;
     139              : 
     140              :   /* Make sure we've got the character length.  */
     141         8115 :   if (sym->ts.type == BT_CHARACTER)
     142          641 :     gfc_conv_const_charlen (sym->ts.u.cl);
     143              : 
     144              :   /* Create the segment_info and fill it in.  */
     145         8115 :   s = XCNEW (segment_info);
     146         8115 :   s->sym = sym;
     147              :   /* We will use this type when building the segment aggregate type.  */
     148         8115 :   s->field = gfc_sym_type (sym);
     149         8115 :   s->length = int_size_in_bytes (s->field);
     150         8115 :   s->offset = offset;
     151              : 
     152         8115 :   return s;
     153              : }
     154              : 
     155              : 
     156              : /* Add a copy of a segment list to the namespace.  This is specifically for
     157              :    equivalence segments, so that dependency checking can be done on
     158              :    equivalence group members.  */
     159              : 
     160              : static void
     161         6554 : copy_equiv_list_to_ns (segment_info *c)
     162              : {
     163         6554 :   segment_info *f;
     164         6554 :   gfc_equiv_info *s;
     165         6554 :   gfc_equiv_list *l;
     166              : 
     167         6554 :   l = XCNEW (gfc_equiv_list);
     168              : 
     169         6554 :   l->next = c->sym->ns->equiv_lists;
     170         6554 :   c->sym->ns->equiv_lists = l;
     171              : 
     172        14669 :   for (f = c; f; f = f->next)
     173              :     {
     174         8115 :       s = XCNEW (gfc_equiv_info);
     175         8115 :       s->next = l->equiv;
     176         8115 :       l->equiv = s;
     177         8115 :       s->sym = f->sym;
     178         8115 :       s->offset = f->offset;
     179         8115 :       s->length = f->length;
     180              :     }
     181         6554 : }
     182              : 
     183              : 
     184              : /* Add combine segment V and segment LIST.  */
     185              : 
     186              : static segment_info *
     187         7322 : add_segments (segment_info *list, segment_info *v)
     188              : {
     189         7322 :   segment_info *s;
     190         7322 :   segment_info *p;
     191         7322 :   segment_info *next;
     192              : 
     193         7322 :   p = NULL;
     194         7322 :   s = list;
     195              : 
     196        14991 :   while (v)
     197              :     {
     198              :       /* Find the location of the new element.  */
     199        42136 :       while (s)
     200              :         {
     201        35575 :           if (v->offset < s->offset)
     202              :             break;
     203        35153 :           if (v->offset == s->offset
     204          732 :               && v->length <= s->length)
     205              :             break;
     206              : 
     207        34467 :           p = s;
     208        34467 :           s = s->next;
     209              :         }
     210              : 
     211              :       /* Insert the new element in between p and s.  */
     212         7669 :       next = v->next;
     213         7669 :       v->next = s;
     214         7669 :       if (p == NULL)
     215              :         list = v;
     216              :       else
     217         4770 :         p->next = v;
     218              : 
     219              :       p = v;
     220              :       v = next;
     221              :     }
     222              : 
     223         7322 :   return list;
     224              : }
     225              : 
     226              : 
     227              : /* Construct mangled common block name from symbol name.  */
     228              : 
     229              : /* We need the bind(c) flag to tell us how/if we should mangle the symbol
     230              :    name.  There are few calls to this function, so few places that this
     231              :    would need to be added.  At the moment, there is only one call, in
     232              :    build_common_decl().  We can't attempt to look up the common block
     233              :    because we may be building it for the first time and therefore, it won't
     234              :    be in the common_root.  We also need the binding label, if it's bind(c).
     235              :    Therefore, send in the pointer to the common block, so whatever info we
     236              :    have so far can be used.  All of the necessary info should be available
     237              :    in the gfc_common_head by now, so it should be accurate to test the
     238              :    isBindC flag and use the binding label given if it is bind(c).
     239              : 
     240              :    We may NOT know yet if it's bind(c) or not, but we can try at least.
     241              :    Will have to figure out what to do later if it's labeled bind(c)
     242              :    after this is called.  */
     243              : 
     244              : static tree
     245         2061 : gfc_sym_mangled_common_id (gfc_common_head *com)
     246              : {
     247         2061 :   int has_underscore;
     248              :   /* Provide sufficient space to hold "symbol.symbol.eq.1234567890__".  */
     249         2061 :   char mangled_name[2*GFC_MAX_MANGLED_SYMBOL_LEN + 1 + 16 + 1];
     250         2061 :   char name[sizeof (mangled_name) - 2];
     251              : 
     252              :   /* Get the name out of the common block pointer.  */
     253         2061 :   size_t len = strlen (com->name);
     254         2061 :   gcc_assert (len < sizeof (name));
     255         2061 :   strcpy (name, com->name);
     256              : 
     257              :   /* If we're suppose to do a bind(c).  */
     258         2061 :   if (com->is_bind_c == 1 && com->binding_label)
     259           69 :     return get_identifier (com->binding_label);
     260              : 
     261         1992 :   if (strcmp (name, BLANK_COMMON_NAME) == 0)
     262          192 :     return get_identifier (name);
     263              : 
     264         1800 :   if (flag_underscoring)
     265              :     {
     266         1800 :       has_underscore = strchr (name, '_') != 0;
     267         1800 :       if (flag_second_underscore && has_underscore)
     268            4 :         snprintf (mangled_name, sizeof mangled_name, "%s__", name);
     269              :       else
     270         1796 :         snprintf (mangled_name, sizeof mangled_name, "%s_", name);
     271              : 
     272         1800 :       return get_identifier (mangled_name);
     273              :     }
     274              :   else
     275            0 :     return get_identifier (name);
     276              : }
     277              : 
     278              : 
     279              : /* Build a field declaration for a common variable or a local equivalence
     280              :    object.  */
     281              : 
     282              : static void
     283         8115 : build_field (segment_info *h, tree union_type, record_layout_info rli)
     284              : {
     285         8115 :   tree field;
     286         8115 :   tree name;
     287         8115 :   HOST_WIDE_INT offset = h->offset;
     288         8115 :   unsigned HOST_WIDE_INT desired_align, known_align;
     289              : 
     290         8115 :   name = get_identifier (h->sym->name);
     291         8115 :   field = build_decl (gfc_get_location (&h->sym->declared_at),
     292              :                       FIELD_DECL, name, h->field);
     293         8115 :   known_align = (offset & -offset) * BITS_PER_UNIT;
     294        12887 :   if (known_align == 0 || known_align > BIGGEST_ALIGNMENT)
     295         4900 :     known_align = BIGGEST_ALIGNMENT;
     296              : 
     297         8115 :   desired_align = update_alignment_for_field (rli, field, known_align);
     298         8115 :   if (desired_align > known_align)
     299            7 :     DECL_PACKED (field) = 1;
     300              : 
     301         8115 :   DECL_FIELD_CONTEXT (field) = union_type;
     302         8115 :   DECL_FIELD_OFFSET (field) = size_int (offset);
     303         8115 :   DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
     304         8115 :   SET_DECL_OFFSET_ALIGN (field, known_align);
     305              : 
     306         8115 :   rli->offset = size_binop (MAX_EXPR, rli->offset,
     307              :                             size_binop (PLUS_EXPR,
     308              :                                         DECL_FIELD_OFFSET (field),
     309              :                                         DECL_SIZE_UNIT (field)));
     310              :   /* If this field is assigned to a label, we create another two variables.
     311              :      One will hold the address of target label or format label. The other will
     312              :      hold the length of format label string.  */
     313         8115 :   if (h->sym->attr.assign)
     314              :     {
     315           14 :       tree len;
     316           14 :       tree addr;
     317              : 
     318           14 :       gfc_allocate_lang_decl (field);
     319           14 :       GFC_DECL_ASSIGN (field) = 1;
     320           14 :       len = gfc_create_var_np (gfc_charlen_type_node,h->sym->name);
     321           14 :       addr = gfc_create_var_np (pvoid_type_node, h->sym->name);
     322           14 :       TREE_STATIC (len) = 1;
     323           14 :       TREE_STATIC (addr) = 1;
     324           14 :       DECL_INITIAL (len) = build_int_cst (gfc_charlen_type_node, -2);
     325           14 :       gfc_set_decl_location (len, &h->sym->declared_at);
     326           14 :       gfc_set_decl_location (addr, &h->sym->declared_at);
     327           14 :       GFC_DECL_STRING_LEN (field) = pushdecl_top_level (len);
     328           14 :       GFC_DECL_ASSIGN_ADDR (field) = pushdecl_top_level (addr);
     329              :     }
     330              : 
     331              :   /* If this field is volatile, mark it.  */
     332         8115 :   if (h->sym->attr.volatile_)
     333              :     {
     334            3 :       tree new_type;
     335            3 :       TREE_THIS_VOLATILE (field) = 1;
     336            3 :       TREE_SIDE_EFFECTS (field) = 1;
     337            3 :       new_type = build_qualified_type (TREE_TYPE (field), TYPE_QUAL_VOLATILE);
     338            3 :       TREE_TYPE (field) = new_type;
     339              :     }
     340              : 
     341         8115 :   h->field = field;
     342         8115 : }
     343              : 
     344              : #if !defined (NO_DOT_IN_LABEL)
     345              : #define GFC_EQUIV_FMT "equiv.%d"
     346              : #elif !defined (NO_DOLLAR_IN_LABEL)
     347              : #define GFC_EQUIV_FMT "_Equiv$%d"
     348              : #else
     349              : #define GFC_EQUIV_FMT "_Equiv_%d"
     350              : #endif
     351              : 
     352              : /* Get storage for local equivalence.  */
     353              : 
     354              : static tree
     355          688 : build_equiv_decl (tree union_type, bool is_init, bool is_saved, bool is_auto)
     356              : {
     357          688 :   tree decl;
     358          688 :   char name[18];
     359          688 :   static int serial = 0;
     360              : 
     361          688 :   if (is_init)
     362              :     {
     363          141 :       decl = gfc_create_var (union_type, "equiv");
     364          141 :       TREE_STATIC (decl) = 1;
     365          141 :       GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
     366          141 :       return decl;
     367              :     }
     368              : 
     369          547 :   snprintf (name, sizeof (name), GFC_EQUIV_FMT, serial++);
     370          547 :   decl = build_decl (input_location,
     371              :                      VAR_DECL, get_identifier (name), union_type);
     372          547 :   DECL_ARTIFICIAL (decl) = 1;
     373          547 :   DECL_IGNORED_P (decl) = 1;
     374              : 
     375          547 :   if (!is_auto && (!gfc_can_put_var_on_stack (DECL_SIZE_UNIT (decl))
     376          526 :       || is_saved))
     377           27 :     TREE_STATIC (decl) = 1;
     378              : 
     379          547 :   TREE_ADDRESSABLE (decl) = 1;
     380          547 :   TREE_USED (decl) = 1;
     381          547 :   GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
     382              : 
     383              :   /* The source location has been lost, and doesn't really matter.
     384              :      We need to set it to something though.  */
     385          547 :   DECL_SOURCE_LOCATION (decl) = input_location;
     386              : 
     387          547 :   gfc_add_decl_to_function (decl);
     388              : 
     389          547 :   return decl;
     390              : }
     391              : 
     392              : 
     393              : /* Get storage for common block.  */
     394              : 
     395              : static tree
     396         2061 : build_common_decl (gfc_common_head *com, tree union_type, bool is_init)
     397              : {
     398         2061 :   tree decl, identifier;
     399              : 
     400         2061 :   identifier = gfc_sym_mangled_common_id (com);
     401         2061 :   decl = gfc_map_of_all_commons.count(identifier)
     402          969 :          ? gfc_map_of_all_commons[identifier] : NULL_TREE;
     403              : 
     404              :   /* Update the size of this common block as needed.  */
     405         2061 :   if (decl != NULL_TREE)
     406              :     {
     407          969 :       tree size = TYPE_SIZE_UNIT (union_type);
     408              : 
     409              :       /* Named common blocks of the same name shall be of the same size
     410              :          in all scoping units of a program in which they appear, but
     411              :          blank common blocks may be of different sizes.  */
     412          969 :       if (!tree_int_cst_equal (DECL_SIZE_UNIT (decl), size)
     413          969 :           && strcmp (com->name, BLANK_COMMON_NAME))
     414           45 :         gfc_warning (0, "Named COMMON block %qs at %L shall be of the "
     415              :                      "same size as elsewhere (%wu vs %wu bytes)", com->name,
     416              :                      &com->where,
     417           15 :                      TREE_INT_CST_LOW (size),
     418           15 :                      TREE_INT_CST_LOW (DECL_SIZE_UNIT (decl)));
     419              : 
     420          969 :       if (tree_int_cst_lt (DECL_SIZE_UNIT (decl), size))
     421              :         {
     422           11 :           DECL_SIZE (decl) = TYPE_SIZE (union_type);
     423           11 :           DECL_SIZE_UNIT (decl) = size;
     424           11 :           SET_DECL_MODE (decl, TYPE_MODE (union_type));
     425           11 :           TREE_TYPE (decl) = union_type;
     426           11 :           layout_decl (decl, 0);
     427              :         }
     428              :      }
     429              : 
     430              :   /* If this common block has been declared in a previous program unit,
     431              :      and either it is already initialized or there is no new initialization
     432              :      for it, just return.  */
     433          969 :   if ((decl != NULL_TREE) && (!is_init || DECL_INITIAL (decl)))
     434              :     return decl;
     435              : 
     436              :   /* If there is no backend_decl for the common block, build it.  */
     437         1110 :   if (decl == NULL_TREE)
     438              :     {
     439         1092 :       tree omp_clauses = NULL_TREE;
     440              : 
     441         1092 :       if (com->is_bind_c == 1 && com->binding_label)
     442           51 :         decl = build_decl (input_location, VAR_DECL, identifier, union_type);
     443              :       else
     444              :         {
     445         1041 :           decl = build_decl (input_location, VAR_DECL, get_identifier (com->name),
     446              :                              union_type);
     447         1041 :           gfc_set_decl_assembler_name (decl, identifier);
     448              :         }
     449              : 
     450         1092 :       TREE_PUBLIC (decl) = 1;
     451         1092 :       TREE_STATIC (decl) = 1;
     452         1092 :       DECL_IGNORED_P (decl) = 1;
     453         1092 :       if (!com->is_bind_c)
     454         2053 :         SET_DECL_ALIGN (decl, BIGGEST_ALIGNMENT);
     455              :       else
     456              :         {
     457              :           /* Do not set the alignment for bind(c) common blocks to
     458              :              BIGGEST_ALIGNMENT because that won't match what C does.  Also,
     459              :              for common blocks with one element, the alignment must be
     460              :              that of the field within the common block in order to match
     461              :              what C will do.  */
     462           59 :           tree field = NULL_TREE;
     463           59 :           field = TYPE_FIELDS (TREE_TYPE (decl));
     464           59 :           if (DECL_CHAIN (field) == NULL_TREE)
     465           23 :             SET_DECL_ALIGN (decl, TYPE_ALIGN (TREE_TYPE (field)));
     466              :         }
     467         1092 :       DECL_USER_ALIGN (decl) = 0;
     468         1092 :       GFC_DECL_COMMON_OR_EQUIV (decl) = 1;
     469              : 
     470         1092 :       gfc_set_decl_location (decl, &com->where);
     471              : 
     472         1092 :       if (com->omp_device_type != OMP_DEVICE_TYPE_UNSET)
     473              :         {
     474           15 :           tree c = build_omp_clause (UNKNOWN_LOCATION, OMP_CLAUSE_DEVICE_TYPE);
     475           15 :           switch (com->omp_device_type)
     476              :             {
     477            4 :             case OMP_DEVICE_TYPE_HOST:
     478            4 :               OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_HOST;
     479            4 :               break;
     480            2 :             case OMP_DEVICE_TYPE_NOHOST:
     481            2 :               OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
     482            2 :               break;
     483            9 :             case OMP_DEVICE_TYPE_ANY:
     484            9 :               OMP_CLAUSE_DEVICE_TYPE_KIND (c) = OMP_CLAUSE_DEVICE_TYPE_ANY;
     485            9 :               break;
     486            0 :             default:
     487            0 :               gcc_unreachable ();
     488              :             }
     489              :           omp_clauses = c;
     490              :         }
     491              :       /* Also check trans-decl.cc when updating/removing the following;
     492              :          also update f95.c's gfc_gnu_attributes.  */
     493         1092 :       if (com->omp_groupprivate)
     494            6 :         gfc_error ("Sorry, OMP GROUPPRIVATE not implemented, used by common "
     495            6 :                    "block %</%s/%> declared at %L", com->name, &com->where);
     496         1086 :       else if (com->omp_declare_target_local)
     497              :         /* Use 'else if' as groupprivate implies 'local'.  */
     498            0 :         gfc_error ("Sorry, OMP DECLARE TARGET with LOCAL clause not implemented"
     499              :                    ", used by common block %</%s/%> declared at %L",
     500            0 :                    com->name, &com->where);
     501              : 
     502         1092 :       if (com->omp_declare_target_link)
     503            3 :         DECL_ATTRIBUTES (decl)
     504            6 :           = tree_cons (get_identifier ("omp declare target link"),
     505            3 :                        omp_clauses, DECL_ATTRIBUTES (decl));
     506         1089 :       else if (com->omp_declare_target)
     507            6 :         DECL_ATTRIBUTES (decl)
     508           12 :           = tree_cons (get_identifier ("omp declare target"),
     509            6 :                        omp_clauses, DECL_ATTRIBUTES (decl));
     510              : 
     511         1092 :       if (com->omp_declare_target_link || com->omp_declare_target
     512              :           /* FIXME: || com->omp_declare_target_local */)
     513              :         {
     514              :           /* Add to offload_vars; get_create does so for omp_declare_target
     515              :              and omp_declare_target_local, omp_declare_target_link requires
     516              :              manual work.  */
     517            9 :           gcc_assert (symtab_node::get (decl) == 0);
     518            9 :           symtab_node *node = symtab_node::get_create (decl);
     519            9 :           if (node != NULL && com->omp_declare_target_link)
     520              :             {
     521            3 :               node->offloadable = 1;
     522            3 :               if (ENABLE_OFFLOADING)
     523              :                 {
     524              :                   g->have_offload = true;
     525              :                   if (is_a <varpool_node *> (node))
     526              :                     vec_safe_push (offload_vars, decl);
     527              :                 }
     528              :             }
     529              :         }
     530              : 
     531              :       /* Place the back end declaration for this common block in
     532              :          GLOBAL_BINDING_LEVEL.  */
     533         1092 :       gfc_map_of_all_commons[identifier] = pushdecl_top_level (decl);
     534              :     }
     535              : 
     536              :   /* Has no initial values.  */
     537         1110 :   if (!is_init)
     538              :     {
     539         1008 :       DECL_INITIAL (decl) = NULL_TREE;
     540         1008 :       DECL_COMMON (decl) = 1;
     541         1008 :       DECL_DEFER_OUTPUT (decl) = 1;
     542              :     }
     543              :   else
     544              :     {
     545          102 :       DECL_INITIAL (decl) = error_mark_node;
     546          102 :       DECL_COMMON (decl) = 0;
     547          102 :       DECL_DEFER_OUTPUT (decl) = 0;
     548              :     }
     549              : 
     550         1110 :   if (com->threadprivate)
     551           43 :     set_decl_tls_model (decl, decl_default_tls_model (decl));
     552              : 
     553              :   return decl;
     554              : }
     555              : 
     556              : 
     557              : /* Return a field that is the size of the union, if an equivalence has
     558              :    overlapping initializers.  Merge the initializers into a single
     559              :    initializer for this new field, then free the old ones.  */
     560              : 
     561              : static tree
     562          941 : get_init_field (segment_info *head, tree union_type, tree *field_init,
     563              :                 record_layout_info rli)
     564              : {
     565          941 :   segment_info *s;
     566          941 :   HOST_WIDE_INT length = 0;
     567          941 :   HOST_WIDE_INT offset = 0;
     568          941 :   unsigned HOST_WIDE_INT known_align, desired_align;
     569          941 :   bool overlap = false;
     570          941 :   tree tmp, field;
     571          941 :   tree init;
     572          941 :   unsigned char *data, *chk;
     573          941 :   vec<constructor_elt, va_gc> *v = NULL;
     574              : 
     575          941 :   tree type = unsigned_char_type_node;
     576          941 :   int i;
     577              : 
     578              :   /* Obtain the size of the union and check if there are any overlapping
     579              :      initializers.  */
     580         4070 :   for (s = head; s; s = s->next)
     581              :     {
     582         3129 :       HOST_WIDE_INT slen = s->offset + s->length;
     583         3129 :       if (s->sym->value)
     584              :         {
     585          229 :           if (s->offset < offset)
     586           50 :             overlap = true;
     587              :           offset = slen;
     588              :         }
     589         3129 :       length = length < slen ? slen : length;
     590              :     }
     591              : 
     592          941 :   if (!overlap)
     593              :     return NULL_TREE;
     594              : 
     595              :   /* Now absorb all the initializer data into a single vector,
     596              :      whilst checking for overlapping, unequal values.  */
     597           46 :   data = XCNEWVEC (unsigned char, (size_t)length);
     598           46 :   chk = XCNEWVEC (unsigned char, (size_t)length);
     599              : 
     600              :   /* TODO - change this when default initialization is implemented.  */
     601           46 :   memset (data, '\0', (size_t)length);
     602           46 :   memset (chk, '\0', (size_t)length);
     603          156 :   for (s = head; s; s = s->next)
     604          110 :     if (s->sym->value)
     605              :       {
     606           96 :         locus *loc = NULL;
     607           96 :         if (s->sym->ns->equiv && s->sym->ns->equiv->eq)
     608           96 :           loc = &s->sym->ns->equiv->eq->expr->where;
     609           96 :         gfc_merge_initializers (s->sym->ts, s->sym->value, loc,
     610              :                               &data[s->offset],
     611           96 :                               &chk[s->offset],
     612           96 :                              (size_t)s->length);
     613              :       }
     614              : 
     615         1142 :   for (i = 0; i < length; i++)
     616         1096 :     CONSTRUCTOR_APPEND_ELT (v, NULL, build_int_cst (type, data[i]));
     617              : 
     618           46 :   free (data);
     619           46 :   free (chk);
     620              : 
     621              :   /* Build a char[length] array to hold the initializers.  Much of what
     622              :      follows is borrowed from build_field, above.  */
     623              : 
     624           46 :   tmp = build_int_cst (gfc_array_index_type, length - 1);
     625           46 :   tmp = build_range_type (gfc_array_index_type,
     626              :                           gfc_index_zero_node, tmp);
     627           46 :   tmp = build_array_type (type, tmp);
     628           46 :   field = build_decl (input_location, FIELD_DECL, NULL_TREE, tmp);
     629              : 
     630           46 :   known_align = BIGGEST_ALIGNMENT;
     631              : 
     632           46 :   desired_align = update_alignment_for_field (rli, field, known_align);
     633           46 :   if (desired_align > known_align)
     634            0 :     DECL_PACKED (field) = 1;
     635              : 
     636           46 :   DECL_FIELD_CONTEXT (field) = union_type;
     637           46 :   DECL_FIELD_OFFSET (field) = size_int (0);
     638           46 :   DECL_FIELD_BIT_OFFSET (field) = bitsize_zero_node;
     639           46 :   SET_DECL_OFFSET_ALIGN (field, known_align);
     640              : 
     641           46 :   rli->offset = size_binop (MAX_EXPR, rli->offset,
     642              :                             size_binop (PLUS_EXPR,
     643              :                                         DECL_FIELD_OFFSET (field),
     644              :                                         DECL_SIZE_UNIT (field)));
     645              : 
     646           46 :   init = build_constructor (TREE_TYPE (field), v);
     647           46 :   TREE_CONSTANT (init) = 1;
     648              : 
     649           46 :   *field_init = init;
     650              : 
     651          156 :   for (s = head; s; s = s->next)
     652              :     {
     653          110 :       if (s->sym->value == NULL)
     654           14 :         continue;
     655              : 
     656           96 :       gfc_free_expr (s->sym->value);
     657           96 :       s->sym->value = NULL;
     658              :     }
     659              : 
     660              :   return field;
     661              : }
     662              : 
     663              : 
     664              : /* Declare memory for the common block or local equivalence, and create
     665              :    backend declarations for all of the elements.  */
     666              : 
     667              : static void
     668         2749 : create_common (gfc_common_head *com, segment_info *head, bool saw_equiv)
     669              : {
     670         2749 :   segment_info *s, *next_s;
     671         2749 :   tree union_type;
     672         2749 :   tree *field_link;
     673         2749 :   tree field;
     674         2749 :   tree field_init = NULL_TREE;
     675         2749 :   record_layout_info rli;
     676         2749 :   tree decl;
     677         2749 :   bool is_init = false;
     678         2749 :   bool is_saved = false;
     679         2749 :   bool is_auto = false;
     680              : 
     681              :   /* Declare the variables inside the common block.
     682              :      If the current common block contains any equivalence object, then
     683              :      make a UNION_TYPE node, otherwise RECORD_TYPE. This will let the
     684              :      alias analyzer work well when there is no address overlapping for
     685              :      common variables in the current common block.  */
     686         2749 :   if (saw_equiv)
     687          941 :     union_type = make_node (UNION_TYPE);
     688              :   else
     689         1808 :     union_type = make_node (RECORD_TYPE);
     690              : 
     691         2749 :   rli = start_record_layout (union_type);
     692         2749 :   field_link = &TYPE_FIELDS (union_type);
     693              : 
     694              :   /* Check for overlapping initializers and replace them with a single,
     695              :      artificial field that contains all the data.  */
     696         2749 :   if (saw_equiv)
     697          941 :     field = get_init_field (head, union_type, &field_init, rli);
     698              :   else
     699              :     field = NULL_TREE;
     700              : 
     701          941 :   if (field != NULL_TREE)
     702              :     {
     703           46 :       is_init = true;
     704           46 :       *field_link = field;
     705           46 :       field_link = &DECL_CHAIN (field);
     706              :     }
     707              : 
     708        10864 :   for (s = head; s; s = s->next)
     709              :     {
     710         8115 :       build_field (s, union_type, rli);
     711              : 
     712              :       /* Link the field into the type.  */
     713         8115 :       *field_link = s->field;
     714         8115 :       field_link = &DECL_CHAIN (s->field);
     715              : 
     716              :       /* Has initial value.  */
     717         8115 :       if (s->sym->value)
     718          254 :         is_init = true;
     719              : 
     720              :       /* Has SAVE attribute.  */
     721         8115 :       if (s->sym->attr.save)
     722          582 :         is_saved = true;
     723              : 
     724              :       /* Has AUTOMATIC attribute.  */
     725         8115 :       if (s->sym->attr.automatic)
     726           14 :         is_auto = true;
     727              :     }
     728              : 
     729         2749 :   finish_record_layout (rli, true);
     730              : 
     731         2749 :   if (com)
     732         2061 :     decl = build_common_decl (com, union_type, is_init);
     733              :   else
     734          688 :     decl = build_equiv_decl (union_type, is_init, is_saved, is_auto);
     735              : 
     736         2749 :   if (is_init)
     737              :     {
     738          243 :       tree ctor, tmp;
     739          243 :       vec<constructor_elt, va_gc> *v = NULL;
     740              : 
     741          243 :       if (field != NULL_TREE && field_init != NULL_TREE)
     742           46 :         CONSTRUCTOR_APPEND_ELT (v, field, field_init);
     743              :       else
     744          605 :         for (s = head; s; s = s->next)
     745              :           {
     746          408 :             if (s->sym->value)
     747              :               {
     748              :                 /* Add the initializer for this field.  */
     749          254 :                 tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts,
     750          254 :                                             TREE_TYPE (s->field),
     751              :                                             s->sym->attr.dimension,
     752          254 :                                             s->sym->attr.pointer
     753          254 :                                             || s->sym->attr.allocatable, false);
     754              : 
     755          254 :                 CONSTRUCTOR_APPEND_ELT (v, s->field, tmp);
     756              :               }
     757              :           }
     758              : 
     759          243 :       gcc_assert (!v->is_empty ());
     760          243 :       ctor = build_constructor (union_type, v);
     761          243 :       TREE_CONSTANT (ctor) = 1;
     762          243 :       TREE_STATIC (ctor) = 1;
     763          243 :       DECL_INITIAL (decl) = ctor;
     764              : 
     765          243 :       if (flag_checking)
     766              :         {
     767              :           tree field, value;
     768              :           unsigned HOST_WIDE_INT idx;
     769          543 :           FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), idx, field, value)
     770          300 :             gcc_assert (TREE_CODE (field) == FIELD_DECL);
     771              :         }
     772              :     }
     773              : 
     774              :   /* Build component reference for each variable.  */
     775        10864 :   for (s = head; s; s = next_s)
     776              :     {
     777         8115 :       tree var_decl;
     778              : 
     779         8115 :       var_decl = build_decl (gfc_get_location (&s->sym->declared_at),
     780         8115 :                              VAR_DECL, DECL_NAME (s->field),
     781         8115 :                              TREE_TYPE (s->field));
     782         8115 :       TREE_STATIC (var_decl) = TREE_STATIC (decl);
     783              :       /* Mark the variable as used in order to avoid warnings about
     784              :          unused variables.  */
     785         8115 :       TREE_USED (var_decl) = 1;
     786         8115 :       if (s->sym->attr.use_assoc)
     787          436 :         DECL_IGNORED_P (var_decl) = 1;
     788         8115 :       if (s->sym->attr.target)
     789           66 :         TREE_ADDRESSABLE (var_decl) = 1;
     790              :       /* Fake variables are not visible from other translation units.  */
     791         8115 :       TREE_PUBLIC (var_decl) = 0;
     792         8115 :       gfc_finish_decl_attrs (var_decl, &s->sym->attr);
     793              : 
     794              :       /* To preserve identifier names in COMMON, chain to procedure
     795              :          scope unless at top level in a module definition.  */
     796         8115 :       if (com
     797         6355 :           && s->sym->ns->proc_name
     798         6284 :           && s->sym->ns->proc_name->attr.flavor == FL_MODULE)
     799          491 :         var_decl = pushdecl_top_level (var_decl);
     800              :       else
     801         7624 :         gfc_add_decl_to_function (var_decl);
     802              : 
     803         8115 :       tree comp = build3_loc (input_location, COMPONENT_REF,
     804         8115 :                               TREE_TYPE (s->field), decl, s->field, NULL_TREE);
     805         8115 :       if (TREE_THIS_VOLATILE (s->field))
     806            3 :         TREE_THIS_VOLATILE (comp) = 1;
     807         8115 :       SET_DECL_VALUE_EXPR (var_decl, comp);
     808         8115 :       DECL_HAS_VALUE_EXPR_P (var_decl) = 1;
     809         8115 :       GFC_DECL_COMMON_OR_EQUIV (var_decl) = 1;
     810              : 
     811         8115 :       if (s->sym->attr.assign)
     812              :         {
     813           14 :           gfc_allocate_lang_decl (var_decl);
     814           14 :           GFC_DECL_ASSIGN (var_decl) = 1;
     815           14 :           GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field);
     816           14 :           GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field);
     817              :         }
     818              : 
     819         8115 :       s->sym->backend_decl = var_decl;
     820              : 
     821         8115 :       next_s = s->next;
     822         8115 :       free (s);
     823              :     }
     824         2749 : }
     825              : 
     826              : 
     827              : /* Given a symbol, find it in the current segment list. Returns NULL if
     828              :    not found.  */
     829              : 
     830              : static segment_info *
     831         7331 : find_segment_info (gfc_symbol *symbol)
     832              : {
     833         7331 :   segment_info *n;
     834              : 
     835        43385 :   for (n = current_segment; n; n = n->next)
     836              :     {
     837        36063 :       if (n->sym == symbol)
     838              :         return n;
     839              :     }
     840              : 
     841              :   return NULL;
     842              : }
     843              : 
     844              : 
     845              : /* Given an expression node, make sure it is a constant integer and return
     846              :    the mpz_t value.  */
     847              : 
     848              : static mpz_t *
     849         6084 : get_mpz (gfc_expr *e)
     850              : {
     851              : 
     852            0 :   if (e->expr_type != EXPR_CONSTANT)
     853            0 :     gfc_internal_error ("get_mpz(): Not an integer constant");
     854              : 
     855         6084 :   return &e->value.integer;
     856              : }
     857              : 
     858              : 
     859              : /* Given an array specification and an array reference, figure out the
     860              :    array element number (zero based). Bounds and elements are guaranteed
     861              :    to be constants.  If something goes wrong we generate an error and
     862              :    return zero.  */
     863              : 
     864              : static HOST_WIDE_INT
     865         1427 : element_number (gfc_array_ref *ar)
     866              : {
     867         1427 :   mpz_t multiplier, offset, extent, n;
     868         1427 :   gfc_array_spec *as;
     869         1427 :   HOST_WIDE_INT i, rank;
     870              : 
     871         1427 :   as = ar->as;
     872         1427 :   rank = as->rank;
     873         1427 :   mpz_init_set_ui (multiplier, 1);
     874         1427 :   mpz_init_set_ui (offset, 0);
     875         1427 :   mpz_init (extent);
     876         1427 :   mpz_init (n);
     877              : 
     878         4291 :   for (i = 0; i < rank; i++)
     879              :     {
     880         1437 :       if (ar->dimen_type[i] != DIMEN_ELEMENT)
     881            0 :         gfc_internal_error ("element_number(): Bad dimension type");
     882              : 
     883         1437 :       if (as && as->lower[i])
     884         1436 :         mpz_sub (n, *get_mpz (ar->start[i]), *get_mpz (as->lower[i]));
     885              :       else
     886            1 :         mpz_sub_ui (n, *get_mpz (ar->start[i]), 1);
     887              : 
     888         1437 :       mpz_mul (n, n, multiplier);
     889         1437 :       mpz_add (offset, offset, n);
     890              : 
     891         1437 :       if (as && as->upper[i] && as->lower[i])
     892              :         {
     893         1436 :           mpz_sub (extent, *get_mpz (as->upper[i]), *get_mpz (as->lower[i]));
     894         1436 :           mpz_add_ui (extent, extent, 1);
     895              :         }
     896              :       else
     897            1 :         mpz_set_ui (extent, 0);
     898              : 
     899         1437 :       if (mpz_sgn (extent) < 0)
     900            0 :         mpz_set_ui (extent, 0);
     901              : 
     902         1437 :       mpz_mul (multiplier, multiplier, extent);
     903              :     }
     904              : 
     905         1427 :   i = mpz_get_ui (offset);
     906              : 
     907         1427 :   mpz_clear (multiplier);
     908         1427 :   mpz_clear (offset);
     909         1427 :   mpz_clear (extent);
     910         1427 :   mpz_clear (n);
     911              : 
     912         1427 :   return i;
     913              : }
     914              : 
     915              : 
     916              : /* Given a single element of an equivalence list, figure out the offset
     917              :    from the base symbol.  For simple variables or full arrays, this is
     918              :    simply zero.  For an array element we have to calculate the array
     919              :    element number and multiply by the element size. For a substring we
     920              :    have to calculate the further reference.  */
     921              : 
     922              : static HOST_WIDE_INT
     923         3126 : calculate_offset (gfc_expr *e)
     924              : {
     925         3126 :   HOST_WIDE_INT n, element_size, offset;
     926         3126 :   gfc_typespec *element_type;
     927         3126 :   gfc_ref *reference;
     928              : 
     929         3126 :   offset = 0;
     930         3126 :   element_type = &e->symtree->n.sym->ts;
     931              : 
     932         5320 :   for (reference = e->ref; reference; reference = reference->next)
     933         2194 :     switch (reference->type)
     934              :       {
     935         1855 :       case REF_ARRAY:
     936         1855 :         switch (reference->u.ar.type)
     937              :           {
     938              :           case AR_FULL:
     939              :             break;
     940              : 
     941         1427 :           case AR_ELEMENT:
     942         1427 :             n = element_number (&reference->u.ar);
     943         1427 :             if (element_type->type == BT_CHARACTER)
     944          221 :               gfc_conv_const_charlen (element_type->u.cl);
     945         1427 :             element_size =
     946         1427 :               int_size_in_bytes (gfc_typenode_for_spec (element_type));
     947         1427 :             offset += n * element_size;
     948         1427 :             break;
     949              : 
     950            0 :           default:
     951            0 :             gfc_error ("Bad array reference at %L", &e->where);
     952              :           }
     953              :         break;
     954          339 :       case REF_SUBSTRING:
     955          339 :         if (reference->u.ss.start != NULL)
     956          339 :           offset += mpz_get_ui (*get_mpz (reference->u.ss.start)) - 1;
     957              :         break;
     958            0 :       default:
     959            0 :         gfc_error ("Illegal reference type at %L as EQUIVALENCE object",
     960              :                    &e->where);
     961              :     }
     962         3126 :   return offset;
     963              : }
     964              : 
     965              : 
     966              : /* Add a new segment_info structure to the current segment.  eq1 is already
     967              :    in the list, eq2 is not.  */
     968              : 
     969              : static void
     970         1561 : new_condition (segment_info *v, gfc_equiv *eq1, gfc_equiv *eq2)
     971              : {
     972         1561 :   HOST_WIDE_INT offset1, offset2;
     973         1561 :   segment_info *a;
     974              : 
     975         1561 :   offset1 = calculate_offset (eq1->expr);
     976         1561 :   offset2 = calculate_offset (eq2->expr);
     977              : 
     978         3122 :   a = get_segment_info (eq2->expr->symtree->n.sym,
     979         1561 :                         v->offset + offset1 - offset2);
     980              : 
     981         1561 :   current_segment = add_segments (current_segment, a);
     982         1561 : }
     983              : 
     984              : 
     985              : /* Given two equivalence structures that are both already in the list, make
     986              :    sure that this new condition is not violated, generating an error if it
     987              :    is.  */
     988              : 
     989              : static void
     990            2 : confirm_condition (segment_info *s1, gfc_equiv *eq1, segment_info *s2,
     991              :                    gfc_equiv *eq2)
     992              : {
     993            2 :   HOST_WIDE_INT offset1, offset2;
     994              : 
     995            2 :   offset1 = calculate_offset (eq1->expr);
     996            2 :   offset2 = calculate_offset (eq2->expr);
     997              : 
     998            2 :   if (s1->offset + offset1 != s2->offset + offset2)
     999            2 :     gfc_error ("Inconsistent equivalence rules involving %qs at %L and "
    1000            2 :                "%qs at %L", s1->sym->name, &s1->sym->declared_at,
    1001            2 :                s2->sym->name, &s2->sym->declared_at);
    1002            2 : }
    1003              : 
    1004              : 
    1005              : /* Process a new equivalence condition. eq1 is know to be in segment f.
    1006              :    If eq2 is also present then confirm that the condition holds.
    1007              :    Otherwise add a new variable to the segment list.  */
    1008              : 
    1009              : static void
    1010         1563 : add_condition (segment_info *f, gfc_equiv *eq1, gfc_equiv *eq2)
    1011              : {
    1012         1563 :   segment_info *n;
    1013              : 
    1014         1563 :   n = find_segment_info (eq2->expr->symtree->n.sym);
    1015              : 
    1016         1563 :   if (n == NULL)
    1017         1561 :     new_condition (f, eq1, eq2);
    1018              :   else
    1019            2 :     confirm_condition (f, eq1, n, eq2);
    1020         1563 : }
    1021              : 
    1022              : static void
    1023        44745 : accumulate_equivalence_attributes (symbol_attribute *dummy_symbol, gfc_equiv *e)
    1024              : {
    1025        44745 :   symbol_attribute attr = e->expr->symtree->n.sym->attr;
    1026              : 
    1027        44745 :   dummy_symbol->dummy |= attr.dummy;
    1028        44745 :   dummy_symbol->pointer |= attr.pointer;
    1029        44745 :   dummy_symbol->target |= attr.target;
    1030        44745 :   dummy_symbol->external |= attr.external;
    1031        44745 :   dummy_symbol->intrinsic |= attr.intrinsic;
    1032        44745 :   dummy_symbol->allocatable |= attr.allocatable;
    1033        44745 :   dummy_symbol->elemental |= attr.elemental;
    1034        44745 :   dummy_symbol->recursive |= attr.recursive;
    1035        44745 :   dummy_symbol->in_common |= attr.in_common;
    1036        44745 :   dummy_symbol->result |= attr.result;
    1037        44745 :   dummy_symbol->in_namelist |= attr.in_namelist;
    1038        44745 :   dummy_symbol->optional |= attr.optional;
    1039        44745 :   dummy_symbol->entry |= attr.entry;
    1040        44745 :   dummy_symbol->function |= attr.function;
    1041        44745 :   dummy_symbol->subroutine |= attr.subroutine;
    1042        44745 :   dummy_symbol->dimension |= attr.dimension;
    1043        44745 :   dummy_symbol->in_equivalence |= attr.in_equivalence;
    1044        44745 :   dummy_symbol->use_assoc |= attr.use_assoc;
    1045        44745 :   dummy_symbol->cray_pointer |= attr.cray_pointer;
    1046        44745 :   dummy_symbol->cray_pointee |= attr.cray_pointee;
    1047        44745 :   dummy_symbol->data |= attr.data;
    1048        44745 :   dummy_symbol->value |= attr.value;
    1049        44745 :   dummy_symbol->volatile_ |= attr.volatile_;
    1050        44745 :   dummy_symbol->is_protected |= attr.is_protected;
    1051        44745 :   dummy_symbol->is_bind_c |= attr.is_bind_c;
    1052        44745 :   dummy_symbol->procedure |= attr.procedure;
    1053        44745 :   dummy_symbol->proc_pointer |= attr.proc_pointer;
    1054        44745 :   dummy_symbol->abstract |= attr.abstract;
    1055        44745 :   dummy_symbol->asynchronous |= attr.asynchronous;
    1056        44745 :   dummy_symbol->codimension |= attr.codimension;
    1057        44745 :   dummy_symbol->contiguous |= attr.contiguous;
    1058        44745 :   dummy_symbol->generic |= attr.generic;
    1059        44745 :   dummy_symbol->automatic |= attr.automatic;
    1060        44745 :   dummy_symbol->threadprivate |= attr.threadprivate;
    1061        44745 :   dummy_symbol->omp_groupprivate |= attr.omp_groupprivate;
    1062        44745 :   dummy_symbol->omp_declare_target |= attr.omp_declare_target;
    1063        44745 :   dummy_symbol->omp_declare_target_link |= attr.omp_declare_target_link;
    1064        44745 :   dummy_symbol->omp_declare_target_local |= attr.omp_declare_target_local;
    1065        44745 :   dummy_symbol->oacc_declare_copyin |= attr.oacc_declare_copyin;
    1066        44745 :   dummy_symbol->oacc_declare_create |= attr.oacc_declare_create;
    1067        44745 :   dummy_symbol->oacc_declare_deviceptr |= attr.oacc_declare_deviceptr;
    1068        44745 :   dummy_symbol->oacc_declare_device_resident
    1069        44745 :     |= attr.oacc_declare_device_resident;
    1070              : 
    1071              :   /* Not strictly correct, but probably close enough.  */
    1072        44745 :   if (attr.save > dummy_symbol->save)
    1073          691 :     dummy_symbol->save = attr.save;
    1074        44745 :   if (attr.access > dummy_symbol->access)
    1075            4 :     dummy_symbol->access = attr.access;
    1076        44745 : }
    1077              : 
    1078              : /* Given a segment element, search through the equivalence lists for unused
    1079              :    conditions that involve the symbol.  Add these rules to the segment.  */
    1080              : 
    1081              : static bool
    1082         8103 : find_equivalence (segment_info *n)
    1083              : {
    1084         8103 :   gfc_equiv *e1, *e2, *eq;
    1085         8103 :   bool found;
    1086              : 
    1087         8103 :   found = false;
    1088              : 
    1089        31010 :   for (e1 = n->sym->ns->equiv; e1; e1 = e1->next)
    1090              :     {
    1091        22907 :       eq = NULL;
    1092              : 
    1093              :       /* Search the equivalence list, including the root (first) element
    1094              :          for the symbol that owns the segment.  */
    1095        22907 :       symbol_attribute dummy_symbol;
    1096        22907 :       memset (&dummy_symbol, 0, sizeof (dummy_symbol));
    1097        66136 :       for (e2 = e1; e2; e2 = e2->eq)
    1098              :         {
    1099        44745 :           accumulate_equivalence_attributes (&dummy_symbol, e2);
    1100        44745 :           if (!e2->used && e2->expr->symtree->n.sym == n->sym)
    1101              :             {
    1102              :               eq = e2;
    1103              :               break;
    1104              :             }
    1105              :         }
    1106              : 
    1107        22907 :       gfc_check_conflict (&dummy_symbol, e1->expr->symtree->name, &e1->expr->where);
    1108              : 
    1109              :       /* Go to the next root element.  */
    1110        22907 :       if (eq == NULL)
    1111        21391 :         continue;
    1112              : 
    1113         1516 :       eq->used = 1;
    1114              : 
    1115              :       /* Now traverse the equivalence list matching the offsets.  */
    1116         4595 :       for (e2 = e1; e2; e2 = e2->eq)
    1117              :         {
    1118         3079 :           if (!e2->used && e2 != eq)
    1119              :             {
    1120         1563 :               add_condition (n, eq, e2);
    1121         1563 :               e2->used = 1;
    1122         1563 :               found = true;
    1123              :             }
    1124              :         }
    1125              :     }
    1126         8103 :   return found;
    1127              : }
    1128              : 
    1129              : 
    1130              : /* Add all symbols equivalenced within a segment.  We need to scan the
    1131              :    segment list multiple times to include indirect equivalences.  Since
    1132              :    a new segment_info can inserted at the beginning of the segment list,
    1133              :    depending on its offset, we have to force a final pass through the
    1134              :    loop by demanding that completion sees a pass with no matches; i.e.,
    1135              :    all symbols with equiv_built set and no new equivalences found.  */
    1136              : 
    1137              : static void
    1138         6554 : add_equivalences (bool *saw_equiv)
    1139              : {
    1140         6554 :   segment_info *f;
    1141         6554 :   bool more = true;
    1142              : 
    1143        14264 :   while (more)
    1144              :     {
    1145         7710 :       more = false;
    1146        17699 :       for (f = current_segment; f; f = f->next)
    1147              :         {
    1148         9989 :           if (!f->sym->equiv_built)
    1149              :             {
    1150         8103 :               f->sym->equiv_built = 1;
    1151         8103 :               bool seen_one = find_equivalence (f);
    1152         8103 :               if (seen_one)
    1153              :                 {
    1154         1163 :                   *saw_equiv = true;
    1155         1163 :                   more = true;
    1156              :                 }
    1157              :             }
    1158              :         }
    1159              :     }
    1160              : 
    1161              :   /* Add a copy of this segment list to the namespace.  */
    1162         6554 :   copy_equiv_list_to_ns (current_segment);
    1163         6554 : }
    1164              : 
    1165              : 
    1166              : /* Returns the offset necessary to properly align the current equivalence.
    1167              :    Sets *palign to the required alignment.  */
    1168              : 
    1169              : static HOST_WIDE_INT
    1170         6536 : align_segment (unsigned HOST_WIDE_INT *palign)
    1171              : {
    1172         6536 :   segment_info *s;
    1173         6536 :   unsigned HOST_WIDE_INT offset;
    1174         6536 :   unsigned HOST_WIDE_INT max_align;
    1175         6536 :   unsigned HOST_WIDE_INT this_align;
    1176         6536 :   unsigned HOST_WIDE_INT this_offset;
    1177              : 
    1178         6536 :   max_align = 1;
    1179         6536 :   offset = 0;
    1180        14633 :   for (s = current_segment; s; s = s->next)
    1181              :     {
    1182         8097 :       this_align = TYPE_ALIGN_UNIT (s->field);
    1183         8097 :       if (s->offset & (this_align - 1))
    1184              :         {
    1185              :           /* Field is misaligned.  */
    1186          128 :           this_offset = this_align - ((s->offset + offset) & (this_align - 1));
    1187          128 :           if (this_offset & (max_align - 1))
    1188              :             {
    1189              :               /* Aligning this field would misalign a previous field.  */
    1190            0 :               gfc_error ("The equivalence set for variable %qs "
    1191              :                          "declared at %L violates alignment requirements",
    1192            0 :                          s->sym->name, &s->sym->declared_at);
    1193              :             }
    1194          128 :           offset += this_offset;
    1195              :         }
    1196         8097 :       max_align = this_align;
    1197              :     }
    1198         6536 :   if (palign)
    1199         6536 :     *palign = max_align;
    1200         6536 :   return offset;
    1201              : }
    1202              : 
    1203              : 
    1204              : /* Adjust segment offsets by the given amount.  */
    1205              : 
    1206              : static void
    1207         6554 : apply_segment_offset (segment_info *s, HOST_WIDE_INT offset)
    1208              : {
    1209        14669 :   for (; s; s = s->next)
    1210         8115 :     s->offset += offset;
    1211            0 : }
    1212              : 
    1213              : 
    1214              : /* Lay out a symbol in a common block.  If the symbol has already been seen
    1215              :    then check the location is consistent.  Otherwise create segments
    1216              :    for that symbol and all the symbols equivalenced with it.  */
    1217              : 
    1218              : /* Translate a single common block.  */
    1219              : 
    1220              : static void
    1221         1957 : translate_common (gfc_common_head *common, gfc_symbol *var_list)
    1222              : {
    1223         1957 :   gfc_symbol *sym;
    1224         1957 :   segment_info *s;
    1225         1957 :   segment_info *common_segment;
    1226         1957 :   HOST_WIDE_INT offset;
    1227         1957 :   HOST_WIDE_INT current_offset;
    1228         1957 :   unsigned HOST_WIDE_INT align;
    1229         1957 :   bool saw_equiv;
    1230              : 
    1231         1957 :   common_segment = NULL;
    1232         1957 :   offset = 0;
    1233         1957 :   current_offset = 0;
    1234         1957 :   align = 1;
    1235         1957 :   saw_equiv = false;
    1236              : 
    1237         1957 :   if (var_list && var_list->attr.omp_allocate)
    1238            6 :     gfc_error ("Sorry, !$OMP allocate for COMMON block variable %qs at %L "
    1239            6 :                "not supported", common->name, &common->where);
    1240              : 
    1241              :   /* Add symbols to the segment.  */
    1242         7725 :   for (sym = var_list; sym; sym = sym->common_next)
    1243              :     {
    1244         5768 :       current_segment = common_segment;
    1245         5768 :       s = find_segment_info (sym);
    1246              : 
    1247              :       /* Symbol has already been added via an equivalence.  Multiple
    1248              :          use associations of the same common block result in equiv_built
    1249              :          being set but no information about the symbol in the segment.  */
    1250         5768 :       if (s && sym->equiv_built)
    1251              :         {
    1252              :           /* Ensure the current location is properly aligned.  */
    1253            7 :           align = TYPE_ALIGN_UNIT (s->field);
    1254            7 :           current_offset = (current_offset + align - 1) &~ (align - 1);
    1255              : 
    1256              :           /* Verify that it ended up where we expect it.  */
    1257            7 :           if (s->offset != current_offset)
    1258              :             {
    1259            1 :               gfc_error ("Equivalence for %qs does not match ordering of "
    1260              :                          "COMMON %qs at %L", sym->name,
    1261            1 :                          common->name, &common->where);
    1262              :             }
    1263              :         }
    1264              :       else
    1265              :         {
    1266              :           /* A symbol we haven't seen before.  */
    1267         5761 :           s = current_segment = get_segment_info (sym, current_offset);
    1268              : 
    1269              :           /* Add all objects directly or indirectly equivalenced with this
    1270              :              symbol.  */
    1271         5761 :           add_equivalences (&saw_equiv);
    1272              : 
    1273         5761 :           if (current_segment->offset < 0)
    1274            0 :             gfc_error ("The equivalence set for %qs cause an invalid "
    1275              :                        "extension to COMMON %qs at %L", sym->name,
    1276            0 :                        common->name, &common->where);
    1277              : 
    1278         5761 :           if (flag_align_commons)
    1279         5743 :             offset = align_segment (&align);
    1280              : 
    1281         5761 :           if (offset)
    1282              :             {
    1283              :               /* The required offset conflicts with previous alignment
    1284              :                  requirements.  Insert padding immediately before this
    1285              :                  segment.  */
    1286           37 :               if (warn_align_commons)
    1287              :                 {
    1288           35 :                   if (strcmp (common->name, BLANK_COMMON_NAME))
    1289           23 :                     gfc_warning (OPT_Walign_commons,
    1290              :                                  "Padding of %d bytes required before %qs in "
    1291              :                                  "COMMON %qs at %L; reorder elements or use "
    1292              :                                  "%<-fno-align-commons%>", (int)offset,
    1293           23 :                                  s->sym->name, common->name, &common->where);
    1294              :                   else
    1295           12 :                     gfc_warning (OPT_Walign_commons,
    1296              :                                  "Padding of %d bytes required before %qs in "
    1297              :                                  "COMMON at %L; reorder elements or use "
    1298              :                                  "%<-fno-align-commons%>", (int)offset,
    1299           12 :                                  s->sym->name, &common->where);
    1300              :                 }
    1301              :             }
    1302              : 
    1303              :           /* Apply the offset to the new segments.  */
    1304         5761 :           apply_segment_offset (current_segment, offset);
    1305         5761 :           current_offset += offset;
    1306              : 
    1307              :           /* Add the new segments to the common block.  */
    1308         5761 :           common_segment = add_segments (common_segment, current_segment);
    1309              :         }
    1310              : 
    1311              :       /* The offset of the next common variable.  */
    1312         5768 :       current_offset += s->length;
    1313              :     }
    1314              : 
    1315         1957 :   if (common_segment == NULL)
    1316              :     {
    1317            1 :       gfc_error ("COMMON %qs at %L does not exist",
    1318            1 :                  common->name, &common->where);
    1319            1 :       return;
    1320              :     }
    1321              : 
    1322         1956 :   if (common_segment->offset != 0 && warn_align_commons)
    1323              :     {
    1324            0 :       if (strcmp (common->name, BLANK_COMMON_NAME))
    1325            0 :         gfc_warning (OPT_Walign_commons,
    1326              :                      "COMMON %qs at %L requires %d bytes of padding; "
    1327              :                      "reorder elements or use %<-fno-align-commons%>",
    1328              :                      common->name, &common->where, (int)common_segment->offset);
    1329              :       else
    1330            0 :         gfc_warning (OPT_Walign_commons,
    1331              :                      "COMMON at %L requires %d bytes of padding; "
    1332              :                      "reorder elements or use %<-fno-align-commons%>",
    1333              :                      &common->where, (int)common_segment->offset);
    1334              :     }
    1335              : 
    1336         1956 :   create_common (common, common_segment, saw_equiv);
    1337              : }
    1338              : 
    1339              : 
    1340              : /* Create a new block for each merged equivalence list.  */
    1341              : 
    1342              : static void
    1343        93143 : finish_equivalences (gfc_namespace *ns)
    1344              : {
    1345        93143 :   gfc_equiv *z, *y;
    1346        93143 :   gfc_symbol *sym;
    1347        93143 :   gfc_common_head * c;
    1348        93143 :   HOST_WIDE_INT offset;
    1349        93143 :   unsigned HOST_WIDE_INT align;
    1350        93143 :   bool dummy;
    1351              : 
    1352        94659 :   for (z = ns->equiv; z; z = z->next)
    1353         2269 :     for (y = z->eq; y; y = y->eq)
    1354              :       {
    1355         1546 :         if (y->used)
    1356          753 :           continue;
    1357          793 :         sym = z->expr->symtree->n.sym;
    1358          793 :         current_segment = get_segment_info (sym, 0);
    1359              : 
    1360              :         /* All objects directly or indirectly equivalenced with this
    1361              :            symbol.  */
    1362          793 :         add_equivalences (&dummy);
    1363              : 
    1364              :         /* Align the block.  */
    1365          793 :         offset = align_segment (&align);
    1366              : 
    1367              :         /* Ensure all offsets are positive.  */
    1368          793 :         offset -= current_segment->offset & ~(align - 1);
    1369              : 
    1370          793 :         apply_segment_offset (current_segment, offset);
    1371              : 
    1372              :         /* Create the decl.  If this is a module equivalence, it has a
    1373              :            unique name, pointed to by z->module.  This is written to a
    1374              :            gfc_common_header to push create_common into using
    1375              :            build_common_decl, so that the equivalence appears as an
    1376              :            external symbol.  Otherwise, a local declaration is built using
    1377              :            build_equiv_decl.  */
    1378          793 :         if (z->module)
    1379              :           {
    1380          105 :             c = gfc_get_common_head ();
    1381              :             /* We've lost the real location, so use the location of the
    1382              :                enclosing procedure.  If we're in a BLOCK DATA block, then
    1383              :                use the location in the sym_root.  */
    1384          105 :             if (ns->proc_name)
    1385          104 :               c->where = ns->proc_name->declared_at;
    1386            1 :             else if (ns->is_block_data)
    1387            1 :               c->where = ns->sym_root->n.sym->declared_at;
    1388              : 
    1389          105 :             size_t len = strlen (z->module);
    1390          105 :             gcc_assert (len < sizeof (c->name));
    1391          105 :             memcpy (c->name, z->module, len);
    1392          105 :             c->name[len] = '\0';
    1393              :           }
    1394              :         else
    1395              :           c = NULL;
    1396              : 
    1397          793 :         create_common (c, current_segment, true);
    1398          793 :         break;
    1399              :       }
    1400        93143 : }
    1401              : 
    1402              : 
    1403              : /* Work function for translating a named common block.  */
    1404              : 
    1405              : static void
    1406         1771 : named_common (gfc_symtree *st)
    1407              : {
    1408         1771 :   translate_common (st->n.common, st->n.common->head);
    1409         1771 : }
    1410              : 
    1411              : 
    1412              : /* Translate the common blocks in a namespace. Unlike other variables,
    1413              :    these have to be created before code, because the backend_decl depends
    1414              :    on the rest of the common block.  */
    1415              : 
    1416              : void
    1417        93143 : gfc_trans_common (gfc_namespace *ns)
    1418              : {
    1419        93143 :   gfc_common_head *c;
    1420              : 
    1421              :   /* Translate the blank common block.  */
    1422        93143 :   if (ns->blank_common.head != NULL)
    1423              :     {
    1424          186 :       c = gfc_get_common_head ();
    1425          186 :       c->where = ns->blank_common.head->common_head->where;
    1426          186 :       strcpy (c->name, BLANK_COMMON_NAME);
    1427          186 :       translate_common (c, ns->blank_common.head);
    1428              :     }
    1429              : 
    1430              :   /* Translate all named common blocks.  */
    1431        93143 :   gfc_traverse_symtree (ns->common_root, named_common);
    1432              : 
    1433              :   /* Translate local equivalence.  */
    1434        93143 :   finish_equivalences (ns);
    1435              : 
    1436              :   /* Commit the newly created symbols for common blocks and module
    1437              :      equivalences.  */
    1438        93143 :   gfc_commit_symbols ();
    1439        93143 : }
        

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