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