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