LCOV - code coverage report
Current view: top level - gcc - attribs.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 714 774 92.2 %
Date: 2020-03-28 11:57:23 Functions: 43 45 95.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* Functions dealing with attribute handling, used by most front ends.
       2                 :            :    Copyright (C) 1992-2020 Free Software Foundation, Inc.
       3                 :            : 
       4                 :            : This file is part of GCC.
       5                 :            : 
       6                 :            : GCC is free software; you can redistribute it and/or modify it under
       7                 :            : the terms of the GNU General Public License as published by the Free
       8                 :            : Software Foundation; either version 3, or (at your option) any later
       9                 :            : version.
      10                 :            : 
      11                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14                 :            : for more details.
      15                 :            : 
      16                 :            : You should have received a copy of the GNU General Public License
      17                 :            : along with GCC; see the file COPYING3.  If not see
      18                 :            : <http://www.gnu.org/licenses/>.  */
      19                 :            : 
      20                 :            : #include "config.h"
      21                 :            : #include "system.h"
      22                 :            : #include "coretypes.h"
      23                 :            : #include "target.h"
      24                 :            : #include "tree.h"
      25                 :            : #include "stringpool.h"
      26                 :            : #include "diagnostic-core.h"
      27                 :            : #include "attribs.h"
      28                 :            : #include "stor-layout.h"
      29                 :            : #include "langhooks.h"
      30                 :            : #include "plugin.h"
      31                 :            : #include "selftest.h"
      32                 :            : #include "hash-set.h"
      33                 :            : #include "diagnostic.h"
      34                 :            : #include "pretty-print.h"
      35                 :            : #include "intl.h"
      36                 :            : 
      37                 :            : /* Table of the tables of attributes (common, language, format, machine)
      38                 :            :    searched.  */
      39                 :            : static const struct attribute_spec *attribute_tables[4];
      40                 :            : 
      41                 :            : /* Substring representation.  */
      42                 :            : 
      43                 :            : struct substring
      44                 :            : {
      45                 :            :   const char *str;
      46                 :            :   int length;
      47                 :            : };
      48                 :            : 
      49                 :            : /* Simple hash function to avoid need to scan whole string.  */
      50                 :            : 
      51                 :            : static inline hashval_t
      52                 :  779261000 : substring_hash (const char *str, int l)
      53                 :            : {
      54                 :  779261000 :   return str[0] + str[l - 1] * 256 + l * 65536;
      55                 :            : }
      56                 :            : 
      57                 :            : /* Used for attribute_hash.  */
      58                 :            : 
      59                 :            : struct attribute_hasher : nofree_ptr_hash <attribute_spec>
      60                 :            : {
      61                 :            :   typedef substring *compare_type;
      62                 :            :   static inline hashval_t hash (const attribute_spec *);
      63                 :            :   static inline bool equal (const attribute_spec *, const substring *);
      64                 :            : };
      65                 :            : 
      66                 :            : inline hashval_t
      67                 :            : attribute_hasher::hash (const attribute_spec *spec)
      68                 :            : {
      69                 :            :   const int l = strlen (spec->name);
      70                 :            :   return substring_hash (spec->name, l);
      71                 :            : }
      72                 :            : 
      73                 :            : inline bool
      74                 : 1269420000 : attribute_hasher::equal (const attribute_spec *spec, const substring *str)
      75                 :            : {
      76                 : 1269420000 :   return (strncmp (spec->name, str->str, str->length) == 0
      77                 : 1269420000 :           && !spec->name[str->length]);
      78                 :            : }
      79                 :            : 
      80                 :            : /* Scoped attribute name representation.  */
      81                 :            : 
      82                 :            : struct scoped_attributes
      83                 :            : {
      84                 :            :   const char *ns;
      85                 :            :   vec<attribute_spec> attributes;
      86                 :            :   hash_table<attribute_hasher> *attribute_hash;
      87                 :            : };
      88                 :            : 
      89                 :            : /* The table of scope attributes.  */
      90                 :            : static vec<scoped_attributes> attributes_table;
      91                 :            : 
      92                 :            : static scoped_attributes* find_attribute_namespace (const char*);
      93                 :            : static void register_scoped_attribute (const struct attribute_spec *,
      94                 :            :                                        scoped_attributes *);
      95                 :            : 
      96                 :            : static bool attributes_initialized = false;
      97                 :            : 
      98                 :            : /* Default empty table of attributes.  */
      99                 :            : 
     100                 :            : static const struct attribute_spec empty_attribute_table[] =
     101                 :            : {
     102                 :            :   { NULL, 0, 0, false, false, false, false, NULL, NULL }
     103                 :            : };
     104                 :            : 
     105                 :            : /* Return base name of the attribute.  Ie '__attr__' is turned into 'attr'.
     106                 :            :    To avoid need for copying, we simply return length of the string.  */
     107                 :            : 
     108                 :            : static void
     109                 :  757416000 : extract_attribute_substring (struct substring *str)
     110                 :            : {
     111                 :  757416000 :   if (str->length > 4 && str->str[0] == '_' && str->str[1] == '_'
     112                 :         17 :       && str->str[str->length - 1] == '_' && str->str[str->length - 2] == '_')
     113                 :            :     {
     114                 :         16 :       str->length -= 4;
     115                 :         16 :       str->str += 2;
     116                 :            :     }
     117                 :  757416000 : }
     118                 :            : 
     119                 :            : /* Insert an array of attributes ATTRIBUTES into a namespace.  This
     120                 :            :    array must be NULL terminated.  NS is the name of attribute
     121                 :            :    namespace.  The function returns the namespace into which the
     122                 :            :    attributes have been registered.  */
     123                 :            : 
     124                 :            : scoped_attributes *
     125                 :     954692 : register_scoped_attributes (const struct attribute_spec *attributes,
     126                 :            :                             const char *ns)
     127                 :            : {
     128                 :     954692 :   scoped_attributes *result = NULL;
     129                 :            : 
     130                 :            :   /* See if we already have attributes in the namespace NS.  */
     131                 :     954692 :   result = find_attribute_namespace (ns);
     132                 :            : 
     133                 :     954692 :   if (result == NULL)
     134                 :            :     {
     135                 :            :       /* We don't have any namespace NS yet.  Create one.  */
     136                 :     356300 :       scoped_attributes sa;
     137                 :            : 
     138                 :     356300 :       if (attributes_table.is_empty ())
     139                 :     199464 :         attributes_table.create (64);
     140                 :            : 
     141                 :     356300 :       memset (&sa, 0, sizeof (sa));
     142                 :     356300 :       sa.ns = ns;
     143                 :     356300 :       sa.attributes.create (64);
     144                 :     356300 :       result = attributes_table.safe_push (sa);
     145                 :     356300 :       result->attribute_hash = new hash_table<attribute_hasher> (200);
     146                 :            :     }
     147                 :            : 
     148                 :            :   /* Really add the attributes to their namespace now.  */
     149                 :   22800300 :   for (unsigned i = 0; attributes[i].name != NULL; ++i)
     150                 :            :     {
     151                 :   21845600 :       result->attributes.safe_push (attributes[i]);
     152                 :   21845600 :       register_scoped_attribute (&attributes[i], result);
     153                 :            :     }
     154                 :            : 
     155                 :     954692 :   gcc_assert (result != NULL);
     156                 :            : 
     157                 :     954692 :   return result;
     158                 :            : }
     159                 :            : 
     160                 :            : /* Return the namespace which name is NS, NULL if none exist.  */
     161                 :            : 
     162                 :            : static scoped_attributes*
     163                 :  758550000 : find_attribute_namespace (const char* ns)
     164                 :            : {
     165                 :  758550000 :   unsigned ix;
     166                 :  758550000 :   scoped_attributes *iter;
     167                 :            : 
     168                 : 1463720000 :   FOR_EACH_VEC_ELT (attributes_table, ix, iter)
     169                 : 1463180000 :     if (ns == iter->ns
     170                 : 1462520000 :         || (iter->ns != NULL
     171                 :  757349000 :             && ns != NULL
     172                 :  757349000 :             && !strcmp (iter->ns, ns)))
     173                 :  758014000 :       return iter;
     174                 :            :   return NULL;
     175                 :            : }
     176                 :            : 
     177                 :            : /* Make some sanity checks on the attribute tables.  */
     178                 :            : 
     179                 :            : static void
     180                 :     199451 : check_attribute_tables (void)
     181                 :            : {
     182                 :     997255 :   for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     183                 :   21936500 :     for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
     184                 :            :       {
     185                 :            :         /* The name must not begin and end with __.  */
     186                 :   21138700 :         const char *name = attribute_tables[i][j].name;
     187                 :   21138700 :         int len = strlen (name);
     188                 :            : 
     189                 :   21138700 :         gcc_assert (!(name[0] == '_' && name[1] == '_'
     190                 :            :                       && name[len - 1] == '_' && name[len - 2] == '_'));
     191                 :            : 
     192                 :            :         /* The minimum and maximum lengths must be consistent.  */
     193                 :   21138700 :         gcc_assert (attribute_tables[i][j].min_length >= 0);
     194                 :            : 
     195                 :   21138700 :         gcc_assert (attribute_tables[i][j].max_length == -1
     196                 :            :                     || (attribute_tables[i][j].max_length
     197                 :            :                         >= attribute_tables[i][j].min_length));
     198                 :            : 
     199                 :            :         /* An attribute cannot require both a DECL and a TYPE.  */
     200                 :   21138700 :         gcc_assert (!attribute_tables[i][j].decl_required
     201                 :            :                     || !attribute_tables[i][j].type_required);
     202                 :            : 
     203                 :            :           /* If an attribute requires a function type, in particular
     204                 :            :              it requires a type.  */
     205                 :   21138700 :         gcc_assert (!attribute_tables[i][j].function_type_required
     206                 :            :                     || attribute_tables[i][j].type_required);
     207                 :            :       }
     208                 :            : 
     209                 :            :   /* Check that each name occurs just once in each table.  */
     210                 :     997255 :   for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     211                 :   21936500 :     for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
     212                 :  828149000 :       for (size_t k = j + 1; attribute_tables[i][k].name != NULL; k++)
     213                 :  807011000 :         gcc_assert (strcmp (attribute_tables[i][j].name,
     214                 :            :                             attribute_tables[i][k].name));
     215                 :            : 
     216                 :            :   /* Check that no name occurs in more than one table.  Names that
     217                 :            :      begin with '*' are exempt, and may be overridden.  */
     218                 :     997255 :   for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     219                 :    1994510 :     for (size_t j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
     220                 :   48738700 :       for (size_t k = 0; attribute_tables[i][k].name != NULL; k++)
     221                 :  498157000 :         for (size_t l = 0; attribute_tables[j][l].name != NULL; l++)
     222                 :  450615000 :           gcc_assert (attribute_tables[i][k].name[0] == '*'
     223                 :            :                       || strcmp (attribute_tables[i][k].name,
     224                 :            :                                  attribute_tables[j][l].name));
     225                 :     199451 : }
     226                 :            : 
     227                 :            : /* Initialize attribute tables, and make some sanity checks if checking is
     228                 :            :    enabled.  */
     229                 :            : 
     230                 :            : void
     231                 :     277969 : init_attributes (void)
     232                 :            : {
     233                 :     277969 :   size_t i;
     234                 :            : 
     235                 :     277969 :   if (attributes_initialized)
     236                 :            :     return;
     237                 :            : 
     238                 :     199464 :   attribute_tables[0] = lang_hooks.common_attribute_table;
     239                 :     199464 :   attribute_tables[1] = lang_hooks.attribute_table;
     240                 :     199464 :   attribute_tables[2] = lang_hooks.format_attribute_table;
     241                 :     199464 :   attribute_tables[3] = targetm.attribute_table;
     242                 :            : 
     243                 :            :   /* Translate NULL pointers to pointers to the empty table.  */
     244                 :     997320 :   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
     245                 :     797856 :     if (attribute_tables[i] == NULL)
     246                 :     153291 :       attribute_tables[i] = empty_attribute_table;
     247                 :            : 
     248                 :     199464 :   if (flag_checking)
     249                 :     199451 :     check_attribute_tables ();
     250                 :            : 
     251                 :     997320 :   for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
     252                 :            :     /* Put all the GNU attributes into the "gnu" namespace.  */
     253                 :     797856 :     register_scoped_attributes (attribute_tables[i], "gnu");
     254                 :            : 
     255                 :     199464 :   invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
     256                 :     199464 :   attributes_initialized = true;
     257                 :            : }
     258                 :            : 
     259                 :            : /* Insert a single ATTR into the attribute table.  */
     260                 :            : 
     261                 :            : void
     262                 :          1 : register_attribute (const struct attribute_spec *attr)
     263                 :            : {
     264                 :          1 :   register_scoped_attribute (attr, find_attribute_namespace ("gnu"));
     265                 :          1 : }
     266                 :            : 
     267                 :            : /* Insert a single attribute ATTR into a namespace of attributes.  */
     268                 :            : 
     269                 :            : static void
     270                 :   21845600 : register_scoped_attribute (const struct attribute_spec *attr,
     271                 :            :                            scoped_attributes *name_space)
     272                 :            : {
     273                 :   21845600 :   struct substring str;
     274                 :   21845600 :   attribute_spec **slot;
     275                 :            : 
     276                 :   21845600 :   gcc_assert (attr != NULL && name_space != NULL);
     277                 :            : 
     278                 :   21845600 :   gcc_assert (name_space->attribute_hash);
     279                 :            : 
     280                 :   21845600 :   str.str = attr->name;
     281                 :   21845600 :   str.length = strlen (str.str);
     282                 :            : 
     283                 :            :   /* Attribute names in the table must be in the form 'text' and not
     284                 :            :      in the form '__text__'.  */
     285                 :   21845600 :   gcc_assert (str.length > 0 && str.str[0] != '_');
     286                 :            : 
     287                 :   21845600 :   slot = name_space->attribute_hash
     288                 :   21845600 :          ->find_slot_with_hash (&str, substring_hash (str.str, str.length),
     289                 :            :                                 INSERT);
     290                 :   21845600 :   gcc_assert (!*slot || attr->name[0] == '*');
     291                 :   21845600 :   *slot = CONST_CAST (struct attribute_spec *, attr);
     292                 :   21845600 : }
     293                 :            : 
     294                 :            : /* Return the spec for the scoped attribute with namespace NS and
     295                 :            :    name NAME.   */
     296                 :            : 
     297                 :            : static const struct attribute_spec *
     298                 :  757596000 : lookup_scoped_attribute_spec (const_tree ns, const_tree name)
     299                 :            : {
     300                 :  757596000 :   struct substring attr;
     301                 :  757596000 :   scoped_attributes *attrs;
     302                 :            : 
     303                 : 1515120000 :   const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL;
     304                 :            : 
     305                 :  757596000 :   attrs = find_attribute_namespace (ns_str);
     306                 :            : 
     307                 :  757596000 :   if (attrs == NULL)
     308                 :            :     return NULL;
     309                 :            : 
     310                 :  757416000 :   attr.str = IDENTIFIER_POINTER (name);
     311                 :  757416000 :   attr.length = IDENTIFIER_LENGTH (name);
     312                 :  757416000 :   extract_attribute_substring (&attr);
     313                 : 1514830000 :   return attrs->attribute_hash->find_with_hash (&attr,
     314                 :            :                                                 substring_hash (attr.str,
     315                 :  757416000 :                                                                 attr.length));
     316                 :            : }
     317                 :            : 
     318                 :            : /* Return the spec for the attribute named NAME.  If NAME is a TREE_LIST,
     319                 :            :    it also specifies the attribute namespace.  */
     320                 :            : 
     321                 :            : const struct attribute_spec *
     322                 :   54495300 : lookup_attribute_spec (const_tree name)
     323                 :            : {
     324                 :   54495300 :   tree ns;
     325                 :   54495300 :   if (TREE_CODE (name) == TREE_LIST)
     326                 :            :     {
     327                 :      52424 :       ns = TREE_PURPOSE (name);
     328                 :      52424 :       name = TREE_VALUE (name);
     329                 :            :     }
     330                 :            :   else
     331                 :   54442900 :     ns = get_identifier ("gnu");
     332                 :   54495300 :   return lookup_scoped_attribute_spec (ns, name);
     333                 :            : }
     334                 :            : 
     335                 :            : 
     336                 :            : /* Return the namespace of the attribute ATTR.  This accessor works on
     337                 :            :    GNU and C++11 (scoped) attributes.  On GNU attributes,
     338                 :            :    it returns an identifier tree for the string "gnu".
     339                 :            : 
     340                 :            :    Please read the comments of cxx11_attribute_p to understand the
     341                 :            :    format of attributes.  */
     342                 :            : 
     343                 :            : tree
     344                 :  703108000 : get_attribute_namespace (const_tree attr)
     345                 :            : {
     346                 :  703108000 :   if (cxx11_attribute_p (attr))
     347                 :     168499 :     return TREE_PURPOSE (TREE_PURPOSE (attr));
     348                 :  702940000 :   return get_identifier ("gnu");
     349                 :            : }
     350                 :            : 
     351                 :            : /* Check LAST_DECL and NODE of the same symbol for attributes that are
     352                 :            :    recorded in SPEC to be mutually exclusive with ATTRNAME, diagnose
     353                 :            :    them, and return true if any have been found.  NODE can be a DECL
     354                 :            :    or a TYPE.  */
     355                 :            : 
     356                 :            : static bool
     357                 :  161946000 : diag_attr_exclusions (tree last_decl, tree node, tree attrname,
     358                 :            :                       const attribute_spec *spec)
     359                 :            : {
     360                 :  161946000 :   const attribute_spec::exclusions *excl = spec->exclude;
     361                 :            : 
     362                 :  161946000 :   tree_code code = TREE_CODE (node);
     363                 :            : 
     364                 :  161946000 :   if ((code == FUNCTION_DECL && !excl->function
     365                 :          0 :        && (!excl->type || !spec->affects_type_identity))
     366                 :  161946000 :       || (code == VAR_DECL && !excl->variable
     367                 :            :           && (!excl->type || !spec->affects_type_identity))
     368                 :  161942000 :       || (((code == TYPE_DECL || RECORD_OR_UNION_TYPE_P (node)) && !excl->type)))
     369                 :            :     return false;
     370                 :            : 
     371                 :            :   /* True if an attribute that's mutually exclusive with ATTRNAME
     372                 :            :      has been found.  */
     373                 :  161832000 :   bool found = false;
     374                 :            : 
     375                 :  163491000 :   if (last_decl && last_decl != node && TREE_TYPE (last_decl) != node)
     376                 :            :     {
     377                 :            :       /* Check both the last DECL and its type for conflicts with
     378                 :            :          the attribute being added to the current decl or type.  */
     379                 :     829347 :       found |= diag_attr_exclusions (last_decl, last_decl, attrname, spec);
     380                 :     829347 :       tree decl_type = TREE_TYPE (last_decl);
     381                 :     829347 :       found |= diag_attr_exclusions (last_decl, decl_type, attrname, spec);
     382                 :            :     }
     383                 :            : 
     384                 :            :   /* NODE is either the current DECL to which the attribute is being
     385                 :            :      applied or its TYPE.  For the former, consider the attributes on
     386                 :            :      both the DECL and its type.  */
     387                 :  161832000 :   tree attrs[2];
     388                 :            : 
     389                 :  161832000 :   if (DECL_P (node))
     390                 :            :     {
     391                 :  157326000 :       attrs[0] = DECL_ATTRIBUTES (node);
     392                 :  157326000 :       attrs[1] = TYPE_ATTRIBUTES (TREE_TYPE (node));
     393                 :            :     }
     394                 :            :   else
     395                 :            :     {
     396                 :    4505880 :       attrs[0] = TYPE_ATTRIBUTES (node);
     397                 :    4505880 :       attrs[1] = NULL_TREE;
     398                 :            :     }
     399                 :            : 
     400                 :            :   /* Iterate over the mutually exclusive attribute names and verify
     401                 :            :      that the symbol doesn't contain it.  */
     402                 :  485496000 :   for (unsigned i = 0; i != sizeof attrs / sizeof *attrs; ++i)
     403                 :            :     {
     404                 :  323664000 :       if (!attrs[i])
     405                 :  278186000 :         continue;
     406                 :            : 
     407                 :  124931000 :       for ( ; excl->name; ++excl)
     408                 :            :         {
     409                 :            :           /* Avoid checking the attribute against itself.  */
     410                 :   79453300 :           if (is_attribute_p (excl->name, attrname))
     411                 :   79452800 :             continue;
     412                 :            : 
     413                 :   71238000 :           if (!lookup_attribute (excl->name, attrs[i]))
     414                 :   71236800 :             continue;
     415                 :            : 
     416                 :            :           /* An exclusion may apply either to a function declaration,
     417                 :            :              type declaration, or a field/variable declaration, or
     418                 :            :              any subset of the three.  */
     419                 :       1142 :           if (TREE_CODE (node) == FUNCTION_DECL
     420                 :        399 :               && !excl->function)
     421                 :          0 :             continue;
     422                 :            : 
     423                 :       1142 :           if (TREE_CODE (node) == TYPE_DECL
     424                 :          0 :               && !excl->type)
     425                 :          0 :             continue;
     426                 :            : 
     427                 :       1142 :           if ((TREE_CODE (node) == FIELD_DECL
     428                 :       1142 :                || TREE_CODE (node) == VAR_DECL)
     429                 :        717 :               && !excl->variable)
     430                 :        692 :             continue;
     431                 :            : 
     432                 :        450 :           found = true;
     433                 :            : 
     434                 :            :           /* Print a note?  */
     435                 :        450 :           bool note = last_decl != NULL_TREE;
     436                 :        900 :           auto_diagnostic_group d;
     437                 :        450 :           if (TREE_CODE (node) == FUNCTION_DECL
     438                 :        450 :               && fndecl_built_in_p (node))
     439                 :          0 :             note &= warning (OPT_Wattributes,
     440                 :            :                              "ignoring attribute %qE in declaration of "
     441                 :            :                              "a built-in function %qD because it conflicts "
     442                 :            :                              "with attribute %qs",
     443                 :          0 :                              attrname, node, excl->name);
     444                 :            :           else
     445                 :        450 :             note &= warning (OPT_Wattributes,
     446                 :            :                              "ignoring attribute %qE because "
     447                 :            :                              "it conflicts with attribute %qs",
     448                 :        450 :                              attrname, excl->name);
     449                 :            : 
     450                 :        450 :           if (note)
     451                 :        219 :             inform (DECL_SOURCE_LOCATION (last_decl),
     452                 :            :                     "previous declaration here");
     453                 :            :         }
     454                 :            :     }
     455                 :            : 
     456                 :            :   return found;
     457                 :            : }
     458                 :            : 
     459                 :            : /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
     460                 :            :    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
     461                 :            :    it should be modified in place; if a TYPE, a copy should be created
     462                 :            :    unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
     463                 :            :    information, in the form of a bitwise OR of flags in enum attribute_flags
     464                 :            :    from tree.h.  Depending on these flags, some attributes may be
     465                 :            :    returned to be applied at a later stage (for example, to apply
     466                 :            :    a decl attribute to the declaration rather than to its type).  */
     467                 :            : 
     468                 :            : tree
     469                 :  848618000 : decl_attributes (tree *node, tree attributes, int flags,
     470                 :            :                  tree last_decl /* = NULL_TREE */)
     471                 :            : {
     472                 :  848618000 :   tree returned_attrs = NULL_TREE;
     473                 :            : 
     474                 :  848618000 :   if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
     475                 :            :     return NULL_TREE;
     476                 :            : 
     477                 :  848617000 :   if (!attributes_initialized)
     478                 :     199464 :     init_attributes ();
     479                 :            : 
     480                 :            :   /* If this is a function and the user used #pragma GCC optimize, add the
     481                 :            :      options to the attribute((optimize(...))) list.  */
     482                 :  848617000 :   if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
     483                 :            :     {
     484                 :       1410 :       tree cur_attr = lookup_attribute ("optimize", attributes);
     485                 :       1410 :       tree opts = copy_list (current_optimize_pragma);
     486                 :            : 
     487                 :       1410 :       if (! cur_attr)
     488                 :       1410 :         attributes
     489                 :       1410 :           = tree_cons (get_identifier ("optimize"), opts, attributes);
     490                 :            :       else
     491                 :          0 :         TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
     492                 :            :     }
     493                 :            : 
     494                 :  848617000 :   if (TREE_CODE (*node) == FUNCTION_DECL
     495                 :  492443000 :       && optimization_current_node != optimization_default_node
     496                 :  848617000 :       && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
     497                 :        256 :     DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
     498                 :            : 
     499                 :            :   /* If this is a function and the user used #pragma GCC target, add the
     500                 :            :      options to the attribute((target(...))) list.  */
     501                 :  848617000 :   if (TREE_CODE (*node) == FUNCTION_DECL
     502                 :  492443000 :       && current_target_pragma
     503                 :  860336000 :       && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
     504                 :            :                                                   current_target_pragma, 0))
     505                 :            :     {
     506                 :   11719200 :       tree cur_attr = lookup_attribute ("target", attributes);
     507                 :   11719200 :       tree opts = copy_list (current_target_pragma);
     508                 :            : 
     509                 :   11719200 :       if (! cur_attr)
     510                 :   11719200 :         attributes = tree_cons (get_identifier ("target"), opts, attributes);
     511                 :            :       else
     512                 :          0 :         TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
     513                 :            :     }
     514                 :            : 
     515                 :            :   /* A "naked" function attribute implies "noinline" and "noclone" for
     516                 :            :      those targets that support it.  */
     517                 :  848617000 :   if (TREE_CODE (*node) == FUNCTION_DECL
     518                 :  492443000 :       && attributes
     519                 :  263750000 :       && lookup_attribute ("naked", attributes) != NULL
     520                 :  848617000 :       && lookup_attribute_spec (get_identifier ("naked")))
     521                 :            :     {
     522                 :         78 :       if (lookup_attribute ("noinline", attributes) == NULL)
     523                 :         77 :         attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
     524                 :            : 
     525                 :         78 :       if (lookup_attribute ("noclone", attributes) == NULL)
     526                 :         77 :         attributes = tree_cons (get_identifier ("noclone"),  NULL, attributes);
     527                 :            :     }
     528                 :            : 
     529                 :            :   /* A "noipa" function attribute implies "noinline", "noclone" and "no_icf"
     530                 :            :      for those targets that support it.  */
     531                 :  848617000 :   if (TREE_CODE (*node) == FUNCTION_DECL
     532                 :  492443000 :       && attributes
     533                 :  263750000 :       && lookup_attribute ("noipa", attributes) != NULL
     534                 :  848622000 :       && lookup_attribute_spec (get_identifier ("noipa")))
     535                 :            :     {
     536                 :       4456 :       if (lookup_attribute ("noinline", attributes) == NULL)
     537                 :       4167 :         attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
     538                 :            : 
     539                 :       4456 :       if (lookup_attribute ("noclone", attributes) == NULL)
     540                 :       4228 :         attributes = tree_cons (get_identifier ("noclone"),  NULL, attributes);
     541                 :            : 
     542                 :       4456 :       if (lookup_attribute ("no_icf", attributes) == NULL)
     543                 :       4456 :         attributes = tree_cons (get_identifier ("no_icf"),  NULL, attributes);
     544                 :            :     }
     545                 :            : 
     546                 :  848617000 :   targetm.insert_attributes (*node, &attributes);
     547                 :            : 
     548                 :            :   /* Note that attributes on the same declaration are not necessarily
     549                 :            :      in the same order as in the source.  */
     550                 : 1551720000 :   for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
     551                 :            :     {
     552                 :  703100000 :       tree ns = get_attribute_namespace (attr);
     553                 :  703100000 :       tree name = get_attribute_name (attr);
     554                 :  703100000 :       tree args = TREE_VALUE (attr);
     555                 :  703100000 :       tree *anode = node;
     556                 :  703100000 :       const struct attribute_spec *spec
     557                 :  703100000 :         = lookup_scoped_attribute_spec (ns, name);
     558                 :  703100000 :       int fn_ptr_quals = 0;
     559                 :  703100000 :       tree fn_ptr_tmp = NULL_TREE;
     560                 :  703100000 :       const bool cxx11_attr_p = cxx11_attribute_p (attr);
     561                 :            : 
     562                 :  703100000 :       if (spec == NULL)
     563                 :            :         {
     564                 :     683769 :           if (!(flags & (int) ATTR_FLAG_BUILT_IN))
     565                 :            :             {
     566                 :        210 :               if (ns == NULL_TREE || !cxx11_attr_p)
     567                 :        115 :                 warning (OPT_Wattributes, "%qE attribute directive ignored",
     568                 :            :                          name);
     569                 :            :               else
     570                 :         95 :                 warning (OPT_Wattributes,
     571                 :            :                          "%<%E::%E%> scoped attribute directive ignored",
     572                 :            :                          ns, name);
     573                 :            :             }
     574                 :     689434 :           continue;
     575                 :            :         }
     576                 :            :       else
     577                 :            :         {
     578                 :  702417000 :           int nargs = list_length (args);
     579                 :  702417000 :           if (nargs < spec->min_length
     580                 :  702417000 :               || (spec->max_length >= 0
     581                 :  654367000 :                   && nargs > spec->max_length))
     582                 :            :             {
     583                 :         47 :               error ("wrong number of arguments specified for %qE attribute",
     584                 :            :                      name);
     585                 :         47 :               if (spec->max_length < 0)
     586                 :          0 :                 inform (input_location, "expected %i or more, found %i",
     587                 :          0 :                         spec->min_length, nargs);
     588                 :            :               else
     589                 :         47 :                 inform (input_location, "expected between %i and %i, found %i",
     590                 :         47 :                         spec->min_length, spec->max_length, nargs);
     591                 :         47 :               continue;
     592                 :            :             }
     593                 :            :         }
     594                 :  702417000 :       gcc_assert (is_attribute_p (spec->name, name));
     595                 :            : 
     596                 :  702417000 :       if (spec->decl_required && !DECL_P (*anode))
     597                 :            :         {
     598                 :       4956 :           if (flags & ((int) ATTR_FLAG_DECL_NEXT
     599                 :            :                        | (int) ATTR_FLAG_FUNCTION_NEXT
     600                 :            :                        | (int) ATTR_FLAG_ARRAY_NEXT))
     601                 :            :             {
     602                 :            :               /* Pass on this attribute to be tried again.  */
     603                 :       4925 :               tree attr = tree_cons (name, args, NULL_TREE);
     604                 :       4925 :               returned_attrs = chainon (returned_attrs, attr);
     605                 :       4925 :               continue;
     606                 :            :             }
     607                 :            :           else
     608                 :            :             {
     609                 :         31 :               warning (OPT_Wattributes, "%qE attribute does not apply to types",
     610                 :            :                        name);
     611                 :         31 :               continue;
     612                 :            :             }
     613                 :            :         }
     614                 :            : 
     615                 :            :       /* If we require a type, but were passed a decl, set up to make a
     616                 :            :          new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
     617                 :            :          would have applied if we'd been passed a type, but we cannot modify
     618                 :            :          the decl's type in place here.  */
     619                 :  702412000 :       if (spec->type_required && DECL_P (*anode))
     620                 :            :         {
     621                 :   63119000 :           anode = &TREE_TYPE (*anode);
     622                 :   63119000 :           flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
     623                 :            :         }
     624                 :            : 
     625                 :  702412000 :       if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
     626                 :      47196 :           && TREE_CODE (*anode) != METHOD_TYPE)
     627                 :            :         {
     628                 :        470 :           if (TREE_CODE (*anode) == POINTER_TYPE
     629                 :        470 :               && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
     630                 :        177 :                   || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
     631                 :            :             {
     632                 :            :               /* OK, this is a bit convoluted.  We can't just make a copy
     633                 :            :                  of the pointer type and modify its TREE_TYPE, because if
     634                 :            :                  we change the attributes of the target type the pointer
     635                 :            :                  type needs to have a different TYPE_MAIN_VARIANT.  So we
     636                 :            :                  pull out the target type now, frob it as appropriate, and
     637                 :            :                  rebuild the pointer type later.
     638                 :            : 
     639                 :            :                  This would all be simpler if attributes were part of the
     640                 :            :                  declarator, grumble grumble.  */
     641                 :        257 :               fn_ptr_tmp = TREE_TYPE (*anode);
     642                 :        257 :               fn_ptr_quals = TYPE_QUALS (*anode);
     643                 :        257 :               anode = &fn_ptr_tmp;
     644                 :        257 :               flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
     645                 :            :             }
     646                 :        213 :           else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
     647                 :            :             {
     648                 :            :               /* Pass on this attribute to be tried again.  */
     649                 :        160 :               tree attr = tree_cons (name, args, NULL_TREE);
     650                 :        160 :               returned_attrs = chainon (returned_attrs, attr);
     651                 :        160 :               continue;
     652                 :            :             }
     653                 :            : 
     654                 :        363 :           if (TREE_CODE (*anode) != FUNCTION_TYPE
     655                 :        310 :               && TREE_CODE (*anode) != METHOD_TYPE)
     656                 :            :             {
     657                 :         53 :               warning (OPT_Wattributes,
     658                 :            :                        "%qE attribute only applies to function types",
     659                 :            :                        name);
     660                 :         53 :               continue;
     661                 :            :             }
     662                 :            :         }
     663                 :            : 
     664                 :  702411000 :       if (TYPE_P (*anode)
     665                 :   63169000 :           && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
     666                 :  702446000 :           && TYPE_SIZE (*anode) != NULL_TREE)
     667                 :            :         {
     668                 :         11 :           warning (OPT_Wattributes, "type attributes ignored after type is already defined");
     669                 :         11 :           continue;
     670                 :            :         }
     671                 :            : 
     672                 :  702411000 :       bool no_add_attrs = false;
     673                 :            : 
     674                 :            :       /* Check for exclusions with other attributes on the current
     675                 :            :          declation as well as the last declaration of the same
     676                 :            :          symbol already processed (if one exists).  Detect and
     677                 :            :          reject incompatible attributes.  */
     678                 :  702411000 :       bool built_in = flags & ATTR_FLAG_BUILT_IN;
     679                 :  702411000 :       if (spec->exclude
     680                 :  157157000 :           && (flag_checking || !built_in))
     681                 :            :         {
     682                 :            :           /* Always check attributes on user-defined functions.
     683                 :            :              Check them on built-ins only when -fchecking is set.
     684                 :            :              Ignore __builtin_unreachable -- it's both const and
     685                 :            :              noreturn.  */
     686                 :            : 
     687                 :  157148000 :           if (!built_in
     688                 :  113833000 :               || !DECL_P (*anode)
     689                 :  110285000 :               || DECL_BUILT_IN_CLASS (*anode) != BUILT_IN_NORMAL
     690                 :  267433000 :               || (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE
     691                 :  109786000 :                   && (DECL_FUNCTION_CODE (*anode)
     692                 :            :                       != BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE)))
     693                 :            :             {
     694                 :  156611000 :               bool no_add = diag_attr_exclusions (last_decl, *anode, name, spec);
     695                 :  156611000 :               if (!no_add && anode != node)
     696                 :    3676170 :                 no_add = diag_attr_exclusions (last_decl, *node, name, spec);
     697                 :  156611000 :               no_add_attrs |= no_add;
     698                 :            :             }
     699                 :            :         }
     700                 :            : 
     701                 :  702411000 :       if (no_add_attrs)
     702                 :        438 :         continue;
     703                 :            : 
     704                 :  702411000 :       if (spec->handler != NULL)
     705                 :            :         {
     706                 :  702297000 :           int cxx11_flag = (cxx11_attr_p ? ATTR_FLAG_CXX11 : 0);
     707                 :            : 
     708                 :            :           /* Pass in an array of the current declaration followed
     709                 :            :              by the last pushed/merged declaration if  one exists.
     710                 :            :              If the handler changes CUR_AND_LAST_DECL[0] replace
     711                 :            :              *ANODE with its value.  */
     712                 :  702297000 :           tree cur_and_last_decl[] = { *anode, last_decl };
     713                 :  702297000 :           tree ret = (spec->handler) (cur_and_last_decl, name, args,
     714                 :            :                                       flags|cxx11_flag, &no_add_attrs);
     715                 :            : 
     716                 :  702297000 :           *anode = cur_and_last_decl[0];
     717                 :  702297000 :           if (ret == error_mark_node)
     718                 :            :             {
     719                 :          0 :               warning (OPT_Wattributes, "%qE attribute ignored", name);
     720                 :          0 :               no_add_attrs = true;
     721                 :            :             }
     722                 :            :           else
     723                 :  702297000 :             returned_attrs = chainon (ret, returned_attrs);
     724                 :            :         }
     725                 :            : 
     726                 :            :       /* Layout the decl in case anything changed.  */
     727                 :  702411000 :       if (spec->type_required && DECL_P (*node)
     728                 :   63118800 :           && (VAR_P (*node)
     729                 :   63116700 :               || TREE_CODE (*node) == PARM_DECL
     730                 :   63116400 :               || TREE_CODE (*node) == RESULT_DECL))
     731                 :       2480 :         relayout_decl (*node);
     732                 :            : 
     733                 :  702411000 :       if (!no_add_attrs)
     734                 :            :         {
     735                 :  700610000 :           tree old_attrs;
     736                 :  700610000 :           tree a;
     737                 :            : 
     738                 :  700610000 :           if (DECL_P (*anode))
     739                 :  638680000 :             old_attrs = DECL_ATTRIBUTES (*anode);
     740                 :            :           else
     741                 :   61929500 :             old_attrs = TYPE_ATTRIBUTES (*anode);
     742                 :            : 
     743                 :  700612000 :           for (a = lookup_attribute (spec->name, old_attrs);
     744                 :  700612000 :                a != NULL_TREE;
     745                 :       2775 :                a = lookup_attribute (spec->name, TREE_CHAIN (a)))
     746                 :            :             {
     747                 :    3139510 :               if (simple_cst_equal (TREE_VALUE (a), args) == 1)
     748                 :            :                 break;
     749                 :            :             }
     750                 :            : 
     751                 :  700610000 :           if (a == NULL_TREE)
     752                 :            :             {
     753                 :            :               /* This attribute isn't already in the list.  */
     754                 :  697473000 :               tree r;
     755                 :            :               /* Preserve the C++11 form.  */
     756                 :  697473000 :               if (cxx11_attr_p)
     757                 :      79773 :                 r = tree_cons (build_tree_list (ns, name), args, old_attrs);
     758                 :            :               else
     759                 :  697393000 :                 r = tree_cons (name, args, old_attrs);
     760                 :            : 
     761                 :  697473000 :               if (DECL_P (*anode))
     762                 :  635589000 :                 DECL_ATTRIBUTES (*anode) = r;
     763                 :   61883500 :               else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
     764                 :            :                 {
     765                 :      23063 :                   TYPE_ATTRIBUTES (*anode) = r;
     766                 :            :                   /* If this is the main variant, also push the attributes
     767                 :            :                      out to the other variants.  */
     768                 :      23063 :                   if (*anode == TYPE_MAIN_VARIANT (*anode))
     769                 :            :                     {
     770                 :      71077 :                       for (tree variant = *anode; variant;
     771                 :      24007 :                            variant = TYPE_NEXT_VARIANT (variant))
     772                 :            :                         {
     773                 :      24007 :                           if (TYPE_ATTRIBUTES (variant) == old_attrs)
     774                 :        944 :                             TYPE_ATTRIBUTES (variant)
     775                 :        944 :                               = TYPE_ATTRIBUTES (*anode);
     776                 :      23063 :                           else if (!lookup_attribute
     777                 :      23063 :                                    (spec->name, TYPE_ATTRIBUTES (variant)))
     778                 :          0 :                             TYPE_ATTRIBUTES (variant) = tree_cons
     779                 :          0 :                               (name, args, TYPE_ATTRIBUTES (variant));
     780                 :            :                         }
     781                 :            :                     }
     782                 :            :                 }
     783                 :            :               else
     784                 :   61860400 :                 *anode = build_type_attribute_variant (*anode, r);
     785                 :            :             }
     786                 :            :         }
     787                 :            : 
     788                 :  702411000 :       if (fn_ptr_tmp)
     789                 :            :         {
     790                 :            :           /* Rebuild the function pointer type and put it in the
     791                 :            :              appropriate place.  */
     792                 :        257 :           fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
     793                 :        257 :           if (fn_ptr_quals)
     794                 :         23 :             fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
     795                 :        257 :           if (DECL_P (*node))
     796                 :        237 :             TREE_TYPE (*node) = fn_ptr_tmp;
     797                 :            :           else
     798                 :            :             {
     799                 :         20 :               gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
     800                 :         20 :               *node = fn_ptr_tmp;
     801                 :            :             }
     802                 :            :         }
     803                 :            :     }
     804                 :            : 
     805                 :            :   return returned_attrs;
     806                 :            : }
     807                 :            : 
     808                 :            : /* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
     809                 :            :    attribute.
     810                 :            : 
     811                 :            :    When G++ parses a C++11 attribute, it is represented as
     812                 :            :    a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST.  TREE_PURPOSE
     813                 :            :    (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
     814                 :            :    TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name.  Please
     815                 :            :    use get_attribute_namespace and get_attribute_name to retrieve the
     816                 :            :    namespace and name of the attribute, as these accessors work with
     817                 :            :    GNU attributes as well.  */
     818                 :            : 
     819                 :            : bool
     820                 : 7973330000 : cxx11_attribute_p (const_tree attr)
     821                 :            : {
     822                 : 7973330000 :   if (attr == NULL_TREE
     823                 : 7973330000 :       || TREE_CODE (attr) != TREE_LIST)
     824                 :            :     return false;
     825                 :            : 
     826                 : 7973330000 :   return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
     827                 :            : }
     828                 :            : 
     829                 :            : /* Return the name of the attribute ATTR.  This accessor works on GNU
     830                 :            :    and C++11 (scoped) attributes.
     831                 :            : 
     832                 :            :    Please read the comments of cxx11_attribute_p to understand the
     833                 :            :    format of attributes.  */
     834                 :            : 
     835                 :            : tree
     836                 : 6565830000 : get_attribute_name (const_tree attr)
     837                 :            : {
     838                 : 6565830000 :   if (cxx11_attribute_p (attr))
     839                 :    9994480 :     return TREE_VALUE (TREE_PURPOSE (attr));
     840                 : 6555840000 :   return TREE_PURPOSE (attr);
     841                 :            : }
     842                 :            : 
     843                 :            : /* Subroutine of set_method_tm_attributes.  Apply TM attribute ATTR
     844                 :            :    to the method FNDECL.  */
     845                 :            : 
     846                 :            : void
     847                 :       3822 : apply_tm_attr (tree fndecl, tree attr)
     848                 :            : {
     849                 :       3822 :   decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
     850                 :       3822 : }
     851                 :            : 
     852                 :            : /* Makes a function attribute of the form NAME(ARG_NAME) and chains
     853                 :            :    it to CHAIN.  */
     854                 :            : 
     855                 :            : tree
     856                 :        322 : make_attribute (const char *name, const char *arg_name, tree chain)
     857                 :            : {
     858                 :        322 :   tree attr_name;
     859                 :        322 :   tree attr_arg_name;
     860                 :        322 :   tree attr_args;
     861                 :        322 :   tree attr;
     862                 :            : 
     863                 :        322 :   attr_name = get_identifier (name);
     864                 :        322 :   attr_arg_name = build_string (strlen (arg_name), arg_name);
     865                 :        322 :   attr_args = tree_cons (NULL_TREE, attr_arg_name, NULL_TREE);
     866                 :        322 :   attr = tree_cons (attr_name, attr_args, chain);
     867                 :        322 :   return attr;
     868                 :            : }
     869                 :            : 
     870                 :            : 
     871                 :            : /* Common functions used for target clone support.  */
     872                 :            : 
     873                 :            : /* Comparator function to be used in qsort routine to sort attribute
     874                 :            :    specification strings to "target".  */
     875                 :            : 
     876                 :            : static int
     877                 :       5632 : attr_strcmp (const void *v1, const void *v2)
     878                 :            : {
     879                 :       5632 :   const char *c1 = *(char *const*)v1;
     880                 :       5632 :   const char *c2 = *(char *const*)v2;
     881                 :       5632 :   return strcmp (c1, c2);
     882                 :            : }
     883                 :            : 
     884                 :            : /* ARGLIST is the argument to target attribute.  This function tokenizes
     885                 :            :    the comma separated arguments, sorts them and returns a string which
     886                 :            :    is a unique identifier for the comma separated arguments.   It also
     887                 :            :    replaces non-identifier characters "=,-" with "_".  */
     888                 :            : 
     889                 :            : char *
     890                 :      23064 : sorted_attr_string (tree arglist)
     891                 :            : {
     892                 :      23064 :   tree arg;
     893                 :      23064 :   size_t str_len_sum = 0;
     894                 :      23064 :   char **args = NULL;
     895                 :      23064 :   char *attr_str, *ret_str;
     896                 :      23064 :   char *attr = NULL;
     897                 :      23064 :   unsigned int argnum = 1;
     898                 :      23064 :   unsigned int i;
     899                 :            : 
     900                 :      46144 :   for (arg = arglist; arg; arg = TREE_CHAIN (arg))
     901                 :            :     {
     902                 :      23080 :       const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
     903                 :      23080 :       size_t len = strlen (str);
     904                 :      23080 :       str_len_sum += len + 1;
     905                 :      23080 :       if (arg != arglist)
     906                 :         16 :         argnum++;
     907                 :     209232 :       for (i = 0; i < strlen (str); i++)
     908                 :     186152 :         if (str[i] == ',')
     909                 :       1392 :           argnum++;
     910                 :            :     }
     911                 :            : 
     912                 :      23064 :   attr_str = XNEWVEC (char, str_len_sum);
     913                 :      23064 :   str_len_sum = 0;
     914                 :      46144 :   for (arg = arglist; arg; arg = TREE_CHAIN (arg))
     915                 :            :     {
     916                 :      23080 :       const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
     917                 :      23080 :       size_t len = strlen (str);
     918                 :      23080 :       memcpy (attr_str + str_len_sum, str, len);
     919                 :      23080 :       attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
     920                 :      23080 :       str_len_sum += len + 1;
     921                 :            :     }
     922                 :            : 
     923                 :            :   /* Replace "=,-" with "_".  */
     924                 :     209232 :   for (i = 0; i < strlen (attr_str); i++)
     925                 :     186168 :     if (attr_str[i] == '=' || attr_str[i]== '-')
     926                 :       9600 :       attr_str[i] = '_';
     927                 :            : 
     928                 :      23064 :   if (argnum == 1)
     929                 :            :     return attr_str;
     930                 :            : 
     931                 :       1408 :   args = XNEWVEC (char *, argnum);
     932                 :            : 
     933                 :       1408 :   i = 0;
     934                 :       1408 :   attr = strtok (attr_str, ",");
     935                 :       4224 :   while (attr != NULL)
     936                 :            :     {
     937                 :       2816 :       args[i] = attr;
     938                 :       2816 :       i++;
     939                 :       2816 :       attr = strtok (NULL, ",");
     940                 :            :     }
     941                 :            : 
     942                 :       1408 :   qsort (args, argnum, sizeof (char *), attr_strcmp);
     943                 :            : 
     944                 :       1408 :   ret_str = XNEWVEC (char, str_len_sum);
     945                 :       1408 :   str_len_sum = 0;
     946                 :       4224 :   for (i = 0; i < argnum; i++)
     947                 :            :     {
     948                 :       2816 :       size_t len = strlen (args[i]);
     949                 :       2816 :       memcpy (ret_str + str_len_sum, args[i], len);
     950                 :       2816 :       ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0';
     951                 :       2816 :       str_len_sum += len + 1;
     952                 :            :     }
     953                 :            : 
     954                 :       1408 :   XDELETEVEC (args);
     955                 :       1408 :   XDELETEVEC (attr_str);
     956                 :       1408 :   return ret_str;
     957                 :            : }
     958                 :            : 
     959                 :            : 
     960                 :            : /* This function returns true if FN1 and FN2 are versions of the same function,
     961                 :            :    that is, the target strings of the function decls are different.  This assumes
     962                 :            :    that FN1 and FN2 have the same signature.  */
     963                 :            : 
     964                 :            : bool
     965                 :    1332400 : common_function_versions (tree fn1, tree fn2)
     966                 :            : {
     967                 :    1332400 :   tree attr1, attr2;
     968                 :    1332400 :   char *target1, *target2;
     969                 :    1332400 :   bool result;
     970                 :            : 
     971                 :    1332400 :   if (TREE_CODE (fn1) != FUNCTION_DECL
     972                 :    1331630 :       || TREE_CODE (fn2) != FUNCTION_DECL)
     973                 :            :     return false;
     974                 :            : 
     975                 :    1265700 :   attr1 = lookup_attribute ("target", DECL_ATTRIBUTES (fn1));
     976                 :    1265700 :   attr2 = lookup_attribute ("target", DECL_ATTRIBUTES (fn2));
     977                 :            : 
     978                 :            :   /* At least one function decl should have the target attribute specified.  */
     979                 :    1265700 :   if (attr1 == NULL_TREE && attr2 == NULL_TREE)
     980                 :            :     return false;
     981                 :            : 
     982                 :            :   /* Diagnose missing target attribute if one of the decls is already
     983                 :            :      multi-versioned.  */
     984                 :      11380 :   if (attr1 == NULL_TREE || attr2 == NULL_TREE)
     985                 :            :     {
     986                 :        212 :       if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
     987                 :            :         {
     988                 :        132 :           if (attr2 != NULL_TREE)
     989                 :            :             {
     990                 :        132 :               std::swap (fn1, fn2);
     991                 :        132 :               attr1 = attr2;
     992                 :            :             }
     993                 :        132 :           error_at (DECL_SOURCE_LOCATION (fn2),
     994                 :            :                     "missing %<target%> attribute for multi-versioned %qD",
     995                 :            :                     fn2);
     996                 :        132 :           inform (DECL_SOURCE_LOCATION (fn1),
     997                 :            :                   "previous declaration of %qD", fn1);
     998                 :            :           /* Prevent diagnosing of the same error multiple times.  */
     999                 :        132 :           DECL_ATTRIBUTES (fn2)
    1000                 :        264 :             = tree_cons (get_identifier ("target"),
    1001                 :        132 :                          copy_node (TREE_VALUE (attr1)),
    1002                 :        132 :                          DECL_ATTRIBUTES (fn2));
    1003                 :            :         }
    1004                 :        212 :       return false;
    1005                 :            :     }
    1006                 :            : 
    1007                 :      11168 :   target1 = sorted_attr_string (TREE_VALUE (attr1));
    1008                 :      11168 :   target2 = sorted_attr_string (TREE_VALUE (attr2));
    1009                 :            : 
    1010                 :            :   /* The sorted target strings must be different for fn1 and fn2
    1011                 :            :      to be versions.  */
    1012                 :      11168 :   if (strcmp (target1, target2) == 0)
    1013                 :            :     result = false;
    1014                 :            :   else
    1015                 :      10828 :     result = true;
    1016                 :            : 
    1017                 :      11168 :   XDELETEVEC (target1);
    1018                 :      11168 :   XDELETEVEC (target2);
    1019                 :            : 
    1020                 :      11168 :   return result;
    1021                 :            : }
    1022                 :            : 
    1023                 :            : /* Return a new name by appending SUFFIX to the DECL name.  If make_unique
    1024                 :            :    is true, append the full path name of the source file.  */
    1025                 :            : 
    1026                 :            : char *
    1027                 :          0 : make_unique_name (tree decl, const char *suffix, bool make_unique)
    1028                 :            : {
    1029                 :          0 :   char *global_var_name;
    1030                 :          0 :   int name_len;
    1031                 :          0 :   const char *name;
    1032                 :          0 :   const char *unique_name = NULL;
    1033                 :            : 
    1034                 :          0 :   name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
    1035                 :            : 
    1036                 :            :   /* Get a unique name that can be used globally without any chances
    1037                 :            :      of collision at link time.  */
    1038                 :          0 :   if (make_unique)
    1039                 :          0 :     unique_name = IDENTIFIER_POINTER (get_file_function_name ("\0"));
    1040                 :            : 
    1041                 :          0 :   name_len = strlen (name) + strlen (suffix) + 2;
    1042                 :            : 
    1043                 :          0 :   if (make_unique)
    1044                 :          0 :     name_len += strlen (unique_name) + 1;
    1045                 :          0 :   global_var_name = XNEWVEC (char, name_len);
    1046                 :            : 
    1047                 :            :   /* Use '.' to concatenate names as it is demangler friendly.  */
    1048                 :          0 :   if (make_unique)
    1049                 :          0 :     snprintf (global_var_name, name_len, "%s.%s.%s", name, unique_name,
    1050                 :            :               suffix);
    1051                 :            :   else
    1052                 :          0 :     snprintf (global_var_name, name_len, "%s.%s", name, suffix);
    1053                 :            : 
    1054                 :          0 :   return global_var_name;
    1055                 :            : }
    1056                 :            : 
    1057                 :            : /* Make a dispatcher declaration for the multi-versioned function DECL.
    1058                 :            :    Calls to DECL function will be replaced with calls to the dispatcher
    1059                 :            :    by the front-end.  Return the decl created.  */
    1060                 :            : 
    1061                 :            : tree
    1062                 :        162 : make_dispatcher_decl (const tree decl)
    1063                 :            : {
    1064                 :        162 :   tree func_decl;
    1065                 :        162 :   char *func_name;
    1066                 :        162 :   tree fn_type, func_type;
    1067                 :            : 
    1068                 :        162 :   func_name = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
    1069                 :            : 
    1070                 :        162 :   fn_type = TREE_TYPE (decl);
    1071                 :        324 :   func_type = build_function_type (TREE_TYPE (fn_type),
    1072                 :        162 :                                    TYPE_ARG_TYPES (fn_type));
    1073                 :            :   
    1074                 :        162 :   func_decl = build_fn_decl (func_name, func_type);
    1075                 :        162 :   XDELETEVEC (func_name);
    1076                 :        162 :   TREE_USED (func_decl) = 1;
    1077                 :        162 :   DECL_CONTEXT (func_decl) = NULL_TREE;
    1078                 :        162 :   DECL_INITIAL (func_decl) = error_mark_node;
    1079                 :        162 :   DECL_ARTIFICIAL (func_decl) = 1;
    1080                 :            :   /* Mark this func as external, the resolver will flip it again if
    1081                 :            :      it gets generated.  */
    1082                 :        162 :   DECL_EXTERNAL (func_decl) = 1;
    1083                 :            :   /* This will be of type IFUNCs have to be externally visible.  */
    1084                 :        162 :   TREE_PUBLIC (func_decl) = 1;
    1085                 :            : 
    1086                 :        162 :   return func_decl;  
    1087                 :            : }
    1088                 :            : 
    1089                 :            : /* Returns true if decl is multi-versioned and DECL is the default function,
    1090                 :            :    that is it is not tagged with target specific optimization.  */
    1091                 :            : 
    1092                 :            : bool
    1093                 :        308 : is_function_default_version (const tree decl)
    1094                 :            : {
    1095                 :        308 :   if (TREE_CODE (decl) != FUNCTION_DECL
    1096                 :        308 :       || !DECL_FUNCTION_VERSIONED (decl))
    1097                 :            :     return false;
    1098                 :        308 :   tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
    1099                 :        308 :   gcc_assert (attr);
    1100                 :        308 :   attr = TREE_VALUE (TREE_VALUE (attr));
    1101                 :        308 :   return (TREE_CODE (attr) == STRING_CST
    1102                 :        308 :           && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
    1103                 :            : }
    1104                 :            : 
    1105                 :            : /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
    1106                 :            :    is ATTRIBUTE.  */
    1107                 :            : 
    1108                 :            : tree
    1109                 :   30629000 : build_decl_attribute_variant (tree ddecl, tree attribute)
    1110                 :            : {
    1111                 :   30629000 :   DECL_ATTRIBUTES (ddecl) = attribute;
    1112                 :   30629000 :   return ddecl;
    1113                 :            : }
    1114                 :            : 
    1115                 :            : /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    1116                 :            :    is ATTRIBUTE and its qualifiers are QUALS.
    1117                 :            : 
    1118                 :            :    Record such modified types already made so we don't make duplicates.  */
    1119                 :            : 
    1120                 :            : tree
    1121                 :  100579000 : build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
    1122                 :            : {
    1123                 :  100579000 :   tree ttype = otype;
    1124                 :  100579000 :   if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
    1125                 :            :     {
    1126                 :   66296000 :       tree ntype;
    1127                 :            : 
    1128                 :            :       /* Building a distinct copy of a tagged type is inappropriate; it
    1129                 :            :          causes breakage in code that expects there to be a one-to-one
    1130                 :            :          relationship between a struct and its fields.
    1131                 :            :          build_duplicate_type is another solution (as used in
    1132                 :            :          handle_transparent_union_attribute), but that doesn't play well
    1133                 :            :          with the stronger C++ type identity model.  */
    1134                 :   66296000 :       if (TREE_CODE (ttype) == RECORD_TYPE
    1135                 :            :           || TREE_CODE (ttype) == UNION_TYPE
    1136                 :   66296000 :           || TREE_CODE (ttype) == QUAL_UNION_TYPE
    1137                 :   66296000 :           || TREE_CODE (ttype) == ENUMERAL_TYPE)
    1138                 :            :         {
    1139                 :          0 :           warning (OPT_Wattributes,
    1140                 :            :                    "ignoring attributes applied to %qT after definition",
    1141                 :          0 :                    TYPE_MAIN_VARIANT (ttype));
    1142                 :          0 :           return build_qualified_type (ttype, quals);
    1143                 :            :         }
    1144                 :            : 
    1145                 :   66296000 :       ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
    1146                 :   66296000 :       if (lang_hooks.types.copy_lang_qualifiers
    1147                 :   93792000 :           && otype != TYPE_MAIN_VARIANT (otype))
    1148                 :    1405760 :         ttype = (lang_hooks.types.copy_lang_qualifiers
    1149                 :    1405760 :                  (ttype, TYPE_MAIN_VARIANT (otype)));
    1150                 :            : 
    1151                 :   66296000 :       tree dtype = ntype = build_distinct_type_copy (ttype);
    1152                 :            : 
    1153                 :   66296000 :       TYPE_ATTRIBUTES (ntype) = attribute;
    1154                 :            : 
    1155                 :   66296000 :       hashval_t hash = type_hash_canon_hash (ntype);
    1156                 :   66296000 :       ntype = type_hash_canon (hash, ntype);
    1157                 :            : 
    1158                 :   66296000 :       if (ntype != dtype)
    1159                 :            :         /* This variant was already in the hash table, don't mess with
    1160                 :            :            TYPE_CANONICAL.  */;
    1161                 :   27563600 :       else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
    1162                 :   27563600 :                || !comp_type_attributes (ntype, ttype))
    1163                 :            :         /* If the target-dependent attributes make NTYPE different from
    1164                 :            :            its canonical type, we will need to use structural equality
    1165                 :            :            checks for this type.
    1166                 :            : 
    1167                 :            :            We shouldn't get here for stripping attributes from a type;
    1168                 :            :            the no-attribute type might not need structural comparison.  But
    1169                 :            :            we can if was discarded from type_hash_table.  */
    1170                 :    1772990 :         SET_TYPE_STRUCTURAL_EQUALITY (ntype);
    1171                 :   25790600 :       else if (TYPE_CANONICAL (ntype) == ntype)
    1172                 :   25790600 :         TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
    1173                 :            : 
    1174                 :   66296000 :       ttype = build_qualified_type (ntype, quals);
    1175                 :   66296000 :       if (lang_hooks.types.copy_lang_qualifiers
    1176                 :   93792000 :           && otype != TYPE_MAIN_VARIANT (otype))
    1177                 :    1405760 :         ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype);
    1178                 :            :     }
    1179                 :   34283100 :   else if (TYPE_QUALS (ttype) != quals)
    1180                 :      43244 :     ttype = build_qualified_type (ttype, quals);
    1181                 :            : 
    1182                 :            :   return ttype;
    1183                 :            : }
    1184                 :            : 
    1185                 :            : /* Compare two identifier nodes representing attributes.
    1186                 :            :    Return true if they are the same, false otherwise.  */
    1187                 :            : 
    1188                 :            : static bool
    1189                 :   38017300 : cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
    1190                 :            : {
    1191                 :            :   /* Make sure we're dealing with IDENTIFIER_NODEs.  */
    1192                 :   38017300 :   gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
    1193                 :            :                        && TREE_CODE (attr2) == IDENTIFIER_NODE);
    1194                 :            : 
    1195                 :            :   /* Identifiers can be compared directly for equality.  */
    1196                 :   38017300 :   if (attr1 == attr2)
    1197                 :            :     return true;
    1198                 :            : 
    1199                 :   25807900 :   return cmp_attribs (IDENTIFIER_POINTER (attr1), IDENTIFIER_LENGTH (attr1),
    1200                 :   25807900 :                       IDENTIFIER_POINTER (attr2), IDENTIFIER_LENGTH (attr2));
    1201                 :            : }
    1202                 :            : 
    1203                 :            : /* Compare two constructor-element-type constants.  Return 1 if the lists
    1204                 :            :    are known to be equal; otherwise return 0.  */
    1205                 :            : 
    1206                 :            : static bool
    1207                 :    5275120 : simple_cst_list_equal (const_tree l1, const_tree l2)
    1208                 :            : {
    1209                 :    9788190 :   while (l1 != NULL_TREE && l2 != NULL_TREE)
    1210                 :            :     {
    1211                 :    6196720 :       if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
    1212                 :            :         return false;
    1213                 :            : 
    1214                 :    4513070 :       l1 = TREE_CHAIN (l1);
    1215                 :    4513070 :       l2 = TREE_CHAIN (l2);
    1216                 :            :     }
    1217                 :            : 
    1218                 :    3591470 :   return l1 == l2;
    1219                 :            : }
    1220                 :            : 
    1221                 :            : /* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
    1222                 :            :    the same.  */
    1223                 :            : 
    1224                 :            : static bool
    1225                 :          0 : omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
    1226                 :            : {
    1227                 :          0 :   tree cl1, cl2;
    1228                 :          0 :   for (cl1 = clauses1, cl2 = clauses2;
    1229                 :          0 :        cl1 && cl2;
    1230                 :          0 :        cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
    1231                 :            :     {
    1232                 :          0 :       if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
    1233                 :            :         return false;
    1234                 :          0 :       if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
    1235                 :            :         {
    1236                 :          0 :           if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
    1237                 :          0 :                                 OMP_CLAUSE_DECL (cl2)) != 1)
    1238                 :            :             return false;
    1239                 :            :         }
    1240                 :          0 :       switch (OMP_CLAUSE_CODE (cl1))
    1241                 :            :         {
    1242                 :          0 :         case OMP_CLAUSE_ALIGNED:
    1243                 :          0 :           if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
    1244                 :          0 :                                 OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
    1245                 :            :             return false;
    1246                 :            :           break;
    1247                 :          0 :         case OMP_CLAUSE_LINEAR:
    1248                 :          0 :           if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
    1249                 :          0 :                                 OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
    1250                 :            :             return false;
    1251                 :            :           break;
    1252                 :          0 :         case OMP_CLAUSE_SIMDLEN:
    1253                 :          0 :           if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
    1254                 :          0 :                                 OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
    1255                 :            :             return false;
    1256                 :            :         default:
    1257                 :            :           break;
    1258                 :            :         }
    1259                 :            :     }
    1260                 :            :   return true;
    1261                 :            : }
    1262                 :            : 
    1263                 :            : 
    1264                 :            : /* Compare two attributes for their value identity.  Return true if the
    1265                 :            :    attribute values are known to be equal; otherwise return false.  */
    1266                 :            : 
    1267                 :            : bool
    1268                 :   11996200 : attribute_value_equal (const_tree attr1, const_tree attr2)
    1269                 :            : {
    1270                 :   11996200 :   if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
    1271                 :            :     return true;
    1272                 :            : 
    1273                 :    8504630 :   if (TREE_VALUE (attr1) != NULL_TREE
    1274                 :    8063330 :       && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
    1275                 :    8063320 :       && TREE_VALUE (attr2) != NULL_TREE
    1276                 :   15733400 :       && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
    1277                 :            :     {
    1278                 :            :       /* Handle attribute format.  */
    1279                 :    7228740 :       if (is_attribute_p ("format", get_attribute_name (attr1)))
    1280                 :            :         {
    1281                 :    2172080 :           attr1 = TREE_VALUE (attr1);
    1282                 :    2172080 :           attr2 = TREE_VALUE (attr2);
    1283                 :            :           /* Compare the archetypes (printf/scanf/strftime/...).  */
    1284                 :    2172080 :           if (!cmp_attrib_identifiers (TREE_VALUE (attr1), TREE_VALUE (attr2)))
    1285                 :            :             return false;
    1286                 :            :           /* Archetypes are the same.  Compare the rest.  */
    1287                 :     436914 :           return (simple_cst_list_equal (TREE_CHAIN (attr1),
    1288                 :     436914 :                                          TREE_CHAIN (attr2)) == 1);
    1289                 :            :         }
    1290                 :   10113300 :       return (simple_cst_list_equal (TREE_VALUE (attr1),
    1291                 :   10113300 :                                      TREE_VALUE (attr2)) == 1);
    1292                 :            :     }
    1293                 :            : 
    1294                 :    1275890 :   if (TREE_VALUE (attr1)
    1295                 :     834594 :       && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
    1296                 :          0 :       && TREE_VALUE (attr2)
    1297                 :    1275890 :       && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
    1298                 :          0 :     return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
    1299                 :          0 :                                            TREE_VALUE (attr2));
    1300                 :            : 
    1301                 :    1275890 :   return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
    1302                 :            : }
    1303                 :            : 
    1304                 :            : /* Return 0 if the attributes for two types are incompatible, 1 if they
    1305                 :            :    are compatible, and 2 if they are nearly compatible (which causes a
    1306                 :            :    warning to be generated).  */
    1307                 :            : int
    1308                 :  102067000 : comp_type_attributes (const_tree type1, const_tree type2)
    1309                 :            : {
    1310                 :  102067000 :   const_tree a1 = TYPE_ATTRIBUTES (type1);
    1311                 :  102067000 :   const_tree a2 = TYPE_ATTRIBUTES (type2);
    1312                 :  102067000 :   const_tree a;
    1313                 :            : 
    1314                 :  102067000 :   if (a1 == a2)
    1315                 :            :     return 1;
    1316                 :   70898900 :   for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
    1317                 :            :     {
    1318                 :   39652500 :       const struct attribute_spec *as;
    1319                 :   39652500 :       const_tree attr;
    1320                 :            : 
    1321                 :   39652500 :       as = lookup_attribute_spec (get_attribute_name (a));
    1322                 :   39652500 :       if (!as || as->affects_type_identity == false)
    1323                 :   38576700 :         continue;
    1324                 :            : 
    1325                 :    1075760 :       attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
    1326                 :    1075760 :       if (!attr || !attribute_value_equal (a, attr))
    1327                 :            :         break;
    1328                 :            :     }
    1329                 :   32316900 :   if (!a)
    1330                 :            :     {
    1331                 :   41437500 :       for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
    1332                 :            :         {
    1333                 :   10196500 :           const struct attribute_spec *as;
    1334                 :            : 
    1335                 :   10196500 :           as = lookup_attribute_spec (get_attribute_name (a));
    1336                 :   10196500 :           if (!as || as->affects_type_identity == false)
    1337                 :   10185900 :             continue;
    1338                 :            : 
    1339                 :      10568 :           if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
    1340                 :            :             break;
    1341                 :            :           /* We don't need to compare trees again, as we did this
    1342                 :            :              already in first loop.  */
    1343                 :            :         }
    1344                 :            :       /* All types - affecting identity - are equal, so
    1345                 :            :          there is no need to call target hook for comparison.  */
    1346                 :   31246400 :       if (!a)
    1347                 :            :         return 1;
    1348                 :            :     }
    1349                 :    1075890 :   if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
    1350                 :            :     return 0;
    1351                 :    1073420 :   if ((lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type1)) != NULL)
    1352                 :    1073420 :       ^ (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type2)) != NULL))
    1353                 :            :     return 0;
    1354                 :            :   /* As some type combinations - like default calling-convention - might
    1355                 :            :      be compatible, we have to call the target hook to get the final result.  */
    1356                 :    1073380 :   return targetm.comp_type_attributes (type1, type2);
    1357                 :            : }
    1358                 :            : 
    1359                 :            : /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
    1360                 :            :    is ATTRIBUTE.
    1361                 :            : 
    1362                 :            :    Record such modified types already made so we don't make duplicates.  */
    1363                 :            : 
    1364                 :            : tree
    1365                 :  100534000 : build_type_attribute_variant (tree ttype, tree attribute)
    1366                 :            : {
    1367                 :  100534000 :   return build_type_attribute_qual_variant (ttype, attribute,
    1368                 :  100534000 :                                             TYPE_QUALS (ttype));
    1369                 :            : }
    1370                 :            : 
    1371                 :            : /* A variant of lookup_attribute() that can be used with an identifier
    1372                 :            :    as the first argument, and where the identifier can be either
    1373                 :            :    'text' or '__text__'.
    1374                 :            : 
    1375                 :            :    Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST,
    1376                 :            :    return a pointer to the attribute's list element if the attribute
    1377                 :            :    is part of the list, or NULL_TREE if not found.  If the attribute
    1378                 :            :    appears more than once, this only returns the first occurrence; the
    1379                 :            :    TREE_CHAIN of the return value should be passed back in if further
    1380                 :            :    occurrences are wanted.  ATTR_IDENTIFIER must be an identifier but
    1381                 :            :    can be in the form 'text' or '__text__'.  */
    1382                 :            : static tree
    1383                 :   83556200 : lookup_ident_attribute (tree attr_identifier, tree list)
    1384                 :            : {
    1385                 :   83556200 :   gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE);
    1386                 :            : 
    1387                 :  107411000 :   while (list)
    1388                 :            :     {
    1389                 :   35845300 :       gcc_checking_assert (TREE_CODE (get_attribute_name (list))
    1390                 :            :                            == IDENTIFIER_NODE);
    1391                 :            : 
    1392                 :   35845300 :       if (cmp_attrib_identifiers (attr_identifier,
    1393                 :   35845300 :                                   get_attribute_name (list)))
    1394                 :            :         /* Found it.  */
    1395                 :            :         break;
    1396                 :   23854300 :       list = TREE_CHAIN (list);
    1397                 :            :     }
    1398                 :            : 
    1399                 :   83556200 :   return list;
    1400                 :            : }
    1401                 :            : 
    1402                 :            : /* Remove any instances of attribute ATTR_NAME in LIST and return the
    1403                 :            :    modified list.  */
    1404                 :            : 
    1405                 :            : tree
    1406                 :   12416200 : remove_attribute (const char *attr_name, tree list)
    1407                 :            : {
    1408                 :   12416200 :   tree *p;
    1409                 :   12416200 :   gcc_checking_assert (attr_name[0] != '_');
    1410                 :            : 
    1411                 :   15781900 :   for (p = &list; *p;)
    1412                 :            :     {
    1413                 :    3365730 :       tree l = *p;
    1414                 :            : 
    1415                 :    3365730 :       tree attr = get_attribute_name (l);
    1416                 :    3365730 :       if (is_attribute_p (attr_name, attr))
    1417                 :        546 :         *p = TREE_CHAIN (l);
    1418                 :            :       else
    1419                 :    3365180 :         p = &TREE_CHAIN (l);
    1420                 :            :     }
    1421                 :            : 
    1422                 :   12416200 :   return list;
    1423                 :            : }
    1424                 :            : 
    1425                 :            : /* Return an attribute list that is the union of a1 and a2.  */
    1426                 :            : 
    1427                 :            : tree
    1428                 :   18278100 : merge_attributes (tree a1, tree a2)
    1429                 :            : {
    1430                 :   18278100 :   tree attributes;
    1431                 :            : 
    1432                 :            :   /* Either one unset?  Take the set one.  */
    1433                 :            : 
    1434                 :   18278100 :   if ((attributes = a1) == 0)
    1435                 :            :     attributes = a2;
    1436                 :            : 
    1437                 :            :   /* One that completely contains the other?  Take it.  */
    1438                 :            : 
    1439                 :    2530700 :   else if (a2 != 0 && ! attribute_list_contained (a1, a2))
    1440                 :            :     {
    1441                 :     483040 :       if (attribute_list_contained (a2, a1))
    1442                 :            :         attributes = a2;
    1443                 :            :       else
    1444                 :            :         {
    1445                 :            :           /* Pick the longest list, and hang on the other list.  */
    1446                 :            : 
    1447                 :     283012 :           if (list_length (a1) < list_length (a2))
    1448                 :      73629 :             attributes = a2, a2 = a1;
    1449                 :            : 
    1450                 :     673313 :           for (; a2 != 0; a2 = TREE_CHAIN (a2))
    1451                 :            :             {
    1452                 :     390301 :               tree a;
    1453                 :     560766 :               for (a = lookup_ident_attribute (get_attribute_name (a2),
    1454                 :            :                                                attributes);
    1455                 :     560766 :                    a != NULL_TREE && !attribute_value_equal (a, a2);
    1456                 :     170465 :                    a = lookup_ident_attribute (get_attribute_name (a2),
    1457                 :     170465 :                                                TREE_CHAIN (a)))
    1458                 :            :                 ;
    1459                 :     390301 :               if (a == NULL_TREE)
    1460                 :            :                 {
    1461                 :     283341 :                   a1 = copy_node (a2);
    1462                 :     283341 :                   TREE_CHAIN (a1) = attributes;
    1463                 :     283341 :                   attributes = a1;
    1464                 :            :                 }
    1465                 :            :             }
    1466                 :            :         }
    1467                 :            :     }
    1468                 :   18278100 :   return attributes;
    1469                 :            : }
    1470                 :            : 
    1471                 :            : /* Given types T1 and T2, merge their attributes and return
    1472                 :            :   the result.  */
    1473                 :            : 
    1474                 :            : tree
    1475                 :   12506600 : merge_type_attributes (tree t1, tree t2)
    1476                 :            : {
    1477                 :   25013300 :   return merge_attributes (TYPE_ATTRIBUTES (t1),
    1478                 :   12506600 :                            TYPE_ATTRIBUTES (t2));
    1479                 :            : }
    1480                 :            : 
    1481                 :            : /* Given decls OLDDECL and NEWDECL, merge their attributes and return
    1482                 :            :    the result.  */
    1483                 :            : 
    1484                 :            : tree
    1485                 :    5744450 : merge_decl_attributes (tree olddecl, tree newdecl)
    1486                 :            : {
    1487                 :   11488900 :   return merge_attributes (DECL_ATTRIBUTES (olddecl),
    1488                 :    5744450 :                            DECL_ATTRIBUTES (newdecl));
    1489                 :            : }
    1490                 :            : 
    1491                 :            : /* Duplicate all attributes with name NAME in ATTR list to *ATTRS if
    1492                 :            :    they are missing there.  */
    1493                 :            : 
    1494                 :            : void
    1495                 :    2095740 : duplicate_one_attribute (tree *attrs, tree attr, const char *name)
    1496                 :            : {
    1497                 :    2095740 :   attr = lookup_attribute (name, attr);
    1498                 :    2095740 :   if (!attr)
    1499                 :            :     return;
    1500                 :       1670 :   tree a = lookup_attribute (name, *attrs);
    1501                 :       3340 :   while (attr)
    1502                 :            :     {
    1503                 :            :       tree a2;
    1504                 :       1670 :       for (a2 = a; a2; a2 = lookup_attribute (name, TREE_CHAIN (a2)))
    1505                 :          0 :         if (attribute_value_equal (attr, a2))
    1506                 :            :           break;
    1507                 :       1670 :       if (!a2)
    1508                 :            :         {
    1509                 :       1670 :           a2 = copy_node (attr);
    1510                 :       1670 :           TREE_CHAIN (a2) = *attrs;
    1511                 :       1670 :           *attrs = a2;
    1512                 :            :         }
    1513                 :       1670 :       attr = lookup_attribute (name, TREE_CHAIN (attr));
    1514                 :            :     }
    1515                 :            : }
    1516                 :            : 
    1517                 :            : /* Duplicate all attributes from user DECL to the corresponding
    1518                 :            :    builtin that should be propagated.  */
    1519                 :            : 
    1520                 :            : void
    1521                 :    2095740 : copy_attributes_to_builtin (tree decl)
    1522                 :            : {
    1523                 :    2095740 :   tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
    1524                 :    2095740 :   if (b)
    1525                 :    4191470 :     duplicate_one_attribute (&DECL_ATTRIBUTES (b),
    1526                 :    2095740 :                              DECL_ATTRIBUTES (decl), "omp declare simd");
    1527                 :    2095740 : }
    1528                 :            : 
    1529                 :            : #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
    1530                 :            : 
    1531                 :            : /* Specialization of merge_decl_attributes for various Windows targets.
    1532                 :            : 
    1533                 :            :    This handles the following situation:
    1534                 :            : 
    1535                 :            :      __declspec (dllimport) int foo;
    1536                 :            :      int foo;
    1537                 :            : 
    1538                 :            :    The second instance of `foo' nullifies the dllimport.  */
    1539                 :            : 
    1540                 :            : tree
    1541                 :            : merge_dllimport_decl_attributes (tree old, tree new_tree)
    1542                 :            : {
    1543                 :            :   tree a;
    1544                 :            :   int delete_dllimport_p = 1;
    1545                 :            : 
    1546                 :            :   /* What we need to do here is remove from `old' dllimport if it doesn't
    1547                 :            :      appear in `new'.  dllimport behaves like extern: if a declaration is
    1548                 :            :      marked dllimport and a definition appears later, then the object
    1549                 :            :      is not dllimport'd.  We also remove a `new' dllimport if the old list
    1550                 :            :      contains dllexport:  dllexport always overrides dllimport, regardless
    1551                 :            :      of the order of declaration.  */
    1552                 :            :   if (!VAR_OR_FUNCTION_DECL_P (new_tree))
    1553                 :            :     delete_dllimport_p = 0;
    1554                 :            :   else if (DECL_DLLIMPORT_P (new_tree)
    1555                 :            :            && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
    1556                 :            :     {
    1557                 :            :       DECL_DLLIMPORT_P (new_tree) = 0;
    1558                 :            :       warning (OPT_Wattributes, "%q+D already declared with dllexport "
    1559                 :            :                "attribute: dllimport ignored", new_tree);
    1560                 :            :     }
    1561                 :            :   else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree))
    1562                 :            :     {
    1563                 :            :       /* Warn about overriding a symbol that has already been used, e.g.:
    1564                 :            :            extern int __attribute__ ((dllimport)) foo;
    1565                 :            :            int* bar () {return &foo;}
    1566                 :            :            int foo;
    1567                 :            :       */
    1568                 :            :       if (TREE_USED (old))
    1569                 :            :         {
    1570                 :            :           warning (0, "%q+D redeclared without dllimport attribute "
    1571                 :            :                    "after being referenced with dll linkage", new_tree);
    1572                 :            :           /* If we have used a variable's address with dllimport linkage,
    1573                 :            :               keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
    1574                 :            :               decl may already have had TREE_CONSTANT computed.
    1575                 :            :               We still remove the attribute so that assembler code refers
    1576                 :            :               to '&foo rather than '_imp__foo'.  */
    1577                 :            :           if (VAR_P (old) && TREE_ADDRESSABLE (old))
    1578                 :            :             DECL_DLLIMPORT_P (new_tree) = 1;
    1579                 :            :         }
    1580                 :            : 
    1581                 :            :       /* Let an inline definition silently override the external reference,
    1582                 :            :          but otherwise warn about attribute inconsistency.  */
    1583                 :            :       else if (VAR_P (new_tree) || !DECL_DECLARED_INLINE_P (new_tree))
    1584                 :            :         warning (OPT_Wattributes, "%q+D redeclared without dllimport "
    1585                 :            :                  "attribute: previous dllimport ignored", new_tree);
    1586                 :            :     }
    1587                 :            :   else
    1588                 :            :     delete_dllimport_p = 0;
    1589                 :            : 
    1590                 :            :   a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
    1591                 :            : 
    1592                 :            :   if (delete_dllimport_p)
    1593                 :            :     a = remove_attribute ("dllimport", a);
    1594                 :            : 
    1595                 :            :   return a;
    1596                 :            : }
    1597                 :            : 
    1598                 :            : /* Handle a "dllimport" or "dllexport" attribute; arguments as in
    1599                 :            :    struct attribute_spec.handler.  */
    1600                 :            : 
    1601                 :            : tree
    1602                 :            : handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
    1603                 :            :                       bool *no_add_attrs)
    1604                 :            : {
    1605                 :            :   tree node = *pnode;
    1606                 :            :   bool is_dllimport;
    1607                 :            : 
    1608                 :            :   /* These attributes may apply to structure and union types being created,
    1609                 :            :      but otherwise should pass to the declaration involved.  */
    1610                 :            :   if (!DECL_P (node))
    1611                 :            :     {
    1612                 :            :       if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
    1613                 :            :                    | (int) ATTR_FLAG_ARRAY_NEXT))
    1614                 :            :         {
    1615                 :            :           *no_add_attrs = true;
    1616                 :            :           return tree_cons (name, args, NULL_TREE);
    1617                 :            :         }
    1618                 :            :       if (TREE_CODE (node) == RECORD_TYPE
    1619                 :            :           || TREE_CODE (node) == UNION_TYPE)
    1620                 :            :         {
    1621                 :            :           node = TYPE_NAME (node);
    1622                 :            :           if (!node)
    1623                 :            :             return NULL_TREE;
    1624                 :            :         }
    1625                 :            :       else
    1626                 :            :         {
    1627                 :            :           warning (OPT_Wattributes, "%qE attribute ignored",
    1628                 :            :                    name);
    1629                 :            :           *no_add_attrs = true;
    1630                 :            :           return NULL_TREE;
    1631                 :            :         }
    1632                 :            :     }
    1633                 :            : 
    1634                 :            :   if (!VAR_OR_FUNCTION_DECL_P (node) && TREE_CODE (node) != TYPE_DECL)
    1635                 :            :     {
    1636                 :            :       *no_add_attrs = true;
    1637                 :            :       warning (OPT_Wattributes, "%qE attribute ignored",
    1638                 :            :                name);
    1639                 :            :       return NULL_TREE;
    1640                 :            :     }
    1641                 :            : 
    1642                 :            :   if (TREE_CODE (node) == TYPE_DECL
    1643                 :            :       && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
    1644                 :            :       && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
    1645                 :            :     {
    1646                 :            :       *no_add_attrs = true;
    1647                 :            :       warning (OPT_Wattributes, "%qE attribute ignored",
    1648                 :            :                name);
    1649                 :            :       return NULL_TREE;
    1650                 :            :     }
    1651                 :            : 
    1652                 :            :   is_dllimport = is_attribute_p ("dllimport", name);
    1653                 :            : 
    1654                 :            :   /* Report error on dllimport ambiguities seen now before they cause
    1655                 :            :      any damage.  */
    1656                 :            :   if (is_dllimport)
    1657                 :            :     {
    1658                 :            :       /* Honor any target-specific overrides.  */
    1659                 :            :       if (!targetm.valid_dllimport_attribute_p (node))
    1660                 :            :         *no_add_attrs = true;
    1661                 :            : 
    1662                 :            :      else if (TREE_CODE (node) == FUNCTION_DECL
    1663                 :            :               && DECL_DECLARED_INLINE_P (node))
    1664                 :            :         {
    1665                 :            :           warning (OPT_Wattributes, "inline function %q+D declared as "
    1666                 :            :                   "dllimport: attribute ignored", node);
    1667                 :            :           *no_add_attrs = true;
    1668                 :            :         }
    1669                 :            :       /* Like MS, treat definition of dllimported variables and
    1670                 :            :          non-inlined functions on declaration as syntax errors.  */
    1671                 :            :      else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
    1672                 :            :         {
    1673                 :            :           error ("function %q+D definition is marked dllimport", node);
    1674                 :            :           *no_add_attrs = true;
    1675                 :            :         }
    1676                 :            : 
    1677                 :            :      else if (VAR_P (node))
    1678                 :            :         {
    1679                 :            :           if (DECL_INITIAL (node))
    1680                 :            :             {
    1681                 :            :               error ("variable %q+D definition is marked dllimport",
    1682                 :            :                      node);
    1683                 :            :               *no_add_attrs = true;
    1684                 :            :             }
    1685                 :            : 
    1686                 :            :           /* `extern' needn't be specified with dllimport.
    1687                 :            :              Specify `extern' now and hope for the best.  Sigh.  */
    1688                 :            :           DECL_EXTERNAL (node) = 1;
    1689                 :            :           /* Also, implicitly give dllimport'd variables declared within
    1690                 :            :              a function global scope, unless declared static.  */
    1691                 :            :           if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
    1692                 :            :             TREE_PUBLIC (node) = 1;
    1693                 :            :           /* Clear TREE_STATIC because DECL_EXTERNAL is set, unless
    1694                 :            :              it is a C++ static data member.  */
    1695                 :            :           if (DECL_CONTEXT (node) == NULL_TREE
    1696                 :            :               || !RECORD_OR_UNION_TYPE_P (DECL_CONTEXT (node)))
    1697                 :            :             TREE_STATIC (node) = 0;
    1698                 :            :         }
    1699                 :            : 
    1700                 :            :       if (*no_add_attrs == false)
    1701                 :            :         DECL_DLLIMPORT_P (node) = 1;
    1702                 :            :     }
    1703                 :            :   else if (TREE_CODE (node) == FUNCTION_DECL
    1704                 :            :            && DECL_DECLARED_INLINE_P (node)
    1705                 :            :            && flag_keep_inline_dllexport)
    1706                 :            :     /* An exported function, even if inline, must be emitted.  */
    1707                 :            :     DECL_EXTERNAL (node) = 0;
    1708                 :            : 
    1709                 :            :   /*  Report error if symbol is not accessible at global scope.  */
    1710                 :            :   if (!TREE_PUBLIC (node) && VAR_OR_FUNCTION_DECL_P (node))
    1711                 :            :     {
    1712                 :            :       error ("external linkage required for symbol %q+D because of "
    1713                 :            :              "%qE attribute", node, name);
    1714                 :            :       *no_add_attrs = true;
    1715                 :            :     }
    1716                 :            : 
    1717                 :            :   /* A dllexport'd entity must have default visibility so that other
    1718                 :            :      program units (shared libraries or the main executable) can see
    1719                 :            :      it.  A dllimport'd entity must have default visibility so that
    1720                 :            :      the linker knows that undefined references within this program
    1721                 :            :      unit can be resolved by the dynamic linker.  */
    1722                 :            :   if (!*no_add_attrs)
    1723                 :            :     {
    1724                 :            :       if (DECL_VISIBILITY_SPECIFIED (node)
    1725                 :            :           && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
    1726                 :            :         error ("%qE implies default visibility, but %qD has already "
    1727                 :            :                "been declared with a different visibility",
    1728                 :            :                name, node);
    1729                 :            :       DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
    1730                 :            :       DECL_VISIBILITY_SPECIFIED (node) = 1;
    1731                 :            :     }
    1732                 :            : 
    1733                 :            :   return NULL_TREE;
    1734                 :            : }
    1735                 :            : 
    1736                 :            : #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES  */
    1737                 :            : 
    1738                 :            : /* Given two lists of attributes, return true if list l2 is
    1739                 :            :    equivalent to l1.  */
    1740                 :            : 
    1741                 :            : int
    1742                 :  625864000 : attribute_list_equal (const_tree l1, const_tree l2)
    1743                 :            : {
    1744                 :  625864000 :   if (l1 == l2)
    1745                 :            :     return 1;
    1746                 :            : 
    1747                 :  108310000 :   return attribute_list_contained (l1, l2)
    1748                 :  108456000 :          && attribute_list_contained (l2, l1);
    1749                 :            : }
    1750                 :            : 
    1751                 :            : /* Given two lists of attributes, return true if list L2 is
    1752                 :            :    completely contained within L1.  */
    1753                 :            : /* ??? This would be faster if attribute names were stored in a canonicalized
    1754                 :            :    form.  Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method
    1755                 :            :    must be used to show these elements are equivalent (which they are).  */
    1756                 :            : /* ??? It's not clear that attributes with arguments will always be handled
    1757                 :            :    correctly.  */
    1758                 :            : 
    1759                 :            : int
    1760                 :  148762000 : attribute_list_contained (const_tree l1, const_tree l2)
    1761                 :            : {
    1762                 :  148762000 :   const_tree t1, t2;
    1763                 :            : 
    1764                 :            :   /* First check the obvious, maybe the lists are identical.  */
    1765                 :  148762000 :   if (l1 == l2)
    1766                 :            :     return 1;
    1767                 :            : 
    1768                 :            :   /* Maybe the lists are similar.  */
    1769                 :   93572700 :   for (t1 = l1, t2 = l2;
    1770                 :  242327000 :        t1 != 0 && t2 != 0
    1771                 :  121275000 :        && get_attribute_name (t1) == get_attribute_name (t2)
    1772                 :  343960000 :        && TREE_VALUE (t1) == TREE_VALUE (t2);
    1773                 :   93572700 :        t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
    1774                 :            :     ;
    1775                 :            : 
    1776                 :            :   /* Maybe the lists are equal.  */
    1777                 :  148754000 :   if (t1 == 0 && t2 == 0)
    1778                 :            :     return 1;
    1779                 :            : 
    1780                 :   83473900 :   for (; t2 != 0; t2 = TREE_CHAIN (t2))
    1781                 :            :     {
    1782                 :   78252700 :       const_tree attr;
    1783                 :            :       /* This CONST_CAST is okay because lookup_attribute does not
    1784                 :            :          modify its argument and the return value is assigned to a
    1785                 :            :          const_tree.  */
    1786                 :   82995500 :       for (attr = lookup_ident_attribute (get_attribute_name (t2),
    1787                 :            :                                           CONST_CAST_TREE (l1));
    1788                 :   82995500 :            attr != NULL_TREE && !attribute_value_equal (t2, attr);
    1789                 :    4742740 :            attr = lookup_ident_attribute (get_attribute_name (t2),
    1790                 :    4742740 :                                           TREE_CHAIN (attr)))
    1791                 :            :         ;
    1792                 :            : 
    1793                 :   78252700 :       if (attr == NULL_TREE)
    1794                 :            :         return 0;
    1795                 :            :     }
    1796                 :            : 
    1797                 :            :   return 1;
    1798                 :            : }
    1799                 :            : 
    1800                 :            : /* The backbone of lookup_attribute().  ATTR_LEN is the string length
    1801                 :            :    of ATTR_NAME, and LIST is not NULL_TREE.
    1802                 :            : 
    1803                 :            :    The function is called from lookup_attribute in order to optimize
    1804                 :            :    for size.  */
    1805                 :            : 
    1806                 :            : tree
    1807                 : 2573730000 : private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
    1808                 :            : {
    1809                 : 7470340000 :   while (list)
    1810                 :            :     {
    1811                 : 5316880000 :       tree attr = get_attribute_name (list);
    1812                 : 5316880000 :       size_t ident_len = IDENTIFIER_LENGTH (attr);
    1813                 : 5316880000 :       if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr),
    1814                 :            :                        ident_len))
    1815                 :            :         break;
    1816                 : 4896610000 :       list = TREE_CHAIN (list);
    1817                 :            :     }
    1818                 :            : 
    1819                 : 2573730000 :   return list;
    1820                 :            : }
    1821                 :            : 
    1822                 :            : /* Return true if the function decl or type NODE has been declared
    1823                 :            :    with attribute ANAME among attributes ATTRS.  */
    1824                 :            : 
    1825                 :            : static bool
    1826                 :     450723 : has_attribute (tree node, tree attrs, const char *aname)
    1827                 :            : {
    1828                 :     450723 :   if (!strcmp (aname, "const"))
    1829                 :            :     {
    1830                 :      36688 :       if (DECL_P (node) && TREE_READONLY (node))
    1831                 :            :         return true;
    1832                 :            :     }
    1833                 :     414035 :   else if (!strcmp (aname, "malloc"))
    1834                 :            :     {
    1835                 :      55721 :       if (DECL_P (node) && DECL_IS_MALLOC (node))
    1836                 :            :         return true;
    1837                 :            :     }
    1838                 :     376917 :   else if (!strcmp (aname, "noreturn"))
    1839                 :            :     {
    1840                 :      36688 :       if (DECL_P (node) && TREE_THIS_VOLATILE (node))
    1841                 :            :         return true;
    1842                 :            :     }
    1843                 :     340229 :   else if (!strcmp (aname, "nothrow"))
    1844                 :            :     {
    1845                 :      36688 :       if (TREE_NOTHROW (node))
    1846                 :            :         return true;
    1847                 :            :     }
    1848                 :     303541 :   else if (!strcmp (aname, "pure"))
    1849                 :            :     {
    1850                 :      55033 :       if (DECL_P (node) && DECL_PURE_P (node))
    1851                 :            :         return true;
    1852                 :            :     }
    1853                 :            : 
    1854                 :     405139 :   return lookup_attribute (aname, attrs);
    1855                 :            : }
    1856                 :            : 
    1857                 :            : /* Return the number of mismatched function or type attributes between
    1858                 :            :    the "template" function declaration TMPL and DECL.  The word "template"
    1859                 :            :    doesn't necessarily refer to a C++ template but rather a declaration
    1860                 :            :    whose attributes should be matched by those on DECL.  For a non-zero
    1861                 :            :    return value set *ATTRSTR to a string representation of the list of
    1862                 :            :    mismatched attributes with quoted names.
    1863                 :            :    ATTRLIST is a list of additional attributes that SPEC should be
    1864                 :            :    taken to ultimately be declared with.  */
    1865                 :            : 
    1866                 :            : unsigned
    1867                 :      78517 : decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist,
    1868                 :            :                              const char* const blacklist[],
    1869                 :            :                              pretty_printer *attrstr)
    1870                 :            : {
    1871                 :      78517 :   if (TREE_CODE (tmpl) != FUNCTION_DECL)
    1872                 :            :     return 0;
    1873                 :            : 
    1874                 :            :   /* Avoid warning if either declaration or its type is deprecated.  */
    1875                 :      76062 :   if (TREE_DEPRECATED (tmpl)
    1876                 :      76062 :       || TREE_DEPRECATED (decl))
    1877                 :            :     return 0;
    1878                 :            : 
    1879                 :      76062 :   const tree tmpls[] = { tmpl, TREE_TYPE (tmpl) };
    1880                 :      76062 :   const tree decls[] = { decl, TREE_TYPE (decl) };
    1881                 :            : 
    1882                 :      76062 :   if (TREE_DEPRECATED (tmpls[1])
    1883                 :      76062 :       || TREE_DEPRECATED (decls[1])
    1884                 :      76062 :       || TREE_DEPRECATED (TREE_TYPE (tmpls[1]))
    1885                 :     152124 :       || TREE_DEPRECATED (TREE_TYPE (decls[1])))
    1886                 :            :     return 0;
    1887                 :            : 
    1888                 :      76050 :   tree tmpl_attrs[] = { DECL_ATTRIBUTES (tmpl), TYPE_ATTRIBUTES (tmpls[1]) };
    1889                 :      76050 :   tree decl_attrs[] = { DECL_ATTRIBUTES (decl), TYPE_ATTRIBUTES (decls[1]) };
    1890                 :            : 
    1891                 :      76050 :   if (!decl_attrs[0])
    1892                 :      57152 :     decl_attrs[0] = attrlist;
    1893                 :      18898 :   else if (!decl_attrs[1])
    1894                 :      18875 :     decl_attrs[1] = attrlist;
    1895                 :            : 
    1896                 :            :   /* Avoid warning if the template has no attributes.  */
    1897                 :      76050 :   if (!tmpl_attrs[0] && !tmpl_attrs[1])
    1898                 :            :     return 0;
    1899                 :            : 
    1900                 :            :   /* Avoid warning if either declaration contains an attribute on
    1901                 :            :      the white list below.  */
    1902                 :      18585 :   const char* const whitelist[] = {
    1903                 :            :     "error", "warning"
    1904                 :            :   };
    1905                 :            : 
    1906                 :      55699 :   for (unsigned i = 0; i != 2; ++i)
    1907                 :     111386 :     for (unsigned j = 0; j != sizeof whitelist / sizeof *whitelist; ++j)
    1908                 :      74272 :       if (lookup_attribute (whitelist[j], tmpl_attrs[i])
    1909                 :      74272 :           || lookup_attribute (whitelist[j], decl_attrs[i]))
    1910                 :         28 :         return 0;
    1911                 :            : 
    1912                 :            :   /* Put together a list of the black-listed attributes that the template
    1913                 :            :      is declared with and the declaration is not, in case it's not apparent
    1914                 :            :      from the most recent declaration of the template.  */
    1915                 :            :   unsigned nattrs = 0;
    1916                 :            : 
    1917                 :     258520 :   for (unsigned i = 0; blacklist[i]; ++i)
    1918                 :            :     {
    1919                 :            :       /* Attribute leaf only applies to extern functions.  Avoid mentioning
    1920                 :            :          it when it's missing from a static declaration.  */
    1921                 :     239963 :       if (!TREE_PUBLIC (decl)
    1922                 :     190255 :           && !strcmp ("leaf", blacklist[i]))
    1923                 :      14635 :         continue;
    1924                 :            : 
    1925                 :     630238 :       for (unsigned j = 0; j != 2; ++j)
    1926                 :            :         {
    1927                 :     427810 :           if (!has_attribute (tmpls[j], tmpl_attrs[j], blacklist[i]))
    1928                 :     404910 :             continue;
    1929                 :            : 
    1930                 :      22900 :           bool found = false;
    1931                 :      22900 :           unsigned kmax = 1 + !!decl_attrs[1];
    1932                 :      22982 :           for (unsigned k = 0; k != kmax; ++k)
    1933                 :            :             {
    1934                 :      22913 :               if (has_attribute (decls[k], decl_attrs[k], blacklist[i]))
    1935                 :            :                 {
    1936                 :            :                   found = true;
    1937                 :            :                   break;
    1938                 :            :                 }
    1939                 :            :             }
    1940                 :            : 
    1941                 :      22900 :           if (!found)
    1942                 :            :             {
    1943                 :         69 :               if (nattrs)
    1944                 :          9 :                 pp_string (attrstr, ", ");
    1945                 :         69 :               pp_begin_quote (attrstr, pp_show_color (global_dc->printer));
    1946                 :         69 :               pp_string (attrstr, blacklist[i]);
    1947                 :         69 :               pp_end_quote (attrstr, pp_show_color (global_dc->printer));
    1948                 :         69 :               ++nattrs;
    1949                 :            :             }
    1950                 :            : 
    1951                 :            :           break;
    1952                 :            :         }
    1953                 :            :     }
    1954                 :            : 
    1955                 :            :   return nattrs;
    1956                 :            : }
    1957                 :            : 
    1958                 :            : /* Issue a warning for the declaration ALIAS for TARGET where ALIAS
    1959                 :            :    specifies either attributes that are incompatible with those of
    1960                 :            :    TARGET, or attributes that are missing and that declaring ALIAS
    1961                 :            :    with would benefit.  */
    1962                 :            : 
    1963                 :            : void
    1964                 :      19048 : maybe_diag_alias_attributes (tree alias, tree target)
    1965                 :            : {
    1966                 :            :   /* Do not expect attributes to match between aliases and ifunc
    1967                 :            :      resolvers.  There is no obvious correspondence between them.  */
    1968                 :      19048 :   if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)))
    1969                 :        145 :     return;
    1970                 :            : 
    1971                 :      18907 :   const char* const blacklist[] = {
    1972                 :            :     "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc",
    1973                 :            :     "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull",
    1974                 :            :     "returns_twice", NULL
    1975                 :            :   };
    1976                 :            : 
    1977                 :      37810 :   pretty_printer attrnames;
    1978                 :      18907 :   if (warn_attribute_alias > 1)
    1979                 :            :     {
    1980                 :            :       /* With -Wattribute-alias=2 detect alias declarations that are more
    1981                 :            :          restrictive than their targets first.  Those indicate potential
    1982                 :            :          codegen bugs.  */
    1983                 :          4 :       if (unsigned n = decls_mismatched_attributes (alias, target, NULL_TREE,
    1984                 :            :                                                     blacklist, &attrnames))
    1985                 :            :         {
    1986                 :          4 :           auto_diagnostic_group d;
    1987                 :          4 :           if (warning_n (DECL_SOURCE_LOCATION (alias),
    1988                 :            :                          OPT_Wattribute_alias_, n,
    1989                 :            :                          "%qD specifies more restrictive attribute than "
    1990                 :            :                          "its target %qD: %s",
    1991                 :            :                          "%qD specifies more restrictive attributes than "
    1992                 :            :                          "its target %qD: %s",
    1993                 :            :                          alias, target, pp_formatted_text (&attrnames)))
    1994                 :          3 :             inform (DECL_SOURCE_LOCATION (target),
    1995                 :            :                     "%qD target declared here", alias);
    1996                 :          4 :           return;
    1997                 :            :         }
    1998                 :            :     }
    1999                 :            : 
    2000                 :            :   /* Detect alias declarations that are less restrictive than their
    2001                 :            :      targets.  Those suggest potential optimization opportunities
    2002                 :            :      (solved by adding the missing attribute(s) to the alias).  */
    2003                 :      18903 :   if (unsigned n = decls_mismatched_attributes (target, alias, NULL_TREE,
    2004                 :            :                                                 blacklist, &attrnames))
    2005                 :            :     {
    2006                 :         40 :       auto_diagnostic_group d;
    2007                 :         20 :       if (warning_n (DECL_SOURCE_LOCATION (alias),
    2008                 :            :                      OPT_Wmissing_attributes, n,
    2009                 :            :                      "%qD specifies less restrictive attribute than "
    2010                 :            :                      "its target %qD: %s",
    2011                 :            :                      "%qD specifies less restrictive attributes than "
    2012                 :            :                      "its target %qD: %s",
    2013                 :            :                      alias, target, pp_formatted_text (&attrnames)))
    2014                 :         11 :         inform (DECL_SOURCE_LOCATION (target),
    2015                 :            :                 "%qD target declared here", alias);
    2016                 :            :     }
    2017                 :            : }
    2018                 :            : 
    2019                 :            : 
    2020                 :            : #if CHECKING_P
    2021                 :            : 
    2022                 :            : namespace selftest
    2023                 :            : {
    2024                 :            : 
    2025                 :            : /* Helper types to verify the consistency attribute exclusions.  */
    2026                 :            : 
    2027                 :            : typedef std::pair<const char *, const char *> excl_pair;
    2028                 :            : 
    2029                 :            : struct excl_hash_traits: typed_noop_remove<excl_pair>
    2030                 :            : {
    2031                 :            :   typedef excl_pair  value_type;
    2032                 :            :   typedef value_type compare_type;
    2033                 :            : 
    2034                 :        810 :   static hashval_t hash (const value_type &x)
    2035                 :            :   {
    2036                 :        810 :     hashval_t h1 = htab_hash_string (x.first);
    2037                 :        810 :     hashval_t h2 = htab_hash_string (x.second);
    2038                 :        810 :     return h1 ^ h2;
    2039                 :            :   }
    2040                 :            : 
    2041                 :            :   static bool equal (const value_type &x, const value_type &y)
    2042                 :            :   {
    2043                 :            :     return !strcmp (x.first, y.first) && !strcmp (x.second, y.second);
    2044                 :            :   }
    2045                 :            : 
    2046                 :            :   static void mark_deleted (value_type &x)
    2047                 :            :   {
    2048                 :            :     x = value_type (NULL, NULL);
    2049                 :            :   }
    2050                 :            : 
    2051                 :            :   static const bool empty_zero_p = false;
    2052                 :            : 
    2053                 :        210 :   static void mark_empty (value_type &x)
    2054                 :            :   {
    2055                 :        210 :     x = value_type ("", "");
    2056                 :            :   }
    2057                 :            : 
    2058                 :        986 :   static bool is_deleted (const value_type &x)
    2059                 :            :   {
    2060                 :        986 :     return !x.first && !x.second;
    2061                 :            :   }
    2062                 :            : 
    2063                 :       2324 :   static bool is_empty (const value_type &x)
    2064                 :            :   {
    2065                 :       2324 :     return !*x.first && !*x.second;
    2066                 :            :   }
    2067                 :            : };
    2068                 :            : 
    2069                 :            : 
    2070                 :            : /* Self-test to verify that each attribute exclusion is symmetric,
    2071                 :            :    meaning that if attribute A is encoded as incompatible with
    2072                 :            :    attribute B then the opposite relationship is also encoded.
    2073                 :            :    This test also detects most cases of misspelled attribute names
    2074                 :            :    in exclusions.  */
    2075                 :            : 
    2076                 :            : static void
    2077                 :          2 : test_attribute_exclusions ()
    2078                 :            : {
    2079                 :            :   /* Iterate over the array of attribute tables first (with TI0 as
    2080                 :            :      the index) and over the array of attribute_spec in each table
    2081                 :            :      (with SI0 as the index).  */
    2082                 :          2 :   const size_t ntables = ARRAY_SIZE (attribute_tables);
    2083                 :            : 
    2084                 :            :   /* Set of pairs of mutually exclusive attributes.  */
    2085                 :          2 :   typedef hash_set<excl_pair, false, excl_hash_traits> exclusion_set;
    2086                 :          2 :   exclusion_set excl_set;
    2087                 :            : 
    2088                 :         10 :   for (size_t ti0 = 0; ti0 != ntables; ++ti0)
    2089                 :        260 :     for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0)
    2090                 :            :       {
    2091                 :        252 :         const attribute_spec::exclusions *excl
    2092                 :            :           = attribute_tables[ti0][s0].exclude;
    2093                 :            : 
    2094                 :            :         /* Skip each attribute that doesn't define exclusions.  */
    2095                 :        252 :         if (!excl)
    2096                 :        214 :           continue;
    2097                 :            : 
    2098                 :        140 :         const char *attr_name = attribute_tables[ti0][s0].name;
    2099                 :            : 
    2100                 :            :         /* Iterate over the set of exclusions for every attribute
    2101                 :            :            (with EI0 as the index) adding the exclusions defined
    2102                 :            :            for each to the set.  */
    2103                 :        140 :         for (size_t ei0 = 0; excl[ei0].name; ++ei0)
    2104                 :            :           {
    2105                 :        102 :             const char *excl_name = excl[ei0].name;
    2106                 :            : 
    2107                 :        102 :             if (!strcmp (attr_name, excl_name))
    2108                 :         22 :               continue;
    2109                 :            : 
    2110                 :         80 :             excl_set.add (excl_pair (attr_name, excl_name));
    2111                 :            :           }
    2112                 :            :       }
    2113                 :            : 
    2114                 :            :   /* Traverse the set of mutually exclusive pairs of attributes
    2115                 :            :      and verify that they are symmetric.  */
    2116                 :        164 :   for (exclusion_set::iterator it = excl_set.begin ();
    2117                 :          2 :        it != excl_set.end ();
    2118                 :         82 :        ++it)
    2119                 :            :     {
    2120                 :         80 :       if (!excl_set.contains (excl_pair ((*it).second, (*it).first)))
    2121                 :            :         {
    2122                 :            :           /* An exclusion for an attribute has been found that
    2123                 :            :              doesn't have a corresponding exclusion in the opposite
    2124                 :            :              direction.  */
    2125                 :          0 :           char desc[120];
    2126                 :          0 :           sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
    2127                 :          0 :                    (*it).first, (*it).second);
    2128                 :          0 :           fail (SELFTEST_LOCATION, desc);
    2129                 :            :         }
    2130                 :            :     }
    2131                 :          2 : }
    2132                 :            : 
    2133                 :            : void
    2134                 :          2 : attribute_c_tests ()
    2135                 :            : {
    2136                 :          2 :   test_attribute_exclusions ();
    2137                 :          2 : }
    2138                 :            : 
    2139                 :            : } /* namespace selftest */
    2140                 :            : 
    2141                 :            : #endif /* CHECKING_P */

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.