1 /* Functions dealing with attribute handling, used by most front ends.
2 Copyright (C) 1992-2022 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 #define INCLUDE_STRING
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "target.h"
25 #include "tree.h"
26 #include "stringpool.h"
27 #include "diagnostic-core.h"
28 #include "attribs.h"
29 #include "fold-const.h"
30 #include "stor-layout.h"
31 #include "langhooks.h"
32 #include "plugin.h"
33 #include "selftest.h"
34 #include "hash-set.h"
35 #include "diagnostic.h"
36 #include "pretty-print.h"
37 #include "tree-pretty-print.h"
38 #include "intl.h"
39
40 /* Table of the tables of attributes (common, language, format, machine)
41 searched. */
42 static const struct attribute_spec *attribute_tables[4];
43
44 /* Substring representation. */
45
46 struct substring
47 {
48 const char *str;
49 int length;
50 };
51
52 /* Simple hash function to avoid need to scan whole string. */
53
54 static inline hashval_t
substring_hash(const char * str,int l)55 substring_hash (const char *str, int l)
56 {
57 return str[0] + str[l - 1] * 256 + l * 65536;
58 }
59
60 /* Used for attribute_hash. */
61
62 struct attribute_hasher : nofree_ptr_hash <attribute_spec>
63 {
64 typedef substring *compare_type;
65 static inline hashval_t hash (const attribute_spec *);
66 static inline bool equal (const attribute_spec *, const substring *);
67 };
68
69 inline hashval_t
hash(const attribute_spec * spec)70 attribute_hasher::hash (const attribute_spec *spec)
71 {
72 const int l = strlen (spec->name);
73 return substring_hash (spec->name, l);
74 }
75
76 inline bool
equal(const attribute_spec * spec,const substring * str)77 attribute_hasher::equal (const attribute_spec *spec, const substring *str)
78 {
79 return (strncmp (spec->name, str->str, str->length) == 0
80 && !spec->name[str->length]);
81 }
82
83 /* Scoped attribute name representation. */
84
85 struct scoped_attributes
86 {
87 const char *ns;
88 vec<attribute_spec> attributes;
89 hash_table<attribute_hasher> *attribute_hash;
90 /* True if we should not warn about unknown attributes in this NS. */
91 bool ignored_p;
92 };
93
94 /* The table of scope attributes. */
95 static vec<scoped_attributes> attributes_table;
96
97 static scoped_attributes* find_attribute_namespace (const char*);
98 static void register_scoped_attribute (const struct attribute_spec *,
99 scoped_attributes *);
100 static const struct attribute_spec *lookup_scoped_attribute_spec (const_tree,
101 const_tree);
102
103 static bool attributes_initialized = false;
104
105 /* Default empty table of attributes. */
106
107 static const struct attribute_spec empty_attribute_table[] =
108 {
109 { NULL, 0, 0, false, false, false, false, NULL, NULL }
110 };
111
112 /* Insert an array of attributes ATTRIBUTES into a namespace. This
113 array must be NULL terminated. NS is the name of attribute
114 namespace. IGNORED_P is true iff all unknown attributes in this
115 namespace should be ignored for the purposes of -Wattributes. The
116 function returns the namespace into which the attributes have been
117 registered. */
118
119 scoped_attributes *
register_scoped_attributes(const struct attribute_spec * attributes,const char * ns,bool ignored_p)120 register_scoped_attributes (const struct attribute_spec *attributes,
121 const char *ns, bool ignored_p /*=false*/)
122 {
123 scoped_attributes *result = NULL;
124
125 /* See if we already have attributes in the namespace NS. */
126 result = find_attribute_namespace (ns);
127
128 if (result == NULL)
129 {
130 /* We don't have any namespace NS yet. Create one. */
131 scoped_attributes sa;
132
133 if (attributes_table.is_empty ())
134 attributes_table.create (64);
135
136 memset (&sa, 0, sizeof (sa));
137 sa.ns = ns;
138 sa.attributes.create (64);
139 sa.ignored_p = ignored_p;
140 result = attributes_table.safe_push (sa);
141 result->attribute_hash = new hash_table<attribute_hasher> (200);
142 }
143 else
144 result->ignored_p |= ignored_p;
145
146 /* Really add the attributes to their namespace now. */
147 for (unsigned i = 0; attributes[i].name != NULL; ++i)
148 {
149 result->attributes.safe_push (attributes[i]);
150 register_scoped_attribute (&attributes[i], result);
151 }
152
153 gcc_assert (result != NULL);
154
155 return result;
156 }
157
158 /* Return the namespace which name is NS, NULL if none exist. */
159
160 static scoped_attributes*
find_attribute_namespace(const char * ns)161 find_attribute_namespace (const char* ns)
162 {
163 for (scoped_attributes &iter : attributes_table)
164 if (ns == iter.ns
165 || (iter.ns != NULL
166 && ns != NULL
167 && !strcmp (iter.ns, ns)))
168 return &iter;
169 return NULL;
170 }
171
172 /* Make some sanity checks on the attribute tables. */
173
174 static void
check_attribute_tables(void)175 check_attribute_tables (void)
176 {
177 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
178 for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
179 {
180 /* The name must not begin and end with __. */
181 const char *name = attribute_tables[i][j].name;
182 int len = strlen (name);
183
184 gcc_assert (!(name[0] == '_' && name[1] == '_'
185 && name[len - 1] == '_' && name[len - 2] == '_'));
186
187 /* The minimum and maximum lengths must be consistent. */
188 gcc_assert (attribute_tables[i][j].min_length >= 0);
189
190 gcc_assert (attribute_tables[i][j].max_length == -1
191 || (attribute_tables[i][j].max_length
192 >= attribute_tables[i][j].min_length));
193
194 /* An attribute cannot require both a DECL and a TYPE. */
195 gcc_assert (!attribute_tables[i][j].decl_required
196 || !attribute_tables[i][j].type_required);
197
198 /* If an attribute requires a function type, in particular
199 it requires a type. */
200 gcc_assert (!attribute_tables[i][j].function_type_required
201 || attribute_tables[i][j].type_required);
202 }
203
204 /* Check that each name occurs just once in each table. */
205 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
206 for (size_t j = 0; attribute_tables[i][j].name != NULL; j++)
207 for (size_t k = j + 1; attribute_tables[i][k].name != NULL; k++)
208 gcc_assert (strcmp (attribute_tables[i][j].name,
209 attribute_tables[i][k].name));
210
211 /* Check that no name occurs in more than one table. Names that
212 begin with '*' are exempt, and may be overridden. */
213 for (size_t i = 0; i < ARRAY_SIZE (attribute_tables); i++)
214 for (size_t j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
215 for (size_t k = 0; attribute_tables[i][k].name != NULL; k++)
216 for (size_t l = 0; attribute_tables[j][l].name != NULL; l++)
217 gcc_assert (attribute_tables[i][k].name[0] == '*'
218 || strcmp (attribute_tables[i][k].name,
219 attribute_tables[j][l].name));
220 }
221
222 /* Used to stash pointers to allocated memory so that we can free them at
223 the end of parsing of all TUs. */
224 static vec<attribute_spec *> ignored_attributes_table;
225
226 /* Parse arguments V of -Wno-attributes=.
227 Currently we accept:
228 vendor::attr
229 vendor::
230 This functions also registers the parsed attributes so that we don't
231 warn that we don't recognize them. */
232
233 void
handle_ignored_attributes_option(vec<char * > * v)234 handle_ignored_attributes_option (vec<char *> *v)
235 {
236 if (v == nullptr)
237 return;
238
239 for (auto opt : v)
240 {
241 char *cln = strstr (opt, "::");
242 /* We don't accept '::attr'. */
243 if (cln == nullptr || cln == opt)
244 {
245 error ("wrong argument to ignored attributes");
246 inform (input_location, "valid format is %<ns::attr%> or %<ns::%>");
247 continue;
248 }
249 const char *vendor_start = opt;
250 ptrdiff_t vendor_len = cln - opt;
251 const char *attr_start = cln + 2;
252 /* This could really use rawmemchr :(. */
253 ptrdiff_t attr_len = strchr (attr_start, '\0') - attr_start;
254 /* Verify that they look valid. */
255 auto valid_p = [](const char *const s, ptrdiff_t len) {
256 bool ok = false;
257
258 for (int i = 0; i < len; ++i)
259 if (ISALNUM (s[i]))
260 ok = true;
261 else if (s[i] != '_')
262 return false;
263
264 return ok;
265 };
266 if (!valid_p (vendor_start, vendor_len))
267 {
268 error ("wrong argument to ignored attributes");
269 continue;
270 }
271 canonicalize_attr_name (vendor_start, vendor_len);
272 /* We perform all this hijinks so that we don't have to copy OPT. */
273 tree vendor_id = get_identifier_with_length (vendor_start, vendor_len);
274 const char *attr;
275 /* In the "vendor::" case, we should ignore *any* attribute coming
276 from this attribute namespace. */
277 if (attr_len > 0)
278 {
279 if (!valid_p (attr_start, attr_len))
280 {
281 error ("wrong argument to ignored attributes");
282 continue;
283 }
284 canonicalize_attr_name (attr_start, attr_len);
285 tree attr_id = get_identifier_with_length (attr_start, attr_len);
286 attr = IDENTIFIER_POINTER (attr_id);
287 /* If we've already seen this vendor::attr, ignore it. Attempting to
288 register it twice would lead to a crash. */
289 if (lookup_scoped_attribute_spec (vendor_id, attr_id))
290 continue;
291 }
292 else
293 attr = nullptr;
294 /* Create a table with extra attributes which we will register.
295 We can't free it here, so squirrel away the pointers. */
296 attribute_spec *table = new attribute_spec[2];
297 ignored_attributes_table.safe_push (table);
298 table[0] = { attr, 0, -2, false, false, false, false, nullptr, nullptr };
299 table[1] = { nullptr, 0, 0, false, false, false, false, nullptr,
300 nullptr };
301 register_scoped_attributes (table, IDENTIFIER_POINTER (vendor_id), !attr);
302 }
303 }
304
305 /* Free data we might have allocated when adding extra attributes. */
306
307 void
free_attr_data()308 free_attr_data ()
309 {
310 for (auto x : ignored_attributes_table)
311 delete[] x;
312 ignored_attributes_table.release ();
313 }
314
315 /* Initialize attribute tables, and make some sanity checks if checking is
316 enabled. */
317
318 void
init_attributes(void)319 init_attributes (void)
320 {
321 size_t i;
322
323 if (attributes_initialized)
324 return;
325
326 attribute_tables[0] = lang_hooks.common_attribute_table;
327 attribute_tables[1] = lang_hooks.attribute_table;
328 attribute_tables[2] = lang_hooks.format_attribute_table;
329 attribute_tables[3] = targetm.attribute_table;
330
331 /* Translate NULL pointers to pointers to the empty table. */
332 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
333 if (attribute_tables[i] == NULL)
334 attribute_tables[i] = empty_attribute_table;
335
336 if (flag_checking)
337 check_attribute_tables ();
338
339 for (i = 0; i < ARRAY_SIZE (attribute_tables); ++i)
340 /* Put all the GNU attributes into the "gnu" namespace. */
341 register_scoped_attributes (attribute_tables[i], "gnu");
342
343 vec<char *> *ignored = (vec<char *> *) flag_ignored_attributes;
344 handle_ignored_attributes_option (ignored);
345
346 invoke_plugin_callbacks (PLUGIN_ATTRIBUTES, NULL);
347 attributes_initialized = true;
348 }
349
350 /* Insert a single ATTR into the attribute table. */
351
352 void
register_attribute(const struct attribute_spec * attr)353 register_attribute (const struct attribute_spec *attr)
354 {
355 register_scoped_attribute (attr, find_attribute_namespace ("gnu"));
356 }
357
358 /* Insert a single attribute ATTR into a namespace of attributes. */
359
360 static void
register_scoped_attribute(const struct attribute_spec * attr,scoped_attributes * name_space)361 register_scoped_attribute (const struct attribute_spec *attr,
362 scoped_attributes *name_space)
363 {
364 struct substring str;
365 attribute_spec **slot;
366
367 gcc_assert (attr != NULL && name_space != NULL);
368
369 gcc_assert (name_space->attribute_hash);
370
371 str.str = attr->name;
372 str.length = strlen (str.str);
373
374 /* Attribute names in the table must be in the form 'text' and not
375 in the form '__text__'. */
376 gcc_checking_assert (!canonicalize_attr_name (str.str, str.length));
377
378 slot = name_space->attribute_hash
379 ->find_slot_with_hash (&str, substring_hash (str.str, str.length),
380 INSERT);
381 gcc_assert (!*slot || attr->name[0] == '*');
382 *slot = CONST_CAST (struct attribute_spec *, attr);
383 }
384
385 /* Return the spec for the scoped attribute with namespace NS and
386 name NAME. */
387
388 static const struct attribute_spec *
lookup_scoped_attribute_spec(const_tree ns,const_tree name)389 lookup_scoped_attribute_spec (const_tree ns, const_tree name)
390 {
391 struct substring attr;
392 scoped_attributes *attrs;
393
394 const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL;
395
396 attrs = find_attribute_namespace (ns_str);
397
398 if (attrs == NULL)
399 return NULL;
400
401 attr.str = IDENTIFIER_POINTER (name);
402 attr.length = IDENTIFIER_LENGTH (name);
403 return attrs->attribute_hash->find_with_hash (&attr,
404 substring_hash (attr.str,
405 attr.length));
406 }
407
408 /* Return the spec for the attribute named NAME. If NAME is a TREE_LIST,
409 it also specifies the attribute namespace. */
410
411 const struct attribute_spec *
lookup_attribute_spec(const_tree name)412 lookup_attribute_spec (const_tree name)
413 {
414 tree ns;
415 if (TREE_CODE (name) == TREE_LIST)
416 {
417 ns = TREE_PURPOSE (name);
418 name = TREE_VALUE (name);
419 }
420 else
421 ns = get_identifier ("gnu");
422 return lookup_scoped_attribute_spec (ns, name);
423 }
424
425
426 /* Return the namespace of the attribute ATTR. This accessor works on
427 GNU and C++11 (scoped) attributes. On GNU attributes,
428 it returns an identifier tree for the string "gnu".
429
430 Please read the comments of cxx11_attribute_p to understand the
431 format of attributes. */
432
433 tree
get_attribute_namespace(const_tree attr)434 get_attribute_namespace (const_tree attr)
435 {
436 if (cxx11_attribute_p (attr))
437 return TREE_PURPOSE (TREE_PURPOSE (attr));
438 return get_identifier ("gnu");
439 }
440
441 /* Check LAST_DECL and NODE of the same symbol for attributes that are
442 recorded in SPEC to be mutually exclusive with ATTRNAME, diagnose
443 them, and return true if any have been found. NODE can be a DECL
444 or a TYPE. */
445
446 static bool
diag_attr_exclusions(tree last_decl,tree node,tree attrname,const attribute_spec * spec)447 diag_attr_exclusions (tree last_decl, tree node, tree attrname,
448 const attribute_spec *spec)
449 {
450 const attribute_spec::exclusions *excl = spec->exclude;
451
452 tree_code code = TREE_CODE (node);
453
454 if ((code == FUNCTION_DECL && !excl->function
455 && (!excl->type || !spec->affects_type_identity))
456 || (code == VAR_DECL && !excl->variable
457 && (!excl->type || !spec->affects_type_identity))
458 || (((code == TYPE_DECL || RECORD_OR_UNION_TYPE_P (node)) && !excl->type)))
459 return false;
460
461 /* True if an attribute that's mutually exclusive with ATTRNAME
462 has been found. */
463 bool found = false;
464
465 if (last_decl && last_decl != node && TREE_TYPE (last_decl) != node)
466 {
467 /* Check both the last DECL and its type for conflicts with
468 the attribute being added to the current decl or type. */
469 found |= diag_attr_exclusions (last_decl, last_decl, attrname, spec);
470 tree decl_type = TREE_TYPE (last_decl);
471 found |= diag_attr_exclusions (last_decl, decl_type, attrname, spec);
472 }
473
474 /* NODE is either the current DECL to which the attribute is being
475 applied or its TYPE. For the former, consider the attributes on
476 both the DECL and its type. */
477 tree attrs[2];
478
479 if (DECL_P (node))
480 {
481 attrs[0] = DECL_ATTRIBUTES (node);
482 if (TREE_TYPE (node))
483 attrs[1] = TYPE_ATTRIBUTES (TREE_TYPE (node));
484 else
485 /* TREE_TYPE can be NULL e.g. while processing attributes on
486 enumerators. */
487 attrs[1] = NULL_TREE;
488 }
489 else
490 {
491 attrs[0] = TYPE_ATTRIBUTES (node);
492 attrs[1] = NULL_TREE;
493 }
494
495 /* Iterate over the mutually exclusive attribute names and verify
496 that the symbol doesn't contain it. */
497 for (unsigned i = 0; i != sizeof attrs / sizeof *attrs; ++i)
498 {
499 if (!attrs[i])
500 continue;
501
502 for ( ; excl->name; ++excl)
503 {
504 /* Avoid checking the attribute against itself. */
505 if (is_attribute_p (excl->name, attrname))
506 continue;
507
508 if (!lookup_attribute (excl->name, attrs[i]))
509 continue;
510
511 /* An exclusion may apply either to a function declaration,
512 type declaration, or a field/variable declaration, or
513 any subset of the three. */
514 if (TREE_CODE (node) == FUNCTION_DECL
515 && !excl->function)
516 continue;
517
518 if (TREE_CODE (node) == TYPE_DECL
519 && !excl->type)
520 continue;
521
522 if ((TREE_CODE (node) == FIELD_DECL
523 || TREE_CODE (node) == VAR_DECL)
524 && !excl->variable)
525 continue;
526
527 found = true;
528
529 /* Print a note? */
530 bool note = last_decl != NULL_TREE;
531 auto_diagnostic_group d;
532 if (TREE_CODE (node) == FUNCTION_DECL
533 && fndecl_built_in_p (node))
534 note &= warning (OPT_Wattributes,
535 "ignoring attribute %qE in declaration of "
536 "a built-in function %qD because it conflicts "
537 "with attribute %qs",
538 attrname, node, excl->name);
539 else
540 note &= warning (OPT_Wattributes,
541 "ignoring attribute %qE because "
542 "it conflicts with attribute %qs",
543 attrname, excl->name);
544
545 if (note)
546 inform (DECL_SOURCE_LOCATION (last_decl),
547 "previous declaration here");
548 }
549 }
550
551 return found;
552 }
553
554 /* Return true iff we should not complain about unknown attributes
555 coming from the attribute namespace NS. This is the case for
556 the -Wno-attributes=ns:: command-line option. */
557
558 static bool
attr_namespace_ignored_p(tree ns)559 attr_namespace_ignored_p (tree ns)
560 {
561 if (ns == NULL_TREE)
562 return false;
563 scoped_attributes *r = find_attribute_namespace (IDENTIFIER_POINTER (ns));
564 return r && r->ignored_p;
565 }
566
567 /* Return true if the attribute ATTR should not be warned about. */
568
569 bool
attribute_ignored_p(tree attr)570 attribute_ignored_p (tree attr)
571 {
572 if (!cxx11_attribute_p (attr))
573 return false;
574 if (tree ns = get_attribute_namespace (attr))
575 {
576 const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attr));
577 if (as == NULL && attr_namespace_ignored_p (ns))
578 return true;
579 if (as && as->max_length == -2)
580 return true;
581 }
582 return false;
583 }
584
585 /* Like above, but takes an attribute_spec AS, which must be nonnull. */
586
587 bool
attribute_ignored_p(const attribute_spec * const as)588 attribute_ignored_p (const attribute_spec *const as)
589 {
590 return as->max_length == -2;
591 }
592
593 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
594 which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
595 it should be modified in place; if a TYPE, a copy should be created
596 unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further
597 information, in the form of a bitwise OR of flags in enum attribute_flags
598 from tree.h. Depending on these flags, some attributes may be
599 returned to be applied at a later stage (for example, to apply
600 a decl attribute to the declaration rather than to its type). */
601
602 tree
decl_attributes(tree * node,tree attributes,int flags,tree last_decl)603 decl_attributes (tree *node, tree attributes, int flags,
604 tree last_decl /* = NULL_TREE */)
605 {
606 tree returned_attrs = NULL_TREE;
607
608 if (TREE_TYPE (*node) == error_mark_node || attributes == error_mark_node)
609 return NULL_TREE;
610
611 if (!attributes_initialized)
612 init_attributes ();
613
614 /* If this is a function and the user used #pragma GCC optimize, add the
615 options to the attribute((optimize(...))) list. */
616 if (TREE_CODE (*node) == FUNCTION_DECL && current_optimize_pragma)
617 {
618 tree cur_attr = lookup_attribute ("optimize", attributes);
619 tree opts = copy_list (current_optimize_pragma);
620
621 if (! cur_attr)
622 attributes
623 = tree_cons (get_identifier ("optimize"), opts, attributes);
624 else
625 TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
626 }
627
628 if (TREE_CODE (*node) == FUNCTION_DECL
629 && (optimization_current_node != optimization_default_node
630 || target_option_current_node != target_option_default_node)
631 && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
632 {
633 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
634 /* Don't set DECL_FUNCTION_SPECIFIC_TARGET for targets that don't
635 support #pragma GCC target or target attribute. */
636 if (target_option_default_node)
637 {
638 tree cur_tree
639 = build_target_option_node (&global_options, &global_options_set);
640 tree old_tree = DECL_FUNCTION_SPECIFIC_TARGET (*node);
641 if (!old_tree)
642 old_tree = target_option_default_node;
643 /* The changes on optimization options can cause the changes in
644 target options, update it accordingly if it's changed. */
645 if (old_tree != cur_tree)
646 DECL_FUNCTION_SPECIFIC_TARGET (*node) = cur_tree;
647 }
648 }
649
650 /* If this is a function and the user used #pragma GCC target, add the
651 options to the attribute((target(...))) list. */
652 if (TREE_CODE (*node) == FUNCTION_DECL
653 && current_target_pragma
654 && targetm.target_option.valid_attribute_p (*node, NULL_TREE,
655 current_target_pragma, 0))
656 {
657 tree cur_attr = lookup_attribute ("target", attributes);
658 tree opts = copy_list (current_target_pragma);
659
660 if (! cur_attr)
661 attributes = tree_cons (get_identifier ("target"), opts, attributes);
662 else
663 TREE_VALUE (cur_attr) = chainon (opts, TREE_VALUE (cur_attr));
664 }
665
666 /* A "naked" function attribute implies "noinline" and "noclone" for
667 those targets that support it. */
668 if (TREE_CODE (*node) == FUNCTION_DECL
669 && attributes
670 && lookup_attribute ("naked", attributes) != NULL
671 && lookup_attribute_spec (get_identifier ("naked"))
672 && lookup_attribute ("noipa", attributes) == NULL)
673 attributes = tree_cons (get_identifier ("noipa"), NULL, attributes);
674
675 /* A "noipa" function attribute implies "noinline", "noclone" and "no_icf"
676 for those targets that support it. */
677 if (TREE_CODE (*node) == FUNCTION_DECL
678 && attributes
679 && lookup_attribute ("noipa", attributes) != NULL
680 && lookup_attribute_spec (get_identifier ("noipa")))
681 {
682 if (lookup_attribute ("noinline", attributes) == NULL)
683 attributes = tree_cons (get_identifier ("noinline"), NULL, attributes);
684
685 if (lookup_attribute ("noclone", attributes) == NULL)
686 attributes = tree_cons (get_identifier ("noclone"), NULL, attributes);
687
688 if (lookup_attribute ("no_icf", attributes) == NULL)
689 attributes = tree_cons (get_identifier ("no_icf"), NULL, attributes);
690 }
691
692 targetm.insert_attributes (*node, &attributes);
693
694 /* Note that attributes on the same declaration are not necessarily
695 in the same order as in the source. */
696 for (tree attr = attributes; attr; attr = TREE_CHAIN (attr))
697 {
698 tree ns = get_attribute_namespace (attr);
699 tree name = get_attribute_name (attr);
700 tree args = TREE_VALUE (attr);
701 tree *anode = node;
702 const struct attribute_spec *spec
703 = lookup_scoped_attribute_spec (ns, name);
704 int fn_ptr_quals = 0;
705 tree fn_ptr_tmp = NULL_TREE;
706 const bool cxx11_attr_p = cxx11_attribute_p (attr);
707
708 if (spec == NULL)
709 {
710 if (!(flags & (int) ATTR_FLAG_BUILT_IN)
711 && !attr_namespace_ignored_p (ns))
712 {
713 if (ns == NULL_TREE || !cxx11_attr_p)
714 warning (OPT_Wattributes, "%qE attribute directive ignored",
715 name);
716 else
717 warning (OPT_Wattributes,
718 "%<%E::%E%> scoped attribute directive ignored",
719 ns, name);
720 }
721 continue;
722 }
723 else
724 {
725 int nargs = list_length (args);
726 if (nargs < spec->min_length
727 || (spec->max_length >= 0
728 && nargs > spec->max_length))
729 {
730 error ("wrong number of arguments specified for %qE attribute",
731 name);
732 if (spec->max_length < 0)
733 inform (input_location, "expected %i or more, found %i",
734 spec->min_length, nargs);
735 else
736 inform (input_location, "expected between %i and %i, found %i",
737 spec->min_length, spec->max_length, nargs);
738 continue;
739 }
740 }
741 gcc_assert (is_attribute_p (spec->name, name));
742
743 if (spec->decl_required && !DECL_P (*anode))
744 {
745 if (flags & ((int) ATTR_FLAG_DECL_NEXT
746 | (int) ATTR_FLAG_FUNCTION_NEXT
747 | (int) ATTR_FLAG_ARRAY_NEXT))
748 {
749 /* Pass on this attribute to be tried again. */
750 tree attr = tree_cons (name, args, NULL_TREE);
751 returned_attrs = chainon (returned_attrs, attr);
752 continue;
753 }
754 else
755 {
756 warning (OPT_Wattributes, "%qE attribute does not apply to types",
757 name);
758 continue;
759 }
760 }
761
762 /* If we require a type, but were passed a decl, set up to make a
763 new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE
764 would have applied if we'd been passed a type, but we cannot modify
765 the decl's type in place here. */
766 if (spec->type_required && DECL_P (*anode))
767 {
768 anode = &TREE_TYPE (*anode);
769 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
770 }
771
772 if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
773 && TREE_CODE (*anode) != METHOD_TYPE)
774 {
775 if (TREE_CODE (*anode) == POINTER_TYPE
776 && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
777 || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
778 {
779 /* OK, this is a bit convoluted. We can't just make a copy
780 of the pointer type and modify its TREE_TYPE, because if
781 we change the attributes of the target type the pointer
782 type needs to have a different TYPE_MAIN_VARIANT. So we
783 pull out the target type now, frob it as appropriate, and
784 rebuild the pointer type later.
785
786 This would all be simpler if attributes were part of the
787 declarator, grumble grumble. */
788 fn_ptr_tmp = TREE_TYPE (*anode);
789 fn_ptr_quals = TYPE_QUALS (*anode);
790 anode = &fn_ptr_tmp;
791 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
792 }
793 else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
794 {
795 /* Pass on this attribute to be tried again. */
796 tree attr = tree_cons (name, args, NULL_TREE);
797 returned_attrs = chainon (returned_attrs, attr);
798 continue;
799 }
800
801 if (TREE_CODE (*anode) != FUNCTION_TYPE
802 && TREE_CODE (*anode) != METHOD_TYPE)
803 {
804 warning (OPT_Wattributes,
805 "%qE attribute only applies to function types",
806 name);
807 continue;
808 }
809 }
810
811 if (TYPE_P (*anode)
812 && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
813 && TYPE_SIZE (*anode) != NULL_TREE)
814 {
815 warning (OPT_Wattributes, "type attributes ignored after type is already defined");
816 continue;
817 }
818
819 bool no_add_attrs = false;
820
821 /* Check for exclusions with other attributes on the current
822 declation as well as the last declaration of the same
823 symbol already processed (if one exists). Detect and
824 reject incompatible attributes. */
825 bool built_in = flags & ATTR_FLAG_BUILT_IN;
826 if (spec->exclude
827 && (flag_checking || !built_in)
828 && !error_operand_p (last_decl))
829 {
830 /* Always check attributes on user-defined functions.
831 Check them on built-ins only when -fchecking is set.
832 Ignore __builtin_unreachable -- it's both const and
833 noreturn. */
834
835 if (!built_in
836 || !DECL_P (*anode)
837 || DECL_BUILT_IN_CLASS (*anode) != BUILT_IN_NORMAL
838 || (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE
839 && (DECL_FUNCTION_CODE (*anode)
840 != BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE)))
841 {
842 bool no_add = diag_attr_exclusions (last_decl, *anode, name, spec);
843 if (!no_add && anode != node)
844 no_add = diag_attr_exclusions (last_decl, *node, name, spec);
845 no_add_attrs |= no_add;
846 }
847 }
848
849 if (no_add_attrs
850 /* Don't add attributes registered just for -Wno-attributes=foo::bar
851 purposes. */
852 || attribute_ignored_p (attr))
853 continue;
854
855 if (spec->handler != NULL)
856 {
857 int cxx11_flag = (cxx11_attr_p ? ATTR_FLAG_CXX11 : 0);
858
859 /* Pass in an array of the current declaration followed
860 by the last pushed/merged declaration if one exists.
861 For calls that modify the type attributes of a DECL
862 and for which *ANODE is *NODE's type, also pass in
863 the DECL as the third element to use in diagnostics.
864 If the handler changes CUR_AND_LAST_DECL[0] replace
865 *ANODE with its value. */
866 tree cur_and_last_decl[3] = { *anode, last_decl };
867 if (anode != node && DECL_P (*node))
868 cur_and_last_decl[2] = *node;
869
870 tree ret = (spec->handler) (cur_and_last_decl, name, args,
871 flags|cxx11_flag, &no_add_attrs);
872
873 *anode = cur_and_last_decl[0];
874 if (ret == error_mark_node)
875 {
876 warning (OPT_Wattributes, "%qE attribute ignored", name);
877 no_add_attrs = true;
878 }
879 else
880 returned_attrs = chainon (ret, returned_attrs);
881 }
882
883 /* Layout the decl in case anything changed. */
884 if (spec->type_required && DECL_P (*node)
885 && (VAR_P (*node)
886 || TREE_CODE (*node) == PARM_DECL
887 || TREE_CODE (*node) == RESULT_DECL))
888 relayout_decl (*node);
889
890 if (!no_add_attrs)
891 {
892 tree old_attrs;
893 tree a;
894
895 if (DECL_P (*anode))
896 old_attrs = DECL_ATTRIBUTES (*anode);
897 else
898 old_attrs = TYPE_ATTRIBUTES (*anode);
899
900 for (a = lookup_attribute (spec->name, old_attrs);
901 a != NULL_TREE;
902 a = lookup_attribute (spec->name, TREE_CHAIN (a)))
903 {
904 if (simple_cst_equal (TREE_VALUE (a), args) == 1)
905 break;
906 }
907
908 if (a == NULL_TREE)
909 {
910 /* This attribute isn't already in the list. */
911 tree r;
912 /* Preserve the C++11 form. */
913 if (cxx11_attr_p)
914 r = tree_cons (build_tree_list (ns, name), args, old_attrs);
915 else
916 r = tree_cons (name, args, old_attrs);
917
918 if (DECL_P (*anode))
919 DECL_ATTRIBUTES (*anode) = r;
920 else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
921 {
922 TYPE_ATTRIBUTES (*anode) = r;
923 /* If this is the main variant, also push the attributes
924 out to the other variants. */
925 if (*anode == TYPE_MAIN_VARIANT (*anode))
926 {
927 for (tree variant = *anode; variant;
928 variant = TYPE_NEXT_VARIANT (variant))
929 {
930 if (TYPE_ATTRIBUTES (variant) == old_attrs)
931 TYPE_ATTRIBUTES (variant)
932 = TYPE_ATTRIBUTES (*anode);
933 else if (!lookup_attribute
934 (spec->name, TYPE_ATTRIBUTES (variant)))
935 TYPE_ATTRIBUTES (variant) = tree_cons
936 (name, args, TYPE_ATTRIBUTES (variant));
937 }
938 }
939 }
940 else
941 *anode = build_type_attribute_variant (*anode, r);
942 }
943 }
944
945 if (fn_ptr_tmp)
946 {
947 /* Rebuild the function pointer type and put it in the
948 appropriate place. */
949 fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
950 if (fn_ptr_quals)
951 fn_ptr_tmp = build_qualified_type (fn_ptr_tmp, fn_ptr_quals);
952 if (DECL_P (*node))
953 TREE_TYPE (*node) = fn_ptr_tmp;
954 else
955 {
956 gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
957 *node = fn_ptr_tmp;
958 }
959 }
960 }
961
962 return returned_attrs;
963 }
964
965 /* Return TRUE iff ATTR has been parsed by the front-end as a C++-11
966 attribute.
967
968 When G++ parses a C++11 attribute, it is represented as
969 a TREE_LIST which TREE_PURPOSE is itself a TREE_LIST. TREE_PURPOSE
970 (TREE_PURPOSE (ATTR)) is the namespace of the attribute, and the
971 TREE_VALUE (TREE_PURPOSE (ATTR)) is its non-qualified name. Please
972 use get_attribute_namespace and get_attribute_name to retrieve the
973 namespace and name of the attribute, as these accessors work with
974 GNU attributes as well. */
975
976 bool
cxx11_attribute_p(const_tree attr)977 cxx11_attribute_p (const_tree attr)
978 {
979 if (attr == NULL_TREE
980 || TREE_CODE (attr) != TREE_LIST)
981 return false;
982
983 return (TREE_CODE (TREE_PURPOSE (attr)) == TREE_LIST);
984 }
985
986 /* Return the name of the attribute ATTR. This accessor works on GNU
987 and C++11 (scoped) attributes.
988
989 Please read the comments of cxx11_attribute_p to understand the
990 format of attributes. */
991
992 tree
get_attribute_name(const_tree attr)993 get_attribute_name (const_tree attr)
994 {
995 if (cxx11_attribute_p (attr))
996 return TREE_VALUE (TREE_PURPOSE (attr));
997 return TREE_PURPOSE (attr);
998 }
999
1000 /* Subroutine of set_method_tm_attributes. Apply TM attribute ATTR
1001 to the method FNDECL. */
1002
1003 void
apply_tm_attr(tree fndecl,tree attr)1004 apply_tm_attr (tree fndecl, tree attr)
1005 {
1006 decl_attributes (&TREE_TYPE (fndecl), tree_cons (attr, NULL, NULL), 0);
1007 }
1008
1009 /* Makes a function attribute of the form NAME(ARG_NAME) and chains
1010 it to CHAIN. */
1011
1012 tree
make_attribute(const char * name,const char * arg_name,tree chain)1013 make_attribute (const char *name, const char *arg_name, tree chain)
1014 {
1015 tree attr_name;
1016 tree attr_arg_name;
1017 tree attr_args;
1018 tree attr;
1019
1020 attr_name = get_identifier (name);
1021 attr_arg_name = build_string (strlen (arg_name), arg_name);
1022 attr_args = tree_cons (NULL_TREE, attr_arg_name, NULL_TREE);
1023 attr = tree_cons (attr_name, attr_args, chain);
1024 return attr;
1025 }
1026
1027
1028 /* Common functions used for target clone support. */
1029
1030 /* Comparator function to be used in qsort routine to sort attribute
1031 specification strings to "target". */
1032
1033 static int
attr_strcmp(const void * v1,const void * v2)1034 attr_strcmp (const void *v1, const void *v2)
1035 {
1036 const char *c1 = *(char *const*)v1;
1037 const char *c2 = *(char *const*)v2;
1038 return strcmp (c1, c2);
1039 }
1040
1041 /* ARGLIST is the argument to target attribute. This function tokenizes
1042 the comma separated arguments, sorts them and returns a string which
1043 is a unique identifier for the comma separated arguments. It also
1044 replaces non-identifier characters "=,-" with "_". */
1045
1046 char *
sorted_attr_string(tree arglist)1047 sorted_attr_string (tree arglist)
1048 {
1049 tree arg;
1050 size_t str_len_sum = 0;
1051 char **args = NULL;
1052 char *attr_str, *ret_str;
1053 char *attr = NULL;
1054 unsigned int argnum = 1;
1055 unsigned int i;
1056
1057 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
1058 {
1059 const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
1060 size_t len = strlen (str);
1061 str_len_sum += len + 1;
1062 if (arg != arglist)
1063 argnum++;
1064 for (i = 0; i < strlen (str); i++)
1065 if (str[i] == ',')
1066 argnum++;
1067 }
1068
1069 attr_str = XNEWVEC (char, str_len_sum);
1070 str_len_sum = 0;
1071 for (arg = arglist; arg; arg = TREE_CHAIN (arg))
1072 {
1073 const char *str = TREE_STRING_POINTER (TREE_VALUE (arg));
1074 size_t len = strlen (str);
1075 memcpy (attr_str + str_len_sum, str, len);
1076 attr_str[str_len_sum + len] = TREE_CHAIN (arg) ? ',' : '\0';
1077 str_len_sum += len + 1;
1078 }
1079
1080 /* Replace "=,-" with "_". */
1081 for (i = 0; i < strlen (attr_str); i++)
1082 if (attr_str[i] == '=' || attr_str[i]== '-')
1083 attr_str[i] = '_';
1084
1085 if (argnum == 1)
1086 return attr_str;
1087
1088 args = XNEWVEC (char *, argnum);
1089
1090 i = 0;
1091 attr = strtok (attr_str, ",");
1092 while (attr != NULL)
1093 {
1094 args[i] = attr;
1095 i++;
1096 attr = strtok (NULL, ",");
1097 }
1098
1099 qsort (args, argnum, sizeof (char *), attr_strcmp);
1100
1101 ret_str = XNEWVEC (char, str_len_sum);
1102 str_len_sum = 0;
1103 for (i = 0; i < argnum; i++)
1104 {
1105 size_t len = strlen (args[i]);
1106 memcpy (ret_str + str_len_sum, args[i], len);
1107 ret_str[str_len_sum + len] = i < argnum - 1 ? '_' : '\0';
1108 str_len_sum += len + 1;
1109 }
1110
1111 XDELETEVEC (args);
1112 XDELETEVEC (attr_str);
1113 return ret_str;
1114 }
1115
1116
1117 /* This function returns true if FN1 and FN2 are versions of the same function,
1118 that is, the target strings of the function decls are different. This assumes
1119 that FN1 and FN2 have the same signature. */
1120
1121 bool
common_function_versions(tree fn1,tree fn2)1122 common_function_versions (tree fn1, tree fn2)
1123 {
1124 tree attr1, attr2;
1125 char *target1, *target2;
1126 bool result;
1127
1128 if (TREE_CODE (fn1) != FUNCTION_DECL
1129 || TREE_CODE (fn2) != FUNCTION_DECL)
1130 return false;
1131
1132 attr1 = lookup_attribute ("target", DECL_ATTRIBUTES (fn1));
1133 attr2 = lookup_attribute ("target", DECL_ATTRIBUTES (fn2));
1134
1135 /* At least one function decl should have the target attribute specified. */
1136 if (attr1 == NULL_TREE && attr2 == NULL_TREE)
1137 return false;
1138
1139 /* Diagnose missing target attribute if one of the decls is already
1140 multi-versioned. */
1141 if (attr1 == NULL_TREE || attr2 == NULL_TREE)
1142 {
1143 if (DECL_FUNCTION_VERSIONED (fn1) || DECL_FUNCTION_VERSIONED (fn2))
1144 {
1145 if (attr2 != NULL_TREE)
1146 {
1147 std::swap (fn1, fn2);
1148 attr1 = attr2;
1149 }
1150 error_at (DECL_SOURCE_LOCATION (fn2),
1151 "missing %<target%> attribute for multi-versioned %qD",
1152 fn2);
1153 inform (DECL_SOURCE_LOCATION (fn1),
1154 "previous declaration of %qD", fn1);
1155 /* Prevent diagnosing of the same error multiple times. */
1156 DECL_ATTRIBUTES (fn2)
1157 = tree_cons (get_identifier ("target"),
1158 copy_node (TREE_VALUE (attr1)),
1159 DECL_ATTRIBUTES (fn2));
1160 }
1161 return false;
1162 }
1163
1164 target1 = sorted_attr_string (TREE_VALUE (attr1));
1165 target2 = sorted_attr_string (TREE_VALUE (attr2));
1166
1167 /* The sorted target strings must be different for fn1 and fn2
1168 to be versions. */
1169 if (strcmp (target1, target2) == 0)
1170 result = false;
1171 else
1172 result = true;
1173
1174 XDELETEVEC (target1);
1175 XDELETEVEC (target2);
1176
1177 return result;
1178 }
1179
1180 /* Make a dispatcher declaration for the multi-versioned function DECL.
1181 Calls to DECL function will be replaced with calls to the dispatcher
1182 by the front-end. Return the decl created. */
1183
1184 tree
make_dispatcher_decl(const tree decl)1185 make_dispatcher_decl (const tree decl)
1186 {
1187 tree func_decl;
1188 char *func_name;
1189 tree fn_type, func_type;
1190
1191 func_name = xstrdup (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
1192
1193 fn_type = TREE_TYPE (decl);
1194 func_type = build_function_type (TREE_TYPE (fn_type),
1195 TYPE_ARG_TYPES (fn_type));
1196
1197 func_decl = build_fn_decl (func_name, func_type);
1198 XDELETEVEC (func_name);
1199 TREE_USED (func_decl) = 1;
1200 DECL_CONTEXT (func_decl) = NULL_TREE;
1201 DECL_INITIAL (func_decl) = error_mark_node;
1202 DECL_ARTIFICIAL (func_decl) = 1;
1203 /* Mark this func as external, the resolver will flip it again if
1204 it gets generated. */
1205 DECL_EXTERNAL (func_decl) = 1;
1206 /* This will be of type IFUNCs have to be externally visible. */
1207 TREE_PUBLIC (func_decl) = 1;
1208
1209 return func_decl;
1210 }
1211
1212 /* Returns true if decl is multi-versioned and DECL is the default function,
1213 that is it is not tagged with target specific optimization. */
1214
1215 bool
is_function_default_version(const tree decl)1216 is_function_default_version (const tree decl)
1217 {
1218 if (TREE_CODE (decl) != FUNCTION_DECL
1219 || !DECL_FUNCTION_VERSIONED (decl))
1220 return false;
1221 tree attr = lookup_attribute ("target", DECL_ATTRIBUTES (decl));
1222 gcc_assert (attr);
1223 attr = TREE_VALUE (TREE_VALUE (attr));
1224 return (TREE_CODE (attr) == STRING_CST
1225 && strcmp (TREE_STRING_POINTER (attr), "default") == 0);
1226 }
1227
1228 /* Return a declaration like DDECL except that its DECL_ATTRIBUTES
1229 is ATTRIBUTE. */
1230
1231 tree
build_decl_attribute_variant(tree ddecl,tree attribute)1232 build_decl_attribute_variant (tree ddecl, tree attribute)
1233 {
1234 DECL_ATTRIBUTES (ddecl) = attribute;
1235 return ddecl;
1236 }
1237
1238 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
1239 is ATTRIBUTE and its qualifiers are QUALS.
1240
1241 Record such modified types already made so we don't make duplicates. */
1242
1243 tree
build_type_attribute_qual_variant(tree otype,tree attribute,int quals)1244 build_type_attribute_qual_variant (tree otype, tree attribute, int quals)
1245 {
1246 tree ttype = otype;
1247 if (! attribute_list_equal (TYPE_ATTRIBUTES (ttype), attribute))
1248 {
1249 tree ntype;
1250
1251 /* Building a distinct copy of a tagged type is inappropriate; it
1252 causes breakage in code that expects there to be a one-to-one
1253 relationship between a struct and its fields.
1254 build_duplicate_type is another solution (as used in
1255 handle_transparent_union_attribute), but that doesn't play well
1256 with the stronger C++ type identity model. */
1257 if (TREE_CODE (ttype) == RECORD_TYPE
1258 || TREE_CODE (ttype) == UNION_TYPE
1259 || TREE_CODE (ttype) == QUAL_UNION_TYPE
1260 || TREE_CODE (ttype) == ENUMERAL_TYPE)
1261 {
1262 warning (OPT_Wattributes,
1263 "ignoring attributes applied to %qT after definition",
1264 TYPE_MAIN_VARIANT (ttype));
1265 return build_qualified_type (ttype, quals);
1266 }
1267
1268 ttype = build_qualified_type (ttype, TYPE_UNQUALIFIED);
1269 if (lang_hooks.types.copy_lang_qualifiers
1270 && otype != TYPE_MAIN_VARIANT (otype))
1271 ttype = (lang_hooks.types.copy_lang_qualifiers
1272 (ttype, TYPE_MAIN_VARIANT (otype)));
1273
1274 tree dtype = ntype = build_distinct_type_copy (ttype);
1275
1276 TYPE_ATTRIBUTES (ntype) = attribute;
1277
1278 hashval_t hash = type_hash_canon_hash (ntype);
1279 ntype = type_hash_canon (hash, ntype);
1280
1281 if (ntype != dtype)
1282 /* This variant was already in the hash table, don't mess with
1283 TYPE_CANONICAL. */;
1284 else if (TYPE_STRUCTURAL_EQUALITY_P (ttype)
1285 || !comp_type_attributes (ntype, ttype))
1286 /* If the target-dependent attributes make NTYPE different from
1287 its canonical type, we will need to use structural equality
1288 checks for this type.
1289
1290 We shouldn't get here for stripping attributes from a type;
1291 the no-attribute type might not need structural comparison. But
1292 we can if was discarded from type_hash_table. */
1293 SET_TYPE_STRUCTURAL_EQUALITY (ntype);
1294 else if (TYPE_CANONICAL (ntype) == ntype)
1295 TYPE_CANONICAL (ntype) = TYPE_CANONICAL (ttype);
1296
1297 ttype = build_qualified_type (ntype, quals);
1298 if (lang_hooks.types.copy_lang_qualifiers
1299 && otype != TYPE_MAIN_VARIANT (otype))
1300 ttype = lang_hooks.types.copy_lang_qualifiers (ttype, otype);
1301 }
1302 else if (TYPE_QUALS (ttype) != quals)
1303 ttype = build_qualified_type (ttype, quals);
1304
1305 return ttype;
1306 }
1307
1308 /* Compare two identifier nodes representing attributes.
1309 Return true if they are the same, false otherwise. */
1310
1311 static bool
cmp_attrib_identifiers(const_tree attr1,const_tree attr2)1312 cmp_attrib_identifiers (const_tree attr1, const_tree attr2)
1313 {
1314 /* Make sure we're dealing with IDENTIFIER_NODEs. */
1315 gcc_checking_assert (TREE_CODE (attr1) == IDENTIFIER_NODE
1316 && TREE_CODE (attr2) == IDENTIFIER_NODE);
1317
1318 /* Identifiers can be compared directly for equality. */
1319 if (attr1 == attr2)
1320 return true;
1321
1322 return cmp_attribs (IDENTIFIER_POINTER (attr1), IDENTIFIER_LENGTH (attr1),
1323 IDENTIFIER_POINTER (attr2), IDENTIFIER_LENGTH (attr2));
1324 }
1325
1326 /* Compare two constructor-element-type constants. Return 1 if the lists
1327 are known to be equal; otherwise return 0. */
1328
1329 bool
simple_cst_list_equal(const_tree l1,const_tree l2)1330 simple_cst_list_equal (const_tree l1, const_tree l2)
1331 {
1332 while (l1 != NULL_TREE && l2 != NULL_TREE)
1333 {
1334 if (simple_cst_equal (TREE_VALUE (l1), TREE_VALUE (l2)) != 1)
1335 return false;
1336
1337 l1 = TREE_CHAIN (l1);
1338 l2 = TREE_CHAIN (l2);
1339 }
1340
1341 return l1 == l2;
1342 }
1343
1344 /* Check if "omp declare simd" attribute arguments, CLAUSES1 and CLAUSES2, are
1345 the same. */
1346
1347 static bool
omp_declare_simd_clauses_equal(tree clauses1,tree clauses2)1348 omp_declare_simd_clauses_equal (tree clauses1, tree clauses2)
1349 {
1350 tree cl1, cl2;
1351 for (cl1 = clauses1, cl2 = clauses2;
1352 cl1 && cl2;
1353 cl1 = OMP_CLAUSE_CHAIN (cl1), cl2 = OMP_CLAUSE_CHAIN (cl2))
1354 {
1355 if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_CODE (cl2))
1356 return false;
1357 if (OMP_CLAUSE_CODE (cl1) != OMP_CLAUSE_SIMDLEN)
1358 {
1359 if (simple_cst_equal (OMP_CLAUSE_DECL (cl1),
1360 OMP_CLAUSE_DECL (cl2)) != 1)
1361 return false;
1362 }
1363 switch (OMP_CLAUSE_CODE (cl1))
1364 {
1365 case OMP_CLAUSE_ALIGNED:
1366 if (simple_cst_equal (OMP_CLAUSE_ALIGNED_ALIGNMENT (cl1),
1367 OMP_CLAUSE_ALIGNED_ALIGNMENT (cl2)) != 1)
1368 return false;
1369 break;
1370 case OMP_CLAUSE_LINEAR:
1371 if (simple_cst_equal (OMP_CLAUSE_LINEAR_STEP (cl1),
1372 OMP_CLAUSE_LINEAR_STEP (cl2)) != 1)
1373 return false;
1374 break;
1375 case OMP_CLAUSE_SIMDLEN:
1376 if (simple_cst_equal (OMP_CLAUSE_SIMDLEN_EXPR (cl1),
1377 OMP_CLAUSE_SIMDLEN_EXPR (cl2)) != 1)
1378 return false;
1379 default:
1380 break;
1381 }
1382 }
1383 return true;
1384 }
1385
1386
1387 /* Compare two attributes for their value identity. Return true if the
1388 attribute values are known to be equal; otherwise return false. */
1389
1390 bool
attribute_value_equal(const_tree attr1,const_tree attr2)1391 attribute_value_equal (const_tree attr1, const_tree attr2)
1392 {
1393 if (TREE_VALUE (attr1) == TREE_VALUE (attr2))
1394 return true;
1395
1396 if (TREE_VALUE (attr1) != NULL_TREE
1397 && TREE_CODE (TREE_VALUE (attr1)) == TREE_LIST
1398 && TREE_VALUE (attr2) != NULL_TREE
1399 && TREE_CODE (TREE_VALUE (attr2)) == TREE_LIST)
1400 {
1401 /* Handle attribute format. */
1402 if (is_attribute_p ("format", get_attribute_name (attr1)))
1403 {
1404 attr1 = TREE_VALUE (attr1);
1405 attr2 = TREE_VALUE (attr2);
1406 /* Compare the archetypes (printf/scanf/strftime/...). */
1407 if (!cmp_attrib_identifiers (TREE_VALUE (attr1), TREE_VALUE (attr2)))
1408 return false;
1409 /* Archetypes are the same. Compare the rest. */
1410 return (simple_cst_list_equal (TREE_CHAIN (attr1),
1411 TREE_CHAIN (attr2)) == 1);
1412 }
1413 return (simple_cst_list_equal (TREE_VALUE (attr1),
1414 TREE_VALUE (attr2)) == 1);
1415 }
1416
1417 if (TREE_VALUE (attr1)
1418 && TREE_CODE (TREE_VALUE (attr1)) == OMP_CLAUSE
1419 && TREE_VALUE (attr2)
1420 && TREE_CODE (TREE_VALUE (attr2)) == OMP_CLAUSE)
1421 return omp_declare_simd_clauses_equal (TREE_VALUE (attr1),
1422 TREE_VALUE (attr2));
1423
1424 return (simple_cst_equal (TREE_VALUE (attr1), TREE_VALUE (attr2)) == 1);
1425 }
1426
1427 /* Return 0 if the attributes for two types are incompatible, 1 if they
1428 are compatible, and 2 if they are nearly compatible (which causes a
1429 warning to be generated). */
1430 int
comp_type_attributes(const_tree type1,const_tree type2)1431 comp_type_attributes (const_tree type1, const_tree type2)
1432 {
1433 const_tree a1 = TYPE_ATTRIBUTES (type1);
1434 const_tree a2 = TYPE_ATTRIBUTES (type2);
1435 const_tree a;
1436
1437 if (a1 == a2)
1438 return 1;
1439 for (a = a1; a != NULL_TREE; a = TREE_CHAIN (a))
1440 {
1441 const struct attribute_spec *as;
1442 const_tree attr;
1443
1444 as = lookup_attribute_spec (get_attribute_name (a));
1445 if (!as || as->affects_type_identity == false)
1446 continue;
1447
1448 attr = lookup_attribute (as->name, CONST_CAST_TREE (a2));
1449 if (!attr || !attribute_value_equal (a, attr))
1450 break;
1451 }
1452 if (!a)
1453 {
1454 for (a = a2; a != NULL_TREE; a = TREE_CHAIN (a))
1455 {
1456 const struct attribute_spec *as;
1457
1458 as = lookup_attribute_spec (get_attribute_name (a));
1459 if (!as || as->affects_type_identity == false)
1460 continue;
1461
1462 if (!lookup_attribute (as->name, CONST_CAST_TREE (a1)))
1463 break;
1464 /* We don't need to compare trees again, as we did this
1465 already in first loop. */
1466 }
1467 /* All types - affecting identity - are equal, so
1468 there is no need to call target hook for comparison. */
1469 if (!a)
1470 return 1;
1471 }
1472 if (lookup_attribute ("transaction_safe", CONST_CAST_TREE (a)))
1473 return 0;
1474 if ((lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type1)) != NULL)
1475 ^ (lookup_attribute ("nocf_check", TYPE_ATTRIBUTES (type2)) != NULL))
1476 return 0;
1477 /* As some type combinations - like default calling-convention - might
1478 be compatible, we have to call the target hook to get the final result. */
1479 return targetm.comp_type_attributes (type1, type2);
1480 }
1481
1482 /* PREDICATE acts as a function of type:
1483
1484 (const_tree attr, const attribute_spec *as) -> bool
1485
1486 where ATTR is an attribute and AS is its possibly-null specification.
1487 Return a list of every attribute in attribute list ATTRS for which
1488 PREDICATE is true. Return ATTRS itself if PREDICATE returns true
1489 for every attribute. */
1490
1491 template<typename Predicate>
1492 tree
remove_attributes_matching(tree attrs,Predicate predicate)1493 remove_attributes_matching (tree attrs, Predicate predicate)
1494 {
1495 tree new_attrs = NULL_TREE;
1496 tree *ptr = &new_attrs;
1497 const_tree start = attrs;
1498 for (const_tree attr = attrs; attr; attr = TREE_CHAIN (attr))
1499 {
1500 tree name = get_attribute_name (attr);
1501 const attribute_spec *as = lookup_attribute_spec (name);
1502 const_tree end;
1503 if (!predicate (attr, as))
1504 end = attr;
1505 else if (start == attrs)
1506 continue;
1507 else
1508 end = TREE_CHAIN (attr);
1509
1510 for (; start != end; start = TREE_CHAIN (start))
1511 {
1512 *ptr = tree_cons (TREE_PURPOSE (start),
1513 TREE_VALUE (start), NULL_TREE);
1514 TREE_CHAIN (*ptr) = NULL_TREE;
1515 ptr = &TREE_CHAIN (*ptr);
1516 }
1517 start = TREE_CHAIN (attr);
1518 }
1519 gcc_assert (!start || start == attrs);
1520 return start ? attrs : new_attrs;
1521 }
1522
1523 /* If VALUE is true, return the subset of ATTRS that affect type identity,
1524 otherwise return the subset of ATTRS that don't affect type identity. */
1525
1526 tree
affects_type_identity_attributes(tree attrs,bool value)1527 affects_type_identity_attributes (tree attrs, bool value)
1528 {
1529 auto predicate = [value](const_tree, const attribute_spec *as) -> bool
1530 {
1531 return bool (as && as->affects_type_identity) == value;
1532 };
1533 return remove_attributes_matching (attrs, predicate);
1534 }
1535
1536 /* Remove attributes that affect type identity from ATTRS unless the
1537 same attributes occur in OK_ATTRS. */
1538
1539 tree
restrict_type_identity_attributes_to(tree attrs,tree ok_attrs)1540 restrict_type_identity_attributes_to (tree attrs, tree ok_attrs)
1541 {
1542 auto predicate = [ok_attrs](const_tree attr,
1543 const attribute_spec *as) -> bool
1544 {
1545 if (!as || !as->affects_type_identity)
1546 return true;
1547
1548 for (tree ok_attr = lookup_attribute (as->name, ok_attrs);
1549 ok_attr;
1550 ok_attr = lookup_attribute (as->name, TREE_CHAIN (ok_attr)))
1551 if (simple_cst_equal (TREE_VALUE (ok_attr), TREE_VALUE (attr)) == 1)
1552 return true;
1553
1554 return false;
1555 };
1556 return remove_attributes_matching (attrs, predicate);
1557 }
1558
1559 /* Return a type like TTYPE except that its TYPE_ATTRIBUTE
1560 is ATTRIBUTE.
1561
1562 Record such modified types already made so we don't make duplicates. */
1563
1564 tree
build_type_attribute_variant(tree ttype,tree attribute)1565 build_type_attribute_variant (tree ttype, tree attribute)
1566 {
1567 return build_type_attribute_qual_variant (ttype, attribute,
1568 TYPE_QUALS (ttype));
1569 }
1570
1571 /* A variant of lookup_attribute() that can be used with an identifier
1572 as the first argument, and where the identifier can be either
1573 'text' or '__text__'.
1574
1575 Given an attribute ATTR_IDENTIFIER, and a list of attributes LIST,
1576 return a pointer to the attribute's list element if the attribute
1577 is part of the list, or NULL_TREE if not found. If the attribute
1578 appears more than once, this only returns the first occurrence; the
1579 TREE_CHAIN of the return value should be passed back in if further
1580 occurrences are wanted. ATTR_IDENTIFIER must be an identifier but
1581 can be in the form 'text' or '__text__'. */
1582 static tree
lookup_ident_attribute(tree attr_identifier,tree list)1583 lookup_ident_attribute (tree attr_identifier, tree list)
1584 {
1585 gcc_checking_assert (TREE_CODE (attr_identifier) == IDENTIFIER_NODE);
1586
1587 while (list)
1588 {
1589 gcc_checking_assert (TREE_CODE (get_attribute_name (list))
1590 == IDENTIFIER_NODE);
1591
1592 if (cmp_attrib_identifiers (attr_identifier,
1593 get_attribute_name (list)))
1594 /* Found it. */
1595 break;
1596 list = TREE_CHAIN (list);
1597 }
1598
1599 return list;
1600 }
1601
1602 /* Remove any instances of attribute ATTR_NAME in LIST and return the
1603 modified list. */
1604
1605 tree
remove_attribute(const char * attr_name,tree list)1606 remove_attribute (const char *attr_name, tree list)
1607 {
1608 tree *p;
1609 gcc_checking_assert (attr_name[0] != '_');
1610
1611 for (p = &list; *p;)
1612 {
1613 tree l = *p;
1614
1615 tree attr = get_attribute_name (l);
1616 if (is_attribute_p (attr_name, attr))
1617 *p = TREE_CHAIN (l);
1618 else
1619 p = &TREE_CHAIN (l);
1620 }
1621
1622 return list;
1623 }
1624
1625 /* Return an attribute list that is the union of a1 and a2. */
1626
1627 tree
merge_attributes(tree a1,tree a2)1628 merge_attributes (tree a1, tree a2)
1629 {
1630 tree attributes;
1631
1632 /* Either one unset? Take the set one. */
1633
1634 if ((attributes = a1) == 0)
1635 attributes = a2;
1636
1637 /* One that completely contains the other? Take it. */
1638
1639 else if (a2 != 0 && ! attribute_list_contained (a1, a2))
1640 {
1641 if (attribute_list_contained (a2, a1))
1642 attributes = a2;
1643 else
1644 {
1645 /* Pick the longest list, and hang on the other list. */
1646
1647 if (list_length (a1) < list_length (a2))
1648 attributes = a2, a2 = a1;
1649
1650 for (; a2 != 0; a2 = TREE_CHAIN (a2))
1651 {
1652 tree a;
1653 for (a = lookup_ident_attribute (get_attribute_name (a2),
1654 attributes);
1655 a != NULL_TREE && !attribute_value_equal (a, a2);
1656 a = lookup_ident_attribute (get_attribute_name (a2),
1657 TREE_CHAIN (a)))
1658 ;
1659 if (a == NULL_TREE)
1660 {
1661 a1 = copy_node (a2);
1662 TREE_CHAIN (a1) = attributes;
1663 attributes = a1;
1664 }
1665 }
1666 }
1667 }
1668 return attributes;
1669 }
1670
1671 /* Given types T1 and T2, merge their attributes and return
1672 the result. */
1673
1674 tree
merge_type_attributes(tree t1,tree t2)1675 merge_type_attributes (tree t1, tree t2)
1676 {
1677 return merge_attributes (TYPE_ATTRIBUTES (t1),
1678 TYPE_ATTRIBUTES (t2));
1679 }
1680
1681 /* Given decls OLDDECL and NEWDECL, merge their attributes and return
1682 the result. */
1683
1684 tree
merge_decl_attributes(tree olddecl,tree newdecl)1685 merge_decl_attributes (tree olddecl, tree newdecl)
1686 {
1687 return merge_attributes (DECL_ATTRIBUTES (olddecl),
1688 DECL_ATTRIBUTES (newdecl));
1689 }
1690
1691 /* Duplicate all attributes with name NAME in ATTR list to *ATTRS if
1692 they are missing there. */
1693
1694 void
duplicate_one_attribute(tree * attrs,tree attr,const char * name)1695 duplicate_one_attribute (tree *attrs, tree attr, const char *name)
1696 {
1697 attr = lookup_attribute (name, attr);
1698 if (!attr)
1699 return;
1700 tree a = lookup_attribute (name, *attrs);
1701 while (attr)
1702 {
1703 tree a2;
1704 for (a2 = a; a2; a2 = lookup_attribute (name, TREE_CHAIN (a2)))
1705 if (attribute_value_equal (attr, a2))
1706 break;
1707 if (!a2)
1708 {
1709 a2 = copy_node (attr);
1710 TREE_CHAIN (a2) = *attrs;
1711 *attrs = a2;
1712 }
1713 attr = lookup_attribute (name, TREE_CHAIN (attr));
1714 }
1715 }
1716
1717 /* Duplicate all attributes from user DECL to the corresponding
1718 builtin that should be propagated. */
1719
1720 void
copy_attributes_to_builtin(tree decl)1721 copy_attributes_to_builtin (tree decl)
1722 {
1723 tree b = builtin_decl_explicit (DECL_FUNCTION_CODE (decl));
1724 if (b)
1725 duplicate_one_attribute (&DECL_ATTRIBUTES (b),
1726 DECL_ATTRIBUTES (decl), "omp declare simd");
1727 }
1728
1729 #if TARGET_DLLIMPORT_DECL_ATTRIBUTES
1730
1731 /* Specialization of merge_decl_attributes for various Windows targets.
1732
1733 This handles the following situation:
1734
1735 __declspec (dllimport) int foo;
1736 int foo;
1737
1738 The second instance of `foo' nullifies the dllimport. */
1739
1740 tree
merge_dllimport_decl_attributes(tree old,tree new_tree)1741 merge_dllimport_decl_attributes (tree old, tree new_tree)
1742 {
1743 tree a;
1744 int delete_dllimport_p = 1;
1745
1746 /* What we need to do here is remove from `old' dllimport if it doesn't
1747 appear in `new'. dllimport behaves like extern: if a declaration is
1748 marked dllimport and a definition appears later, then the object
1749 is not dllimport'd. We also remove a `new' dllimport if the old list
1750 contains dllexport: dllexport always overrides dllimport, regardless
1751 of the order of declaration. */
1752 if (!VAR_OR_FUNCTION_DECL_P (new_tree))
1753 delete_dllimport_p = 0;
1754 else if (DECL_DLLIMPORT_P (new_tree)
1755 && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
1756 {
1757 DECL_DLLIMPORT_P (new_tree) = 0;
1758 warning (OPT_Wattributes, "%q+D already declared with dllexport "
1759 "attribute: dllimport ignored", new_tree);
1760 }
1761 else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new_tree))
1762 {
1763 /* Warn about overriding a symbol that has already been used, e.g.:
1764 extern int __attribute__ ((dllimport)) foo;
1765 int* bar () {return &foo;}
1766 int foo;
1767 */
1768 if (TREE_USED (old))
1769 {
1770 warning (0, "%q+D redeclared without dllimport attribute "
1771 "after being referenced with dll linkage", new_tree);
1772 /* If we have used a variable's address with dllimport linkage,
1773 keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
1774 decl may already have had TREE_CONSTANT computed.
1775 We still remove the attribute so that assembler code refers
1776 to '&foo rather than '_imp__foo'. */
1777 if (VAR_P (old) && TREE_ADDRESSABLE (old))
1778 DECL_DLLIMPORT_P (new_tree) = 1;
1779 }
1780
1781 /* Let an inline definition silently override the external reference,
1782 but otherwise warn about attribute inconsistency. */
1783 else if (VAR_P (new_tree) || !DECL_DECLARED_INLINE_P (new_tree))
1784 warning (OPT_Wattributes, "%q+D redeclared without dllimport "
1785 "attribute: previous dllimport ignored", new_tree);
1786 }
1787 else
1788 delete_dllimport_p = 0;
1789
1790 a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new_tree));
1791
1792 if (delete_dllimport_p)
1793 a = remove_attribute ("dllimport", a);
1794
1795 return a;
1796 }
1797
1798 /* Handle a "dllimport" or "dllexport" attribute; arguments as in
1799 struct attribute_spec.handler. */
1800
1801 tree
handle_dll_attribute(tree * pnode,tree name,tree args,int flags,bool * no_add_attrs)1802 handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
1803 bool *no_add_attrs)
1804 {
1805 tree node = *pnode;
1806 bool is_dllimport;
1807
1808 /* These attributes may apply to structure and union types being created,
1809 but otherwise should pass to the declaration involved. */
1810 if (!DECL_P (node))
1811 {
1812 if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
1813 | (int) ATTR_FLAG_ARRAY_NEXT))
1814 {
1815 *no_add_attrs = true;
1816 return tree_cons (name, args, NULL_TREE);
1817 }
1818 if (TREE_CODE (node) == RECORD_TYPE
1819 || TREE_CODE (node) == UNION_TYPE)
1820 {
1821 node = TYPE_NAME (node);
1822 if (!node)
1823 return NULL_TREE;
1824 }
1825 else
1826 {
1827 warning (OPT_Wattributes, "%qE attribute ignored",
1828 name);
1829 *no_add_attrs = true;
1830 return NULL_TREE;
1831 }
1832 }
1833
1834 if (!VAR_OR_FUNCTION_DECL_P (node) && TREE_CODE (node) != TYPE_DECL)
1835 {
1836 *no_add_attrs = true;
1837 warning (OPT_Wattributes, "%qE attribute ignored",
1838 name);
1839 return NULL_TREE;
1840 }
1841
1842 if (TREE_CODE (node) == TYPE_DECL
1843 && TREE_CODE (TREE_TYPE (node)) != RECORD_TYPE
1844 && TREE_CODE (TREE_TYPE (node)) != UNION_TYPE)
1845 {
1846 *no_add_attrs = true;
1847 warning (OPT_Wattributes, "%qE attribute ignored",
1848 name);
1849 return NULL_TREE;
1850 }
1851
1852 is_dllimport = is_attribute_p ("dllimport", name);
1853
1854 /* Report error on dllimport ambiguities seen now before they cause
1855 any damage. */
1856 if (is_dllimport)
1857 {
1858 /* Honor any target-specific overrides. */
1859 if (!targetm.valid_dllimport_attribute_p (node))
1860 *no_add_attrs = true;
1861
1862 else if (TREE_CODE (node) == FUNCTION_DECL
1863 && DECL_DECLARED_INLINE_P (node))
1864 {
1865 warning (OPT_Wattributes, "inline function %q+D declared as "
1866 "dllimport: attribute ignored", node);
1867 *no_add_attrs = true;
1868 }
1869 /* Like MS, treat definition of dllimported variables and
1870 non-inlined functions on declaration as syntax errors. */
1871 else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
1872 {
1873 error ("function %q+D definition is marked dllimport", node);
1874 *no_add_attrs = true;
1875 }
1876
1877 else if (VAR_P (node))
1878 {
1879 if (DECL_INITIAL (node))
1880 {
1881 error ("variable %q+D definition is marked dllimport",
1882 node);
1883 *no_add_attrs = true;
1884 }
1885
1886 /* `extern' needn't be specified with dllimport.
1887 Specify `extern' now and hope for the best. Sigh. */
1888 DECL_EXTERNAL (node) = 1;
1889 /* Also, implicitly give dllimport'd variables declared within
1890 a function global scope, unless declared static. */
1891 if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
1892 TREE_PUBLIC (node) = 1;
1893 /* Clear TREE_STATIC because DECL_EXTERNAL is set, unless
1894 it is a C++ static data member. */
1895 if (DECL_CONTEXT (node) == NULL_TREE
1896 || !RECORD_OR_UNION_TYPE_P (DECL_CONTEXT (node)))
1897 TREE_STATIC (node) = 0;
1898 }
1899
1900 if (*no_add_attrs == false)
1901 DECL_DLLIMPORT_P (node) = 1;
1902 }
1903 else if (TREE_CODE (node) == FUNCTION_DECL
1904 && DECL_DECLARED_INLINE_P (node)
1905 && flag_keep_inline_dllexport)
1906 /* An exported function, even if inline, must be emitted. */
1907 DECL_EXTERNAL (node) = 0;
1908
1909 /* Report error if symbol is not accessible at global scope. */
1910 if (!TREE_PUBLIC (node) && VAR_OR_FUNCTION_DECL_P (node))
1911 {
1912 error ("external linkage required for symbol %q+D because of "
1913 "%qE attribute", node, name);
1914 *no_add_attrs = true;
1915 }
1916
1917 /* A dllexport'd entity must have default visibility so that other
1918 program units (shared libraries or the main executable) can see
1919 it. A dllimport'd entity must have default visibility so that
1920 the linker knows that undefined references within this program
1921 unit can be resolved by the dynamic linker. */
1922 if (!*no_add_attrs)
1923 {
1924 if (DECL_VISIBILITY_SPECIFIED (node)
1925 && DECL_VISIBILITY (node) != VISIBILITY_DEFAULT)
1926 error ("%qE implies default visibility, but %qD has already "
1927 "been declared with a different visibility",
1928 name, node);
1929 DECL_VISIBILITY (node) = VISIBILITY_DEFAULT;
1930 DECL_VISIBILITY_SPECIFIED (node) = 1;
1931 }
1932
1933 return NULL_TREE;
1934 }
1935
1936 #endif /* TARGET_DLLIMPORT_DECL_ATTRIBUTES */
1937
1938 /* Given two lists of attributes, return true if list l2 is
1939 equivalent to l1. */
1940
1941 int
attribute_list_equal(const_tree l1,const_tree l2)1942 attribute_list_equal (const_tree l1, const_tree l2)
1943 {
1944 if (l1 == l2)
1945 return 1;
1946
1947 return attribute_list_contained (l1, l2)
1948 && attribute_list_contained (l2, l1);
1949 }
1950
1951 /* Given two lists of attributes, return true if list L2 is
1952 completely contained within L1. */
1953 /* ??? This would be faster if attribute names were stored in a canonicalized
1954 form. Otherwise, if L1 uses `foo' and L2 uses `__foo__', the long method
1955 must be used to show these elements are equivalent (which they are). */
1956 /* ??? It's not clear that attributes with arguments will always be handled
1957 correctly. */
1958
1959 int
attribute_list_contained(const_tree l1,const_tree l2)1960 attribute_list_contained (const_tree l1, const_tree l2)
1961 {
1962 const_tree t1, t2;
1963
1964 /* First check the obvious, maybe the lists are identical. */
1965 if (l1 == l2)
1966 return 1;
1967
1968 /* Maybe the lists are similar. */
1969 for (t1 = l1, t2 = l2;
1970 t1 != 0 && t2 != 0
1971 && get_attribute_name (t1) == get_attribute_name (t2)
1972 && TREE_VALUE (t1) == TREE_VALUE (t2);
1973 t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
1974 ;
1975
1976 /* Maybe the lists are equal. */
1977 if (t1 == 0 && t2 == 0)
1978 return 1;
1979
1980 for (; t2 != 0; t2 = TREE_CHAIN (t2))
1981 {
1982 const_tree attr;
1983 /* This CONST_CAST is okay because lookup_attribute does not
1984 modify its argument and the return value is assigned to a
1985 const_tree. */
1986 for (attr = lookup_ident_attribute (get_attribute_name (t2),
1987 CONST_CAST_TREE (l1));
1988 attr != NULL_TREE && !attribute_value_equal (t2, attr);
1989 attr = lookup_ident_attribute (get_attribute_name (t2),
1990 TREE_CHAIN (attr)))
1991 ;
1992
1993 if (attr == NULL_TREE)
1994 return 0;
1995 }
1996
1997 return 1;
1998 }
1999
2000 /* The backbone of lookup_attribute(). ATTR_LEN is the string length
2001 of ATTR_NAME, and LIST is not NULL_TREE.
2002
2003 The function is called from lookup_attribute in order to optimize
2004 for size. */
2005
2006 tree
private_lookup_attribute(const char * attr_name,size_t attr_len,tree list)2007 private_lookup_attribute (const char *attr_name, size_t attr_len, tree list)
2008 {
2009 while (list)
2010 {
2011 tree attr = get_attribute_name (list);
2012 size_t ident_len = IDENTIFIER_LENGTH (attr);
2013 if (cmp_attribs (attr_name, attr_len, IDENTIFIER_POINTER (attr),
2014 ident_len))
2015 break;
2016 list = TREE_CHAIN (list);
2017 }
2018
2019 return list;
2020 }
2021
2022 /* Return true if the function decl or type NODE has been declared
2023 with attribute ANAME among attributes ATTRS. */
2024
2025 static bool
has_attribute(tree node,tree attrs,const char * aname)2026 has_attribute (tree node, tree attrs, const char *aname)
2027 {
2028 if (!strcmp (aname, "const"))
2029 {
2030 if (DECL_P (node) && TREE_READONLY (node))
2031 return true;
2032 }
2033 else if (!strcmp (aname, "malloc"))
2034 {
2035 if (DECL_P (node) && DECL_IS_MALLOC (node))
2036 return true;
2037 }
2038 else if (!strcmp (aname, "noreturn"))
2039 {
2040 if (DECL_P (node) && TREE_THIS_VOLATILE (node))
2041 return true;
2042 }
2043 else if (!strcmp (aname, "nothrow"))
2044 {
2045 if (TREE_NOTHROW (node))
2046 return true;
2047 }
2048 else if (!strcmp (aname, "pure"))
2049 {
2050 if (DECL_P (node) && DECL_PURE_P (node))
2051 return true;
2052 }
2053
2054 return lookup_attribute (aname, attrs);
2055 }
2056
2057 /* Return the number of mismatched function or type attributes between
2058 the "template" function declaration TMPL and DECL. The word "template"
2059 doesn't necessarily refer to a C++ template but rather a declaration
2060 whose attributes should be matched by those on DECL. For a non-zero
2061 return value set *ATTRSTR to a string representation of the list of
2062 mismatched attributes with quoted names.
2063 ATTRLIST is a list of additional attributes that SPEC should be
2064 taken to ultimately be declared with. */
2065
2066 unsigned
decls_mismatched_attributes(tree tmpl,tree decl,tree attrlist,const char * const blacklist[],pretty_printer * attrstr)2067 decls_mismatched_attributes (tree tmpl, tree decl, tree attrlist,
2068 const char* const blacklist[],
2069 pretty_printer *attrstr)
2070 {
2071 if (TREE_CODE (tmpl) != FUNCTION_DECL)
2072 return 0;
2073
2074 /* Avoid warning if either declaration or its type is deprecated. */
2075 if (TREE_DEPRECATED (tmpl)
2076 || TREE_DEPRECATED (decl))
2077 return 0;
2078
2079 const tree tmpls[] = { tmpl, TREE_TYPE (tmpl) };
2080 const tree decls[] = { decl, TREE_TYPE (decl) };
2081
2082 if (TREE_DEPRECATED (tmpls[1])
2083 || TREE_DEPRECATED (decls[1])
2084 || TREE_DEPRECATED (TREE_TYPE (tmpls[1]))
2085 || TREE_DEPRECATED (TREE_TYPE (decls[1])))
2086 return 0;
2087
2088 tree tmpl_attrs[] = { DECL_ATTRIBUTES (tmpl), TYPE_ATTRIBUTES (tmpls[1]) };
2089 tree decl_attrs[] = { DECL_ATTRIBUTES (decl), TYPE_ATTRIBUTES (decls[1]) };
2090
2091 if (!decl_attrs[0])
2092 decl_attrs[0] = attrlist;
2093 else if (!decl_attrs[1])
2094 decl_attrs[1] = attrlist;
2095
2096 /* Avoid warning if the template has no attributes. */
2097 if (!tmpl_attrs[0] && !tmpl_attrs[1])
2098 return 0;
2099
2100 /* Avoid warning if either declaration contains an attribute on
2101 the white list below. */
2102 const char* const whitelist[] = {
2103 "error", "warning"
2104 };
2105
2106 for (unsigned i = 0; i != 2; ++i)
2107 for (unsigned j = 0; j != sizeof whitelist / sizeof *whitelist; ++j)
2108 if (lookup_attribute (whitelist[j], tmpl_attrs[i])
2109 || lookup_attribute (whitelist[j], decl_attrs[i]))
2110 return 0;
2111
2112 /* Put together a list of the black-listed attributes that the template
2113 is declared with and the declaration is not, in case it's not apparent
2114 from the most recent declaration of the template. */
2115 unsigned nattrs = 0;
2116
2117 for (unsigned i = 0; blacklist[i]; ++i)
2118 {
2119 /* Attribute leaf only applies to extern functions. Avoid mentioning
2120 it when it's missing from a static declaration. */
2121 if (!TREE_PUBLIC (decl)
2122 && !strcmp ("leaf", blacklist[i]))
2123 continue;
2124
2125 for (unsigned j = 0; j != 2; ++j)
2126 {
2127 if (!has_attribute (tmpls[j], tmpl_attrs[j], blacklist[i]))
2128 continue;
2129
2130 bool found = false;
2131 unsigned kmax = 1 + !!decl_attrs[1];
2132 for (unsigned k = 0; k != kmax; ++k)
2133 {
2134 if (has_attribute (decls[k], decl_attrs[k], blacklist[i]))
2135 {
2136 found = true;
2137 break;
2138 }
2139 }
2140
2141 if (!found)
2142 {
2143 if (nattrs)
2144 pp_string (attrstr, ", ");
2145 pp_begin_quote (attrstr, pp_show_color (global_dc->printer));
2146 pp_string (attrstr, blacklist[i]);
2147 pp_end_quote (attrstr, pp_show_color (global_dc->printer));
2148 ++nattrs;
2149 }
2150
2151 break;
2152 }
2153 }
2154
2155 return nattrs;
2156 }
2157
2158 /* Issue a warning for the declaration ALIAS for TARGET where ALIAS
2159 specifies either attributes that are incompatible with those of
2160 TARGET, or attributes that are missing and that declaring ALIAS
2161 with would benefit. */
2162
2163 void
maybe_diag_alias_attributes(tree alias,tree target)2164 maybe_diag_alias_attributes (tree alias, tree target)
2165 {
2166 /* Do not expect attributes to match between aliases and ifunc
2167 resolvers. There is no obvious correspondence between them. */
2168 if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (alias)))
2169 return;
2170
2171 const char* const blacklist[] = {
2172 "alloc_align", "alloc_size", "cold", "const", "hot", "leaf", "malloc",
2173 "nonnull", "noreturn", "nothrow", "pure", "returns_nonnull",
2174 "returns_twice", NULL
2175 };
2176
2177 pretty_printer attrnames;
2178 if (warn_attribute_alias > 1)
2179 {
2180 /* With -Wattribute-alias=2 detect alias declarations that are more
2181 restrictive than their targets first. Those indicate potential
2182 codegen bugs. */
2183 if (unsigned n = decls_mismatched_attributes (alias, target, NULL_TREE,
2184 blacklist, &attrnames))
2185 {
2186 auto_diagnostic_group d;
2187 if (warning_n (DECL_SOURCE_LOCATION (alias),
2188 OPT_Wattribute_alias_, n,
2189 "%qD specifies more restrictive attribute than "
2190 "its target %qD: %s",
2191 "%qD specifies more restrictive attributes than "
2192 "its target %qD: %s",
2193 alias, target, pp_formatted_text (&attrnames)))
2194 inform (DECL_SOURCE_LOCATION (target),
2195 "%qD target declared here", alias);
2196 return;
2197 }
2198 }
2199
2200 /* Detect alias declarations that are less restrictive than their
2201 targets. Those suggest potential optimization opportunities
2202 (solved by adding the missing attribute(s) to the alias). */
2203 if (unsigned n = decls_mismatched_attributes (target, alias, NULL_TREE,
2204 blacklist, &attrnames))
2205 {
2206 auto_diagnostic_group d;
2207 if (warning_n (DECL_SOURCE_LOCATION (alias),
2208 OPT_Wmissing_attributes, n,
2209 "%qD specifies less restrictive attribute than "
2210 "its target %qD: %s",
2211 "%qD specifies less restrictive attributes than "
2212 "its target %qD: %s",
2213 alias, target, pp_formatted_text (&attrnames)))
2214 inform (DECL_SOURCE_LOCATION (target),
2215 "%qD target declared here", alias);
2216 }
2217 }
2218
2219 /* Initialize a mapping RWM for a call to a function declared with
2220 attribute access in ATTRS. Each attribute positional operand
2221 inserts one entry into the mapping with the operand number as
2222 the key. */
2223
2224 void
init_attr_rdwr_indices(rdwr_map * rwm,tree attrs)2225 init_attr_rdwr_indices (rdwr_map *rwm, tree attrs)
2226 {
2227 if (!attrs)
2228 return;
2229
2230 for (tree access = attrs;
2231 (access = lookup_attribute ("access", access));
2232 access = TREE_CHAIN (access))
2233 {
2234 /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
2235 is the attribute argument's value. */
2236 tree mode = TREE_VALUE (access);
2237 if (!mode)
2238 return;
2239
2240 /* The (optional) list of VLA bounds. */
2241 tree vblist = TREE_CHAIN (mode);
2242 mode = TREE_VALUE (mode);
2243 if (TREE_CODE (mode) != STRING_CST)
2244 continue;
2245 gcc_assert (TREE_CODE (mode) == STRING_CST);
2246
2247 if (vblist)
2248 vblist = nreverse (copy_list (TREE_VALUE (vblist)));
2249
2250 for (const char *m = TREE_STRING_POINTER (mode); *m; )
2251 {
2252 attr_access acc = { };
2253
2254 /* Skip the internal-only plus sign. */
2255 if (*m == '+')
2256 ++m;
2257
2258 acc.str = m;
2259 acc.mode = acc.from_mode_char (*m);
2260 acc.sizarg = UINT_MAX;
2261
2262 const char *end;
2263 acc.ptrarg = strtoul (++m, const_cast<char**>(&end), 10);
2264 m = end;
2265
2266 if (*m == '[')
2267 {
2268 /* Forms containing the square bracket are internal-only
2269 (not specified by an attribute declaration), and used
2270 for various forms of array and VLA parameters. */
2271 acc.internal_p = true;
2272
2273 /* Search to the closing bracket and look at the preceding
2274 code: it determines the form of the most significant
2275 bound of the array. Others prior to it encode the form
2276 of interior VLA bounds. They're not of interest here. */
2277 end = strchr (m, ']');
2278 const char *p = end;
2279 gcc_assert (p);
2280
2281 while (ISDIGIT (p[-1]))
2282 --p;
2283
2284 if (ISDIGIT (*p))
2285 {
2286 /* A digit denotes a constant bound (as in T[3]). */
2287 acc.static_p = p[-1] == 's';
2288 acc.minsize = strtoull (p, NULL, 10);
2289 }
2290 else if (' ' == p[-1])
2291 {
2292 /* A space denotes an ordinary array of unspecified bound
2293 (as in T[]). */
2294 acc.minsize = 0;
2295 }
2296 else if ('*' == p[-1] || '$' == p[-1])
2297 {
2298 /* An asterisk denotes a VLA. When the closing bracket
2299 is followed by a comma and a dollar sign its bound is
2300 on the list. Otherwise it's a VLA with an unspecified
2301 bound. */
2302 acc.static_p = p[-2] == 's';
2303 acc.minsize = HOST_WIDE_INT_M1U;
2304 }
2305
2306 m = end + 1;
2307 }
2308
2309 if (*m == ',')
2310 {
2311 ++m;
2312 do
2313 {
2314 if (*m == '$')
2315 {
2316 ++m;
2317 if (!acc.size && vblist)
2318 {
2319 /* Extract the list of VLA bounds for the current
2320 parameter, store it in ACC.SIZE, and advance
2321 to the list of bounds for the next VLA parameter.
2322 */
2323 acc.size = TREE_VALUE (vblist);
2324 vblist = TREE_CHAIN (vblist);
2325 }
2326 }
2327
2328 if (ISDIGIT (*m))
2329 {
2330 /* Extract the positional argument. It's absent
2331 for VLAs whose bound doesn't name a function
2332 parameter. */
2333 unsigned pos = strtoul (m, const_cast<char**>(&end), 10);
2334 if (acc.sizarg == UINT_MAX)
2335 acc.sizarg = pos;
2336 m = end;
2337 }
2338 }
2339 while (*m == '$');
2340 }
2341
2342 acc.end = m;
2343
2344 bool existing;
2345 auto &ref = rwm->get_or_insert (acc.ptrarg, &existing);
2346 if (existing)
2347 {
2348 /* Merge the new spec with the existing. */
2349 if (acc.minsize == HOST_WIDE_INT_M1U)
2350 ref.minsize = HOST_WIDE_INT_M1U;
2351
2352 if (acc.sizarg != UINT_MAX)
2353 ref.sizarg = acc.sizarg;
2354
2355 if (acc.mode)
2356 ref.mode = acc.mode;
2357 }
2358 else
2359 ref = acc;
2360
2361 /* Unconditionally add an entry for the required pointer
2362 operand of the attribute, and one for the optional size
2363 operand when it's specified. */
2364 if (acc.sizarg != UINT_MAX)
2365 rwm->put (acc.sizarg, acc);
2366 }
2367 }
2368 }
2369
2370 /* Return the access specification for a function parameter PARM
2371 or null if the current function has no such specification. */
2372
2373 attr_access *
get_parm_access(rdwr_map & rdwr_idx,tree parm,tree fndecl)2374 get_parm_access (rdwr_map &rdwr_idx, tree parm,
2375 tree fndecl /* = current_function_decl */)
2376 {
2377 tree fntype = TREE_TYPE (fndecl);
2378 init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype));
2379
2380 if (rdwr_idx.is_empty ())
2381 return NULL;
2382
2383 unsigned argpos = 0;
2384 tree fnargs = DECL_ARGUMENTS (fndecl);
2385 for (tree arg = fnargs; arg; arg = TREE_CHAIN (arg), ++argpos)
2386 if (arg == parm)
2387 return rdwr_idx.get (argpos);
2388
2389 return NULL;
2390 }
2391
2392 /* Return the internal representation as STRING_CST. Internal positional
2393 arguments are zero-based. */
2394
2395 tree
to_internal_string() const2396 attr_access::to_internal_string () const
2397 {
2398 return build_string (end - str, str);
2399 }
2400
2401 /* Return the human-readable representation of the external attribute
2402 specification (as it might appear in the source code) as STRING_CST.
2403 External positional arguments are one-based. */
2404
2405 tree
to_external_string() const2406 attr_access::to_external_string () const
2407 {
2408 char buf[80];
2409 gcc_assert (mode != access_deferred);
2410 int len = snprintf (buf, sizeof buf, "access (%s, %u",
2411 mode_names[mode], ptrarg + 1);
2412 if (sizarg != UINT_MAX)
2413 len += snprintf (buf + len, sizeof buf - len, ", %u", sizarg + 1);
2414 strcpy (buf + len, ")");
2415 return build_string (len + 2, buf);
2416 }
2417
2418 /* Return the number of specified VLA bounds and set *nunspec to
2419 the number of unspecified ones (those designated by [*]). */
2420
2421 unsigned
vla_bounds(unsigned * nunspec) const2422 attr_access::vla_bounds (unsigned *nunspec) const
2423 {
2424 unsigned nbounds = 0;
2425 *nunspec = 0;
2426 /* STR points to the beginning of the specified string for the current
2427 argument that may be followed by the string for the next argument. */
2428 for (const char* p = strchr (str, ']'); p && *p != '['; --p)
2429 {
2430 if (*p == '*')
2431 ++*nunspec;
2432 else if (*p == '$')
2433 ++nbounds;
2434 }
2435 return nbounds;
2436 }
2437
2438 /* Reset front end-specific attribute access data from ATTRS.
2439 Called from the free_lang_data pass. */
2440
2441 /* static */ void
free_lang_data(tree attrs)2442 attr_access::free_lang_data (tree attrs)
2443 {
2444 for (tree acs = attrs; (acs = lookup_attribute ("access", acs));
2445 acs = TREE_CHAIN (acs))
2446 {
2447 tree vblist = TREE_VALUE (acs);
2448 vblist = TREE_CHAIN (vblist);
2449 if (!vblist)
2450 continue;
2451
2452 for (vblist = TREE_VALUE (vblist); vblist; vblist = TREE_CHAIN (vblist))
2453 {
2454 tree *pvbnd = &TREE_VALUE (vblist);
2455 if (!*pvbnd || DECL_P (*pvbnd))
2456 continue;
2457
2458 /* VLA bounds that are expressions as opposed to DECLs are
2459 only used in the front end. Reset them to keep front end
2460 trees leaking into the middle end (see pr97172) and to
2461 free up memory. */
2462 *pvbnd = NULL_TREE;
2463 }
2464 }
2465
2466 for (tree argspec = attrs; (argspec = lookup_attribute ("arg spec", argspec));
2467 argspec = TREE_CHAIN (argspec))
2468 {
2469 /* Same as above. */
2470 tree *pvblist = &TREE_VALUE (argspec);
2471 *pvblist = NULL_TREE;
2472 }
2473 }
2474
2475 /* Defined in attr_access. */
2476 constexpr char attr_access::mode_chars[];
2477 constexpr char attr_access::mode_names[][11];
2478
2479 /* Format an array, including a VLA, pointed to by TYPE and used as
2480 a function parameter as a human-readable string. ACC describes
2481 an access to the parameter and is used to determine the outermost
2482 form of the array including its bound which is otherwise obviated
2483 by its decay to pointer. Return the formatted string. */
2484
2485 std::string
array_as_string(tree type) const2486 attr_access::array_as_string (tree type) const
2487 {
2488 std::string typstr;
2489
2490 if (type == error_mark_node)
2491 return std::string ();
2492
2493 if (this->str)
2494 {
2495 /* For array parameters (but not pointers) create a temporary array
2496 type that corresponds to the form of the parameter including its
2497 qualifiers even though they apply to the pointer, not the array
2498 type. */
2499 const bool vla_p = minsize == HOST_WIDE_INT_M1U;
2500 tree eltype = TREE_TYPE (type);
2501 tree index_type = NULL_TREE;
2502
2503 if (minsize == HOST_WIDE_INT_M1U)
2504 {
2505 /* Determine if this is a VLA (an array whose most significant
2506 bound is nonconstant and whose access string has "$]" in it)
2507 extract the bound expression from SIZE. */
2508 const char *p = end;
2509 for ( ; p != str && *p-- != ']'; );
2510 if (*p == '$')
2511 /* SIZE may have been cleared. Use it with care. */
2512 index_type = build_index_type (size ? TREE_VALUE (size) : size);
2513 }
2514 else if (minsize)
2515 index_type = build_index_type (size_int (minsize - 1));
2516
2517 tree arat = NULL_TREE;
2518 if (static_p || vla_p)
2519 {
2520 tree flag = static_p ? integer_one_node : NULL_TREE;
2521 /* Hack: there's no language-independent way to encode
2522 the "static" specifier or the "*" notation in an array type.
2523 Add a "fake" attribute to have the pretty-printer add "static"
2524 or "*". The "[static N]" notation is only valid in the most
2525 significant bound but [*] can be used for any bound. Because
2526 [*] is represented the same as [0] this hack only works for
2527 the most significant bound like static and the others are
2528 rendered as [0]. */
2529 arat = build_tree_list (get_identifier ("array"), flag);
2530 }
2531
2532 const int quals = TYPE_QUALS (type);
2533 type = build_array_type (eltype, index_type);
2534 type = build_type_attribute_qual_variant (type, arat, quals);
2535 }
2536
2537 /* Format the type using the current pretty printer. The generic tree
2538 printer does a terrible job. */
2539 pretty_printer *pp = global_dc->printer->clone ();
2540 pp_printf (pp, "%qT", type);
2541 typstr = pp_formatted_text (pp);
2542 delete pp;
2543
2544 return typstr;
2545 }
2546
2547 #if CHECKING_P
2548
2549 namespace selftest
2550 {
2551
2552 /* Helper types to verify the consistency attribute exclusions. */
2553
2554 typedef std::pair<const char *, const char *> excl_pair;
2555
2556 struct excl_hash_traits: typed_noop_remove<excl_pair>
2557 {
2558 typedef excl_pair value_type;
2559 typedef value_type compare_type;
2560
hashselftest::excl_hash_traits2561 static hashval_t hash (const value_type &x)
2562 {
2563 hashval_t h1 = htab_hash_string (x.first);
2564 hashval_t h2 = htab_hash_string (x.second);
2565 return h1 ^ h2;
2566 }
2567
equalselftest::excl_hash_traits2568 static bool equal (const value_type &x, const value_type &y)
2569 {
2570 return !strcmp (x.first, y.first) && !strcmp (x.second, y.second);
2571 }
2572
mark_deletedselftest::excl_hash_traits2573 static void mark_deleted (value_type &x)
2574 {
2575 x = value_type (NULL, NULL);
2576 }
2577
2578 static const bool empty_zero_p = false;
2579
mark_emptyselftest::excl_hash_traits2580 static void mark_empty (value_type &x)
2581 {
2582 x = value_type ("", "");
2583 }
2584
is_deletedselftest::excl_hash_traits2585 static bool is_deleted (const value_type &x)
2586 {
2587 return !x.first && !x.second;
2588 }
2589
is_emptyselftest::excl_hash_traits2590 static bool is_empty (const value_type &x)
2591 {
2592 return !*x.first && !*x.second;
2593 }
2594 };
2595
2596
2597 /* Self-test to verify that each attribute exclusion is symmetric,
2598 meaning that if attribute A is encoded as incompatible with
2599 attribute B then the opposite relationship is also encoded.
2600 This test also detects most cases of misspelled attribute names
2601 in exclusions. */
2602
2603 static void
test_attribute_exclusions()2604 test_attribute_exclusions ()
2605 {
2606 /* Iterate over the array of attribute tables first (with TI0 as
2607 the index) and over the array of attribute_spec in each table
2608 (with SI0 as the index). */
2609 const size_t ntables = ARRAY_SIZE (attribute_tables);
2610
2611 /* Set of pairs of mutually exclusive attributes. */
2612 typedef hash_set<excl_pair, false, excl_hash_traits> exclusion_set;
2613 exclusion_set excl_set;
2614
2615 for (size_t ti0 = 0; ti0 != ntables; ++ti0)
2616 for (size_t s0 = 0; attribute_tables[ti0][s0].name; ++s0)
2617 {
2618 const attribute_spec::exclusions *excl
2619 = attribute_tables[ti0][s0].exclude;
2620
2621 /* Skip each attribute that doesn't define exclusions. */
2622 if (!excl)
2623 continue;
2624
2625 const char *attr_name = attribute_tables[ti0][s0].name;
2626
2627 /* Iterate over the set of exclusions for every attribute
2628 (with EI0 as the index) adding the exclusions defined
2629 for each to the set. */
2630 for (size_t ei0 = 0; excl[ei0].name; ++ei0)
2631 {
2632 const char *excl_name = excl[ei0].name;
2633
2634 if (!strcmp (attr_name, excl_name))
2635 continue;
2636
2637 excl_set.add (excl_pair (attr_name, excl_name));
2638 }
2639 }
2640
2641 /* Traverse the set of mutually exclusive pairs of attributes
2642 and verify that they are symmetric. */
2643 for (exclusion_set::iterator it = excl_set.begin ();
2644 it != excl_set.end ();
2645 ++it)
2646 {
2647 if (!excl_set.contains (excl_pair ((*it).second, (*it).first)))
2648 {
2649 /* An exclusion for an attribute has been found that
2650 doesn't have a corresponding exclusion in the opposite
2651 direction. */
2652 char desc[120];
2653 sprintf (desc, "'%s' attribute exclusion '%s' must be symmetric",
2654 (*it).first, (*it).second);
2655 fail (SELFTEST_LOCATION, desc);
2656 }
2657 }
2658 }
2659
2660 void
attribs_cc_tests()2661 attribs_cc_tests ()
2662 {
2663 test_attribute_exclusions ();
2664 }
2665
2666 } /* namespace selftest */
2667
2668 #endif /* CHECKING_P */
2669