1/* C-family attributes handling.
2 Copyright (C) 1992-2025 Free Software Foundation, Inc.
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
8Software Foundation; either version 3, or (at your option) any later
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
17along 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 "function.h"
26#include "tree.h"
27#include "memmodel.h"
28#include "c-common.h"
29#include "gimple-expr.h"
30#include "tm_p.h"
31#include "stringpool.h"
32#include "cgraph.h"
33#include "diagnostic.h"
34#include "intl.h"
35#include "stor-layout.h"
36#include "calls.h"
37#include "attribs.h"
38#include "varasm.h"
39#include "trans-mem.h"
40#include "c-objc.h"
41#include "common/common-target.h"
42#include "langhooks.h"
43#include "tree-inline.h"
44#include "ipa-strub.h"
45#include "toplev.h"
46#include "tree-iterator.h"
47#include "opts.h"
48#include "gimplify.h"
49#include "tree-pretty-print.h"
50#include "gcc-rich-location.h"
51#include "gcc-urlifier.h"
52
53static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
54static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
55static tree handle_common_attribute (tree *, tree, tree, int, bool *);
56static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
57static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
58static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
59static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
60 int, bool *);
61static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
62 int, bool *);
63static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
64 int, bool *);
65static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
66 bool *);
67static tree handle_no_sanitize_coverage_attribute (tree *, tree, tree, int,
68 bool *);
69static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
70 bool *);
71static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
72static tree handle_no_stack_protector_function_attribute (tree *, tree,
73 tree, int, bool *);
74static tree handle_strub_attribute (tree *, tree, tree, int, bool *);
75static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
76static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
77static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *);
78static tree handle_symver_attribute (tree *, tree, tree, int, bool *);
79static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
80static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
81static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
82static tree handle_always_inline_attribute (tree *, tree, tree, int,
83 bool *);
84static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
85static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
86static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
87static tree handle_error_attribute (tree *, tree, tree, int, bool *);
88static tree handle_used_attribute (tree *, tree, tree, int, bool *);
89static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *);
90static tree handle_externally_visible_attribute (tree *, tree, tree, int,
91 bool *);
92static tree handle_no_reorder_attribute (tree *, tree, tree, int,
93 bool *);
94static tree handle_const_attribute (tree *, tree, tree, int, bool *);
95static tree handle_transparent_union_attribute (tree *, tree, tree,
96 int, bool *);
97static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
98 int, bool *);
99static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
100static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
101static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
102static tree handle_section_attribute (tree *, tree, tree, int, bool *);
103static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *);
104static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
105 int, bool *);
106static tree handle_strict_flex_array_attribute (tree *, tree, tree,
107 int, bool *);
108static tree handle_counted_by_attribute (tree *, tree, tree,
109 int, bool *);
110static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
111static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
112static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
113static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *);
114static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
115static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
116static tree handle_visibility_attribute (tree *, tree, tree, int,
117 bool *);
118static tree handle_tls_model_attribute (tree *, tree, tree, int,
119 bool *);
120static tree handle_no_instrument_function_attribute (tree *, tree,
121 tree, int, bool *);
122static tree handle_no_profile_instrument_function_attribute (tree *, tree,
123 tree, int, bool *);
124static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
125static tree handle_dealloc_attribute (tree *, tree, tree, int, bool *);
126static tree handle_tainted_args_attribute (tree *, tree, tree, int, bool *);
127static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
128static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
129 bool *);
130static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
131static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
132static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
133static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
134static tree handle_unavailable_attribute (tree *, tree, tree, int,
135 bool *);
136static tree handle_vector_size_attribute (tree *, tree, tree, int,
137 bool *) ATTRIBUTE_NONNULL(3);
138static tree handle_vector_mask_attribute (tree *, tree, tree, int,
139 bool *) ATTRIBUTE_NONNULL(3);
140static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
141static tree handle_nonnull_if_nonzero_attribute (tree *, tree, tree, int,
142 bool *);
143static tree handle_nonstring_attribute (tree *, tree, tree, int, bool *);
144static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
145static tree handle_expected_throw_attribute (tree *, tree, tree, int, bool *);
146static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
147static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
148 bool *);
149static tree handle_access_attribute (tree *, tree, tree, int, bool *);
150
151static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
152static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
153static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
154static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
155static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
156static tree handle_assume_attribute (tree *, tree, tree, int, bool *);
157static tree handle_target_attribute (tree *, tree, tree, int, bool *);
158static tree handle_target_version_attribute (tree *, tree, tree, int, bool *);
159static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
160static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
161static tree ignore_attribute (tree *, tree, tree, int, bool *);
162static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
163static tree handle_zero_call_used_regs_attribute (tree *, tree, tree, int,
164 bool *);
165static tree handle_argspec_attribute (tree *, tree, tree, int, bool *);
166static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
167static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
168static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
169static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
170 bool *);
171static tree handle_omp_declare_variant_attribute (tree *, tree, tree, int,
172 bool *);
173static tree handle_simd_attribute (tree *, tree, tree, int, bool *);
174static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
175 bool *);
176static tree handle_non_overlapping_attribute (tree *, tree, tree, int, bool *);
177static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
178static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
179 int, bool *);
180static tree handle_copy_attribute (tree *, tree, tree, int, bool *);
181static tree handle_nsobject_attribute (tree *, tree, tree, int, bool *);
182static tree handle_objc_root_class_attribute (tree *, tree, tree, int, bool *);
183static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *);
184static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int,
185 bool *);
186static tree handle_hardbool_attribute (tree *, tree, tree, int, bool *);
187static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
188static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
189static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *);
190static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *);
191
192/* Helper to define attribute exclusions. */
193#define ATTR_EXCL(name, function, type, variable) \
194 { name, function, type, variable }
195
196/* Define attributes that are mutually exclusive with one another. */
197extern const struct attribute_spec::exclusions attr_aligned_exclusions[] =
198{
199 /* Attribute name exclusion applies to:
200 function, type, variable */
201 ATTR_EXCL ("aligned", true, false, false),
202 ATTR_EXCL ("packed", true, false, false),
203 ATTR_EXCL (NULL, false, false, false)
204};
205
206extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
207{
208 ATTR_EXCL ("cold", true, true, true),
209 ATTR_EXCL ("hot", true, true, true),
210 ATTR_EXCL (NULL, false, false, false)
211};
212
213static const struct attribute_spec::exclusions attr_common_exclusions[] =
214{
215 ATTR_EXCL ("common", true, true, true),
216 ATTR_EXCL ("nocommon", true, true, true),
217 ATTR_EXCL (NULL, false, false, false),
218};
219
220static const struct attribute_spec::exclusions attr_inline_exclusions[] =
221{
222 ATTR_EXCL ("noinline", true, true, true),
223 ATTR_EXCL (NULL, false, false, false),
224};
225
226static const struct attribute_spec::exclusions attr_always_inline_exclusions[] =
227{
228 ATTR_EXCL ("noinline", true, true, true),
229 ATTR_EXCL ("target_clones", true, true, true),
230 ATTR_EXCL (NULL, false, false, false),
231};
232
233static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
234{
235 ATTR_EXCL ("always_inline", true, true, true),
236 ATTR_EXCL ("gnu_inline", true, true, true),
237 ATTR_EXCL (NULL, false, false, false),
238};
239
240static const struct attribute_spec::exclusions attr_target_exclusions[] =
241{
242 ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
243 TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
244 ATTR_EXCL (NULL, false, false, false),
245};
246
247static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
248{
249 ATTR_EXCL ("always_inline", true, true, true),
250 ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
251 TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
252 ATTR_EXCL ("target_version", true, true, true),
253 ATTR_EXCL (NULL, false, false, false),
254};
255
256static const struct attribute_spec::exclusions attr_target_version_exclusions[] =
257{
258 ATTR_EXCL ("target_clones", true, true, true),
259 ATTR_EXCL (NULL, false, false, false),
260};
261
262extern const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
263{
264 ATTR_EXCL ("alloc_align", true, true, true),
265 ATTR_EXCL ("alloc_size", true, true, true),
266 ATTR_EXCL ("const", true, true, true),
267 ATTR_EXCL ("malloc", true, true, true),
268 ATTR_EXCL ("pure", true, true, true),
269 ATTR_EXCL ("returns_twice", true, true, true),
270 ATTR_EXCL ("warn_unused_result", true, true, true),
271 ATTR_EXCL (NULL, false, false, false),
272};
273
274static const struct attribute_spec::exclusions
275attr_warn_unused_result_exclusions[] =
276{
277 ATTR_EXCL ("noreturn", true, true, true),
278 ATTR_EXCL ("warn_unused_result", true, true, true),
279 ATTR_EXCL (NULL, false, false, false),
280};
281
282static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
283{
284 ATTR_EXCL ("noreturn", true, true, true),
285 ATTR_EXCL (NULL, false, false, false),
286};
287
288/* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */
289static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
290{
291 ATTR_EXCL ("const", true, true, true),
292 ATTR_EXCL ("noreturn", true, true, true),
293 ATTR_EXCL ("pure", true, true, true),
294 ATTR_EXCL (NULL, false, false, false),
295};
296
297static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
298{
299 ATTR_EXCL ("const", true, true, true),
300 ATTR_EXCL ("alloc_align", true, true, true),
301 ATTR_EXCL ("alloc_size", true, true, true),
302 ATTR_EXCL ("malloc", true, true, true),
303 ATTR_EXCL ("noreturn", true, true, true),
304 ATTR_EXCL ("pure", true, true, true),
305 ATTR_EXCL (NULL, false, false, false)
306};
307
308/* Exclusions that apply to attributes that put declarations in specific
309 sections. */
310static const struct attribute_spec::exclusions attr_section_exclusions[] =
311{
312 ATTR_EXCL ("noinit", true, true, true),
313 ATTR_EXCL ("persistent", true, true, true),
314 ATTR_EXCL ("section", true, true, true),
315 ATTR_EXCL (NULL, false, false, false),
316};
317
318static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
319{
320 ATTR_EXCL ("stack_protect", true, false, false),
321 ATTR_EXCL ("no_stack_protector", true, false, false),
322 ATTR_EXCL (NULL, false, false, false),
323};
324
325
326/* Table of machine-independent attributes common to all C-like languages.
327
328 Current list of processed common attributes: nonnull. */
329const struct attribute_spec c_common_gnu_attributes[] =
330{
331 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
332 affects_type_identity, handler, exclude } */
333 { .name: "signed_bool_precision", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
334 .handler: handle_signed_bool_precision_attribute, NULL },
335 { .name: "hardbool", .min_length: 0, .max_length: 2, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
336 .handler: handle_hardbool_attribute, NULL },
337 { .name: "packed", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
338 .handler: handle_packed_attribute,
339 .exclude: attr_aligned_exclusions },
340 { .name: "nocommon", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
341 .handler: handle_nocommon_attribute,
342 .exclude: attr_common_exclusions },
343 { .name: "common", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
344 .handler: handle_common_attribute,
345 .exclude: attr_common_exclusions },
346 { .name: "musttail", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false,
347 .affects_type_identity: false, .handler: handle_musttail_attribute, NULL },
348 /* FIXME: logically, noreturn attributes should be listed as
349 "false, true, true" and apply to function types. But implementing this
350 would require all the places in the compiler that use TREE_THIS_VOLATILE
351 on a decl to identify non-returning functions to be located and fixed
352 to check the function type instead. */
353 { .name: "noreturn", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
354 .handler: handle_noreturn_attribute,
355 .exclude: attr_noreturn_exclusions },
356 { .name: "volatile", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
357 .handler: handle_noreturn_attribute, NULL },
358 { .name: "stack_protect", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
359 .handler: handle_stack_protect_attribute,
360 .exclude: attr_stack_protect_exclusions },
361 { .name: "no_stack_protector", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
362 .handler: handle_no_stack_protector_function_attribute,
363 .exclude: attr_stack_protect_exclusions },
364 { .name: "strub", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
365 .handler: handle_strub_attribute, NULL },
366 { .name: "noinline", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
367 .handler: handle_noinline_attribute,
368 .exclude: attr_noinline_exclusions },
369 { .name: "noclone", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
370 .handler: handle_noclone_attribute, NULL },
371 { .name: "no_icf", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
372 .handler: handle_noicf_attribute, NULL },
373 { .name: "noipa", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
374 .handler: handle_noipa_attribute, NULL },
375 { .name: "leaf", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
376 .handler: handle_leaf_attribute, NULL },
377 { .name: "always_inline", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
378 .handler: handle_always_inline_attribute,
379 .exclude: attr_always_inline_exclusions },
380 { .name: "gnu_inline", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
381 .handler: handle_gnu_inline_attribute,
382 .exclude: attr_inline_exclusions },
383 { .name: "artificial", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
384 .handler: handle_artificial_attribute, NULL },
385 { .name: "flatten", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
386 .handler: handle_flatten_attribute, NULL },
387 { .name: "used", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
388 .handler: handle_used_attribute, NULL },
389 { .name: "unused", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
390 .handler: handle_unused_attribute, NULL },
391 { .name: "uninitialized", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
392 .handler: handle_uninitialized_attribute, NULL },
393 { .name: "retain", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
394 .handler: handle_retain_attribute, NULL },
395 { .name: "externally_visible", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
396 .handler: handle_externally_visible_attribute, NULL },
397 { .name: "no_reorder", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
398 .handler: handle_no_reorder_attribute, NULL },
399 /* The same comments as for noreturn attributes apply to const ones. */
400 { .name: "const", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
401 .handler: handle_const_attribute,
402 .exclude: attr_const_pure_exclusions },
403 { .name: "scalar_storage_order", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
404 .handler: handle_scalar_storage_order_attribute, NULL },
405 { .name: "transparent_union", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
406 .handler: handle_transparent_union_attribute, NULL },
407 { .name: "constructor", .min_length: 0, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
408 .handler: handle_constructor_attribute, NULL },
409 { .name: "destructor", .min_length: 0, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
410 .handler: handle_destructor_attribute, NULL },
411 { .name: "mode", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
412 .handler: handle_mode_attribute, NULL },
413 { .name: "section", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
414 .handler: handle_section_attribute, .exclude: attr_section_exclusions },
415 { .name: "aligned", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
416 .handler: handle_aligned_attribute,
417 .exclude: attr_aligned_exclusions },
418 { .name: "warn_if_not_aligned", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
419 .handler: handle_warn_if_not_aligned_attribute, NULL },
420 { .name: "strict_flex_array", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
421 .handler: handle_strict_flex_array_attribute, NULL },
422 { .name: "counted_by", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
423 .handler: handle_counted_by_attribute, NULL },
424 { .name: "weak", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
425 .handler: handle_weak_attribute, NULL },
426 { .name: "noplt", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
427 .handler: handle_noplt_attribute, NULL },
428 { .name: "ifunc", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
429 .handler: handle_ifunc_attribute, NULL },
430 { .name: "alias", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
431 .handler: handle_alias_attribute, NULL },
432 { .name: "weakref", .min_length: 0, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
433 .handler: handle_weakref_attribute, NULL },
434 { .name: "no_instrument_function", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
435 .handler: handle_no_instrument_function_attribute,
436 NULL },
437 { .name: "no_profile_instrument_function", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
438 .handler: handle_no_profile_instrument_function_attribute,
439 NULL },
440 { .name: "malloc", .min_length: 0, .max_length: 2, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
441 .handler: handle_malloc_attribute, .exclude: attr_alloc_exclusions },
442 { .name: "returns_twice", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
443 .handler: handle_returns_twice_attribute,
444 .exclude: attr_returns_twice_exclusions },
445 { .name: "no_stack_limit", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
446 .handler: handle_no_limit_stack_attribute, NULL },
447 { .name: "pure", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
448 .handler: handle_pure_attribute,
449 .exclude: attr_const_pure_exclusions },
450 { .name: "reproducible", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
451 .handler: handle_reproducible_attribute, NULL },
452 { .name: "unsequenced", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
453 .handler: handle_unsequenced_attribute, NULL },
454 { .name: "reproducible noptr", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
455 .handler: handle_reproducible_attribute, NULL },
456 { .name: "unsequenced noptr", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
457 .handler: handle_unsequenced_attribute, NULL },
458 { .name: "transaction_callable", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
459 .handler: handle_tm_attribute, NULL },
460 { .name: "transaction_unsafe", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
461 .handler: handle_tm_attribute, NULL },
462 { .name: "transaction_safe", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
463 .handler: handle_tm_attribute, NULL },
464 { .name: "transaction_safe_dynamic", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
465 .handler: handle_tm_attribute, NULL },
466 { .name: "transaction_may_cancel_outer", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
467 .handler: handle_tm_attribute, NULL },
468 /* ??? These two attributes didn't make the transition from the
469 Intel language document to the multi-vendor language document. */
470 { .name: "transaction_pure", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
471 .handler: handle_tm_attribute, NULL },
472 { .name: "transaction_wrap", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
473 .handler: handle_tm_wrap_attribute, NULL },
474 /* For internal use (marking of builtins) only. The name contains space
475 to prevent its usage in source code. */
476 { .name: "no vops", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
477 .handler: handle_novops_attribute, NULL },
478 { .name: "deprecated", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
479 .handler: handle_deprecated_attribute, NULL },
480 { .name: "unavailable", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
481 .handler: handle_unavailable_attribute, NULL },
482 { .name: "vector_size", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
483 .handler: handle_vector_size_attribute, NULL },
484 { .name: "vector_mask", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: true,
485 .handler: handle_vector_mask_attribute, NULL },
486 { .name: "visibility", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
487 .handler: handle_visibility_attribute, NULL },
488 { .name: "tls_model", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
489 .handler: handle_tls_model_attribute, NULL },
490 { .name: "nonnull", .min_length: 0, .max_length: -1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
491 .handler: handle_nonnull_attribute, NULL },
492 { .name: "nonnull_if_nonzero", .min_length: 2, .max_length: 2, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
493 .handler: handle_nonnull_if_nonzero_attribute, NULL },
494 { .name: "nonstring", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
495 .handler: handle_nonstring_attribute, NULL },
496 { .name: "nothrow", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
497 .handler: handle_nothrow_attribute, NULL },
498 { .name: "expected_throw", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
499 .handler: handle_expected_throw_attribute, NULL },
500 { .name: "may_alias", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false, NULL, NULL },
501 { .name: "cleanup", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
502 .handler: handle_cleanup_attribute, NULL },
503 { .name: "warn_unused_result", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
504 .handler: handle_warn_unused_result_attribute,
505 .exclude: attr_warn_unused_result_exclusions },
506 { .name: "sentinel", .min_length: 0, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
507 .handler: handle_sentinel_attribute, NULL },
508 /* For internal use (marking of builtins) only. The name contains space
509 to prevent its usage in source code. */
510 { .name: "type generic", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
511 .handler: handle_type_generic_attribute, NULL },
512 { .name: "alloc_size", .min_length: 1, .max_length: 2, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
513 .handler: handle_alloc_size_attribute,
514 .exclude: attr_alloc_exclusions },
515 { .name: "cold", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
516 .handler: handle_cold_attribute,
517 .exclude: attr_cold_hot_exclusions },
518 { .name: "hot", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
519 .handler: handle_hot_attribute,
520 .exclude: attr_cold_hot_exclusions },
521 { .name: "no_address_safety_analysis",
522 .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
523 .handler: handle_no_address_safety_analysis_attribute,
524 NULL },
525 { .name: "no_sanitize", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
526 .handler: handle_no_sanitize_attribute, NULL },
527 { .name: "no_sanitize_address", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
528 .handler: handle_no_sanitize_address_attribute, NULL },
529 { .name: "no_sanitize_thread", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
530 .handler: handle_no_sanitize_thread_attribute, NULL },
531 { .name: "no_sanitize_undefined", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
532 .handler: handle_no_sanitize_undefined_attribute, NULL },
533 { .name: "no_sanitize_coverage", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
534 .handler: handle_no_sanitize_coverage_attribute, NULL },
535 { .name: "asan odr indicator", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
536 .handler: handle_asan_odr_indicator_attribute, NULL },
537 { .name: "warning", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
538 .handler: handle_error_attribute, NULL },
539 { .name: "error", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
540 .handler: handle_error_attribute, NULL },
541 { .name: "target", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
542 .handler: handle_target_attribute,
543 .exclude: attr_target_exclusions },
544 { .name: "target_version", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
545 .handler: handle_target_version_attribute,
546 .exclude: attr_target_version_exclusions },
547 { .name: "target_clones", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
548 .handler: handle_target_clones_attribute,
549 .exclude: attr_target_clones_exclusions },
550 { .name: "optimize", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
551 .handler: handle_optimize_attribute, NULL },
552 /* For internal use only. The leading '*' both prevents its usage in
553 source code and signals that it may be overridden by machine tables. */
554 { .name: "*tm regparm", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
555 .handler: ignore_attribute, NULL },
556 { .name: "no_split_stack", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
557 .handler: handle_no_split_stack_attribute, NULL },
558 { .name: "zero_call_used_regs", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
559 .handler: handle_zero_call_used_regs_attribute, NULL },
560 /* For internal use only (marking of function arguments).
561 The name contains a space to prevent its usage in source code. */
562 { .name: "arg spec", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
563 .handler: handle_argspec_attribute, NULL },
564 /* For internal use (marking of builtins and runtime functions) only.
565 The name contains space to prevent its usage in source code. */
566 { .name: "fn spec", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
567 .handler: handle_fnspec_attribute, NULL },
568 { .name: "warn_unused", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
569 .handler: handle_warn_unused_attribute, NULL },
570 { .name: "returns_nonnull", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
571 .handler: handle_returns_nonnull_attribute, NULL },
572 { .name: "omp declare simd", .min_length: 0, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
573 .handler: handle_omp_declare_simd_attribute, NULL },
574 { .name: "omp declare variant base", .min_length: 0, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
575 .handler: handle_omp_declare_variant_attribute, NULL },
576 { .name: "omp declare variant variant", .min_length: 0, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
577 .handler: handle_omp_declare_variant_attribute, NULL },
578 { .name: "omp declare variant variant args", .min_length: 0, .max_length: -1, .decl_required: true, .type_required: false,
579 .function_type_required: false, .affects_type_identity: false,
580 .handler: handle_omp_declare_variant_attribute, NULL },
581 { .name: "simd", .min_length: 0, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
582 .handler: handle_simd_attribute, NULL },
583 { .name: "omp declare target", .min_length: 0, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
584 .handler: handle_omp_declare_target_attribute, NULL },
585 { .name: "omp declare target link", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
586 .handler: handle_omp_declare_target_attribute, NULL },
587 { .name: "omp declare target implicit", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
588 .handler: handle_omp_declare_target_attribute, NULL },
589 { .name: "omp declare target indirect", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
590 .handler: handle_omp_declare_target_attribute, NULL },
591 { .name: "omp declare target host", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
592 .handler: handle_omp_declare_target_attribute, NULL },
593 { .name: "omp declare target nohost", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
594 .handler: handle_omp_declare_target_attribute, NULL },
595 { .name: "non overlapping", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
596 .handler: handle_non_overlapping_attribute, NULL },
597 { .name: "alloc_align", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
598 .handler: handle_alloc_align_attribute,
599 .exclude: attr_alloc_exclusions },
600 { .name: "assume_aligned", .min_length: 1, .max_length: 2, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
601 .handler: handle_assume_aligned_attribute, NULL },
602 { .name: "designated_init", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
603 .handler: handle_designated_init_attribute, NULL },
604 { .name: "fallthrough", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
605 .handler: handle_fallthrough_attribute, NULL },
606 { .name: "assume", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
607 .handler: handle_assume_attribute, NULL },
608 { .name: "patchable_function_entry", .min_length: 1, .max_length: 2, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
609 .handler: handle_patchable_function_entry_attribute,
610 NULL },
611 { .name: "nocf_check", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: true,
612 .handler: handle_nocf_check_attribute, NULL },
613 { .name: "symver", .min_length: 1, .max_length: -1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
614 .handler: handle_symver_attribute, NULL},
615 { .name: "copy", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: false, .function_type_required: false, .affects_type_identity: false,
616 .handler: handle_copy_attribute, NULL },
617 { .name: "noinit", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
618 .handler: handle_special_var_sec_attribute, .exclude: attr_section_exclusions },
619 { .name: "persistent", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
620 .handler: handle_special_var_sec_attribute, .exclude: attr_section_exclusions },
621 { .name: "access", .min_length: 1, .max_length: 3, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
622 .handler: handle_access_attribute, NULL },
623 /* Attributes used by Objective-C. */
624 { .name: "NSObject", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
625 .handler: handle_nsobject_attribute, NULL },
626 { .name: "objc_root_class", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
627 .handler: handle_objc_root_class_attribute, NULL },
628 { .name: "objc_nullability", .min_length: 1, .max_length: 1, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
629 .handler: handle_objc_nullability_attribute, NULL },
630 { .name: "*dealloc", .min_length: 1, .max_length: 2, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
631 .handler: handle_dealloc_attribute, NULL },
632 { .name: "tainted_args", .min_length: 0, .max_length: 0, .decl_required: true, .type_required: false, .function_type_required: false, .affects_type_identity: false,
633 .handler: handle_tainted_args_attribute, NULL },
634 { .name: "fd_arg", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
635 .handler: handle_fd_arg_attribute, NULL},
636 { .name: "fd_arg_read", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
637 .handler: handle_fd_arg_attribute, NULL},
638 { .name: "fd_arg_write", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
639 .handler: handle_fd_arg_attribute, NULL},
640 { .name: "flag_enum", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
641 .handler: handle_flag_enum_attribute, NULL },
642 { .name: "null_terminated_string_arg", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
643 .handler: handle_null_terminated_string_arg_attribute, NULL}
644};
645
646const struct scoped_attribute_specs c_common_gnu_attribute_table =
647{
648 .ns: "gnu", .attributes: { c_common_gnu_attributes }
649};
650
651/* Attributes also recognized in the clang:: namespace. */
652const struct attribute_spec c_common_clang_attributes[] = {
653 { .name: "flag_enum", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: true, .function_type_required: false, .affects_type_identity: false,
654 .handler: handle_flag_enum_attribute, NULL },
655 { .name: "musttail", .min_length: 0, .max_length: 0, .decl_required: false, .type_required: false, .function_type_required: false,
656 .affects_type_identity: false, .handler: handle_musttail_attribute, NULL }
657};
658
659const struct scoped_attribute_specs c_common_clang_attribute_table =
660{
661 .ns: "clang", .attributes: { c_common_clang_attributes }
662};
663
664/* Give the specifications for the format attributes, used by C and all
665 descendants.
666
667 Current list of processed format attributes: format, format_arg. */
668const struct attribute_spec c_common_format_attributes[] =
669{
670 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
671 affects_type_identity, handler, exclude } */
672 { .name: "format", .min_length: 3, .max_length: 3, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
673 .handler: handle_format_attribute, NULL },
674 { .name: "format_arg", .min_length: 1, .max_length: 1, .decl_required: false, .type_required: true, .function_type_required: true, .affects_type_identity: false,
675 .handler: handle_format_arg_attribute, NULL }
676};
677
678const struct scoped_attribute_specs c_common_format_attribute_table =
679{
680 .ns: "gnu", .attributes: { c_common_format_attributes }
681};
682
683/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
684 identifier as an argument, so the front end shouldn't look it up. */
685
686bool
687attribute_takes_identifier_p (const_tree attr_id)
688{
689 const struct attribute_spec *spec = lookup_attribute_spec (attr_id);
690 if (spec == NULL)
691 /* Unknown attribute that we'll end up ignoring, return true so we
692 don't complain about an identifier argument. */
693 return true;
694 else if (!strcmp (s1: "mode", s2: spec->name)
695 || !strcmp (s1: "format", s2: spec->name)
696 || !strcmp (s1: "cleanup", s2: spec->name)
697 || !strcmp (s1: "access", s2: spec->name)
698 || !strcmp (s1: "counted_by", s2: spec->name))
699 return true;
700 else
701 return targetm.attribute_takes_identifier_p (attr_id);
702}
703
704/* Set a musttail attribute MUSTTAIL_P on return expression RETVAL
705 at LOC. */
706
707void
708set_musttail_on_return (tree retval, location_t loc, bool musttail_p)
709{
710 if (retval && musttail_p)
711 {
712 tree t = retval;
713 if (TREE_CODE (t) == TARGET_EXPR)
714 t = TARGET_EXPR_INITIAL (t);
715 if (TREE_CODE (t) != CALL_EXPR)
716 error_at (loc, "cannot tail-call: return value must be a call");
717 else
718 CALL_EXPR_MUST_TAIL_CALL (t) = 1;
719 }
720 else if (musttail_p && !retval)
721 error_at (loc, "cannot tail-call: return value must be a call");
722}
723
724/* Verify that argument value POS at position ARGNO to attribute NAME
725 applied to function FN (which is either a function declaration or function
726 type) refers to a function parameter at position POS and the expected type
727 CODE. Treat CODE == INTEGER_TYPE as matching all C integral types except
728 bool. If successful, return POS after default conversions (and possibly
729 adjusted by ADJUST_POS). Otherwise, issue appropriate warnings and return
730 null. A non-zero 1-based ARGNO should be passed in by callers only for
731 attributes with more than one argument.
732
733 N.B. This function modifies POS. */
734
735tree
736positional_argument (const_tree fn, const_tree atname, tree &pos,
737 tree_code code, int argno /* = 0 */,
738 int flags /* = posargflags () */)
739{
740 auto_urlify_attributes sentinel;
741
742 const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn;
743 const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn);
744 if (pos && TREE_CODE (pos) != IDENTIFIER_NODE
745 && TREE_CODE (pos) != FUNCTION_DECL)
746 pos = default_conversion (pos);
747
748 tree postype = TREE_TYPE (pos);
749 if (pos == error_mark_node || !postype)
750 {
751 /* Only mention the positional argument number when it's non-zero. */
752 if (argno < 1)
753 warning (OPT_Wattributes,
754 "%qE attribute argument is invalid", atname);
755 else
756 warning (OPT_Wattributes,
757 "%qE attribute argument %i is invalid", atname, argno);
758
759 return NULL_TREE;
760 }
761
762 if (!INTEGRAL_TYPE_P (postype))
763 {
764 /* Handle this case specially to avoid mentioning the value
765 of pointer constants in diagnostics. Only mention
766 the positional argument number when it's non-zero. */
767 if (argno < 1)
768 warning (OPT_Wattributes,
769 "%qE attribute argument has type %qT",
770 atname, postype);
771 else
772 warning (OPT_Wattributes,
773 "%qE attribute argument %i has type %qT",
774 atname, argno, postype);
775
776 return NULL_TREE;
777 }
778
779 if (TREE_CODE (pos) != INTEGER_CST)
780 {
781 /* Only mention the argument number when it's non-zero. */
782 if (argno < 1)
783 warning (OPT_Wattributes,
784 "%qE attribute argument value %qE is not an integer "
785 "constant",
786 atname, pos);
787 else
788 warning (OPT_Wattributes,
789 "%qE attribute argument %i value %qE is not an integer "
790 "constant",
791 atname, argno, pos);
792
793 return NULL_TREE;
794 }
795
796 /* Argument positions are 1-based. */
797 if (integer_zerop (pos))
798 {
799 if (flags & POSARG_ZERO)
800 /* Zero is explicitly allowed. */
801 return pos;
802
803 if (argno < 1)
804 warning (OPT_Wattributes,
805 "%qE attribute argument value %qE does not refer to "
806 "a function parameter",
807 atname, pos);
808 else
809 warning (OPT_Wattributes,
810 "%qE attribute argument %i value %qE does not refer to "
811 "a function parameter",
812 atname, argno, pos);
813
814 return NULL_TREE;
815 }
816
817 if (!prototype_p (fntype))
818 return pos;
819
820 /* ADJUST_POS is non-zero in C++ when the function type has invisible
821 parameters generated by the compiler, such as the in-charge or VTT
822 parameters. */
823 const int adjust_pos = maybe_adjust_arg_pos_for_attribute (fndecl);
824
825 /* Verify that the argument position does not exceed the number
826 of formal arguments to the function. When POSARG_ELLIPSIS
827 is set, ARGNO may be beyond the last argument of a vararg
828 function. */
829 unsigned nargs = type_num_arguments (fntype);
830 if (!nargs
831 || !tree_fits_uhwi_p (pos)
832 || ((flags & POSARG_ELLIPSIS) == 0
833 && !IN_RANGE (tree_to_uhwi (pos) + adjust_pos, 1, nargs)))
834 {
835
836 if (argno < 1)
837 warning (OPT_Wattributes,
838 "%qE attribute argument value %qE exceeds the number "
839 "of function parameters %u",
840 atname, pos, nargs);
841 else
842 warning (OPT_Wattributes,
843 "%qE attribute argument %i value %qE exceeds the number "
844 "of function parameters %u",
845 atname, argno, pos, nargs);
846 return NULL_TREE;
847 }
848
849 /* Verify that the type of the referenced formal argument matches
850 the expected type. Invisible parameters may have been added by
851 the compiler, so adjust the position accordingly. */
852 unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos) + adjust_pos;
853
854 /* Zero was handled above. */
855 gcc_assert (ipos != 0);
856
857 if (tree argtype = type_argument_type (fntype, ipos))
858 {
859 if (argtype == error_mark_node)
860 return NULL_TREE;
861
862 if (flags & POSARG_ELLIPSIS)
863 {
864 if (argno < 1)
865 error ("%qE attribute argument value %qE does not refer to "
866 "a variable argument list",
867 atname, pos);
868 else
869 error ("%qE attribute argument %i value %qE does not refer to "
870 "a variable argument list",
871 atname, argno, pos);
872 return NULL_TREE;
873 }
874
875 /* Where the expected code is STRING_CST accept any pointer
876 expected by attribute format (this includes possibly qualified
877 char pointers and, for targets like Darwin, also pointers to
878 struct CFString). */
879 bool type_match;
880 if (code == STRING_CST)
881 type_match = valid_format_string_type_p (argtype);
882 else if (code == INTEGER_TYPE)
883 /* For integers, accept enums, wide characters and other types
884 that match INTEGRAL_TYPE_P except for bool. */
885 type_match = (INTEGRAL_TYPE_P (argtype)
886 && TREE_CODE (argtype) != BOOLEAN_TYPE);
887 else
888 type_match = TREE_CODE (argtype) == code;
889
890 if (!type_match)
891 {
892 if (code == STRING_CST)
893 {
894 /* Reject invalid format strings with an error. */
895 if (argno < 1)
896 error ("%qE attribute argument value %qE refers to "
897 "parameter type %qT",
898 atname, pos, argtype);
899 else
900 error ("%qE attribute argument %i value %qE refers to "
901 "parameter type %qT",
902 atname, argno, pos, argtype);
903
904 return NULL_TREE;
905 }
906
907 if (argno < 1)
908 warning (OPT_Wattributes,
909 "%qE attribute argument value %qE refers to "
910 "parameter type %qT",
911 atname, pos, argtype);
912 else
913 warning (OPT_Wattributes,
914 "%qE attribute argument %i value %qE refers to "
915 "parameter type %qT",
916 atname, argno, pos, argtype);
917 return NULL_TREE;
918 }
919 }
920 else if (!(flags & POSARG_ELLIPSIS))
921 {
922 if (argno < 1)
923 warning (OPT_Wattributes,
924 "%qE attribute argument value %qE refers to "
925 "a variadic function parameter of unknown type",
926 atname, pos);
927 else
928 warning (OPT_Wattributes,
929 "%qE attribute argument %i value %qE refers to "
930 "a variadic function parameter of unknown type",
931 atname, argno, pos);
932 return NULL_TREE;
933 }
934
935 return build_int_cst (TREE_TYPE (pos), ipos);
936}
937
938/* Return the first of DECL or TYPE attributes installed in NODE if it's
939 a DECL, or TYPE attributes if it's a TYPE, or null otherwise. */
940
941static tree
942decl_or_type_attrs (tree node)
943{
944 if (DECL_P (node))
945 {
946 if (tree attrs = DECL_ATTRIBUTES (node))
947 return attrs;
948
949 tree type = TREE_TYPE (node);
950 if (type == error_mark_node)
951 return NULL_TREE;
952 return TYPE_ATTRIBUTES (type);
953 }
954
955 if (TYPE_P (node))
956 return TYPE_ATTRIBUTES (node);
957
958 return NULL_TREE;
959}
960
961/* Given a pair of NODEs for arbitrary DECLs or TYPEs, validate one or
962 two integral or string attribute arguments NEWARGS to be applied to
963 NODE[0] for the absence of conflicts with the same attribute arguments
964 already applied to NODE[1]. Issue a warning for conflicts and return
965 false. Otherwise, when no conflicts are found, return true. */
966
967static bool
968validate_attr_args (tree node[2], tree name, tree newargs[2])
969{
970 /* First validate the arguments against those already applied to
971 the same declaration (or type). */
972 tree self[2] = { node[0], node[0] };
973 if (node[0] != node[1] && !validate_attr_args (node: self, name, newargs))
974 return false;
975
976 if (!node[1])
977 return true;
978
979 /* Extract the same attribute from the previous declaration or type. */
980 tree prevattr = decl_or_type_attrs (node: node[1]);
981 const char* const namestr = IDENTIFIER_POINTER (name);
982 prevattr = lookup_attribute (attr_name: namestr, list: prevattr);
983 if (!prevattr)
984 return true;
985
986 /* Extract one or both attribute arguments. */
987 tree prevargs[2];
988 prevargs[0] = TREE_VALUE (TREE_VALUE (prevattr));
989 prevargs[1] = TREE_CHAIN (TREE_VALUE (prevattr));
990 if (prevargs[1])
991 prevargs[1] = TREE_VALUE (prevargs[1]);
992
993 /* Both arguments must be equal or, for the second pair, neither must
994 be provided to succeed. */
995 bool arg1eq, arg2eq;
996 if (TREE_CODE (newargs[0]) == INTEGER_CST)
997 {
998 arg1eq = tree_int_cst_equal (newargs[0], prevargs[0]);
999 if (newargs[1] && prevargs[1])
1000 arg2eq = tree_int_cst_equal (newargs[1], prevargs[1]);
1001 else
1002 arg2eq = newargs[1] == prevargs[1];
1003 }
1004 else if (TREE_CODE (newargs[0]) == STRING_CST)
1005 {
1006 const char *s0 = TREE_STRING_POINTER (newargs[0]);
1007 const char *s1 = TREE_STRING_POINTER (prevargs[0]);
1008 arg1eq = strcmp (s1: s0, s2: s1) == 0;
1009 if (newargs[1] && prevargs[1])
1010 {
1011 s0 = TREE_STRING_POINTER (newargs[1]);
1012 s1 = TREE_STRING_POINTER (prevargs[1]);
1013 arg2eq = strcmp (s1: s0, s2: s1) == 0;
1014 }
1015 else
1016 arg2eq = newargs[1] == prevargs[1];
1017 }
1018 else
1019 gcc_unreachable ();
1020
1021 if (arg1eq && arg2eq)
1022 return true;
1023
1024 /* If the two locations are different print a note pointing to
1025 the previous one. */
1026 const location_t curloc = input_location;
1027 const location_t prevloc =
1028 DECL_P (node[1]) ? DECL_SOURCE_LOCATION (node[1]) : curloc;
1029
1030 /* Format the attribute specification for convenience. */
1031 char newspec[80], prevspec[80];
1032 if (newargs[1])
1033 snprintf (s: newspec, maxlen: sizeof newspec, format: "%s (%s, %s)", namestr,
1034 print_generic_expr_to_str (newargs[0]),
1035 print_generic_expr_to_str (newargs[1]));
1036 else
1037 snprintf (s: newspec, maxlen: sizeof newspec, format: "%s (%s)", namestr,
1038 print_generic_expr_to_str (newargs[0]));
1039
1040 if (prevargs[1])
1041 snprintf (s: prevspec, maxlen: sizeof prevspec, format: "%s (%s, %s)", namestr,
1042 print_generic_expr_to_str (prevargs[0]),
1043 print_generic_expr_to_str (prevargs[1]));
1044 else
1045 snprintf (s: prevspec, maxlen: sizeof prevspec, format: "%s (%s)", namestr,
1046 print_generic_expr_to_str (prevargs[0]));
1047
1048 if (warning_at (curloc, OPT_Wattributes,
1049 "ignoring attribute %qs because it conflicts "
1050 "with previous %qs",
1051 newspec, prevspec)
1052 && curloc != prevloc)
1053 inform (prevloc, "previous declaration here");
1054
1055 return false;
1056}
1057
1058/* Convenience wrapper for validate_attr_args to validate a single
1059 attribute argument. Used by handlers for attributes that take
1060 just a single argument. */
1061
1062static bool
1063validate_attr_arg (tree node[2], tree name, tree newarg)
1064{
1065 tree argarray[2] = { newarg, NULL_TREE };
1066 return validate_attr_args (node, name, newargs: argarray);
1067}
1068
1069/* Attribute handlers common to C front ends. */
1070
1071/* Handle a "signed_bool_precision" attribute; arguments as in
1072 struct attribute_spec.handler. */
1073
1074static tree
1075handle_signed_bool_precision_attribute (tree *node, tree name, tree args,
1076 int, bool *no_add_attrs)
1077{
1078 *no_add_attrs = true;
1079 if (!flag_gimple)
1080 {
1081 warning (OPT_Wattributes, "%qE attribute ignored", name);
1082 return NULL_TREE;
1083 }
1084
1085 if (!TYPE_P (*node) || TREE_CODE (*node) != BOOLEAN_TYPE)
1086 {
1087 warning (OPT_Wattributes, "%qE attribute only supported on "
1088 "boolean types", name);
1089 return NULL_TREE;
1090 }
1091
1092 unsigned HOST_WIDE_INT prec = HOST_WIDE_INT_M1U;
1093 if (tree_fits_uhwi_p (TREE_VALUE (args)))
1094 prec = tree_to_uhwi (TREE_VALUE (args));
1095 if (prec > MAX_FIXED_MODE_SIZE)
1096 {
1097 warning (OPT_Wattributes, "%qE attribute with unsupported boolean "
1098 "precision", name);
1099 return NULL_TREE;
1100 }
1101
1102 tree new_type = build_nonstandard_boolean_type (prec);
1103 *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
1104
1105 return NULL_TREE;
1106}
1107
1108/* Handle a "hardbool" attribute; arguments as in struct
1109 attribute_spec.handler. */
1110
1111static tree
1112handle_hardbool_attribute (tree *node, tree name, tree args,
1113 int /* flags */, bool *no_add_attrs)
1114{
1115 if (c_language != clk_c)
1116 {
1117 error ("%qE attribute only supported in C", name);
1118 *no_add_attrs = TRUE;
1119 return NULL_TREE;
1120 }
1121
1122 if (!TYPE_P (*node) || TREE_CODE (*node) != INTEGER_TYPE)
1123 {
1124 error ("%qE attribute only supported on "
1125 "integral types", name);
1126 *no_add_attrs = TRUE;
1127 return NULL_TREE;
1128 }
1129
1130 tree orig = *node;
1131 *node = build_duplicate_type (orig);
1132
1133 TREE_SET_CODE (*node, ENUMERAL_TYPE);
1134 ENUM_UNDERLYING_TYPE (*node) = orig;
1135 TYPE_CANONICAL (*node) = TYPE_CANONICAL (orig);
1136
1137 tree false_value;
1138 if (args)
1139 false_value = fold_convert (*node, TREE_VALUE (args));
1140 else
1141 false_value = fold_convert (*node, integer_zero_node);
1142
1143 if (TREE_OVERFLOW_P (false_value))
1144 {
1145 warning (OPT_Wattributes,
1146 "overflows in conversion from %qT to %qT "
1147 "changes value from %qE to %qE",
1148 TREE_TYPE (TREE_VALUE (args)), *node,
1149 TREE_VALUE (args), false_value);
1150 TREE_OVERFLOW (false_value) = false;
1151 }
1152
1153 tree true_value;
1154 if (args && TREE_CHAIN (args))
1155 true_value = fold_convert (*node, TREE_VALUE (TREE_CHAIN (args)));
1156 else
1157 true_value = fold_build1 (BIT_NOT_EXPR, *node, false_value);
1158
1159 if (TREE_OVERFLOW_P (true_value))
1160 {
1161 warning (OPT_Wattributes,
1162 "overflows in conversion from %qT to %qT "
1163 "changes value from %qE to %qE",
1164 TREE_TYPE (TREE_VALUE (TREE_CHAIN (args))), *node,
1165 TREE_VALUE (TREE_CHAIN (args)), true_value);
1166 TREE_OVERFLOW (true_value) = false;
1167 }
1168
1169 if (tree_int_cst_compare (t1: false_value, t2: true_value) == 0)
1170 {
1171 error ("%qE attribute requires different values for"
1172 " %<false%> and %<true%> for type %qT",
1173 name, *node);
1174 *no_add_attrs = TRUE;
1175 return NULL_TREE;
1176 }
1177
1178 tree values = build_tree_list (get_identifier ("false"),
1179 false_value);
1180 TREE_CHAIN (values) = build_tree_list (get_identifier ("true"),
1181 true_value);
1182
1183 /* Do *not* set TYPE_MIN_VALUE, TYPE_MAX_VALUE, nor TYPE_PRECISION according
1184 to the false and true values. That might cause the constants to be the
1185 only acceptable values, which would drop the very hardening checks this
1186 attribute is supposed to add. */
1187
1188 TYPE_ATTRIBUTES (*node) = tree_cons (name, args,
1189 TYPE_ATTRIBUTES (*node));
1190 *no_add_attrs = TRUE;
1191
1192 gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node));
1193 TYPE_VALUES (*node) = values;
1194 TYPE_NAME (*node) = orig;
1195
1196 return NULL_TREE;
1197}
1198
1199/* Handle a "packed" attribute; arguments as in
1200 struct attribute_spec.handler. */
1201
1202static tree
1203handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1204 int flags, bool *no_add_attrs)
1205{
1206 if (TYPE_P (*node))
1207 {
1208 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1209 {
1210 warning (OPT_Wattributes,
1211 "%qE attribute ignored for type %qT", name, *node);
1212 *no_add_attrs = true;
1213 }
1214 else
1215 TYPE_PACKED (*node) = 1;
1216 }
1217 else if (TREE_CODE (*node) == FIELD_DECL)
1218 {
1219 if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
1220 /* Still pack bitfields. */
1221 && ! DECL_C_BIT_FIELD (*node))
1222 warning (OPT_Wattributes,
1223 "%qE attribute ignored for field of type %qT",
1224 name, TREE_TYPE (*node));
1225 else
1226 DECL_PACKED (*node) = 1;
1227 }
1228 /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
1229 used for DECL_REGISTER. It wouldn't mean anything anyway.
1230 We can't set DECL_PACKED on the type of a TYPE_DECL, because
1231 that changes what the typedef is typing. */
1232 else
1233 {
1234 warning (OPT_Wattributes, "%qE attribute ignored", name);
1235 *no_add_attrs = true;
1236 }
1237
1238 return NULL_TREE;
1239}
1240
1241/* Handle a "nocommon" attribute; arguments as in
1242 struct attribute_spec.handler. */
1243
1244static tree
1245handle_nocommon_attribute (tree *node, tree name,
1246 tree ARG_UNUSED (args),
1247 int ARG_UNUSED (flags), bool *no_add_attrs)
1248{
1249 if (VAR_P (*node))
1250 DECL_COMMON (*node) = 0;
1251 else
1252 {
1253 warning (OPT_Wattributes, "%qE attribute ignored", name);
1254 *no_add_attrs = true;
1255 }
1256
1257 return NULL_TREE;
1258}
1259
1260/* Handle a "common" attribute; arguments as in
1261 struct attribute_spec.handler. */
1262
1263static tree
1264handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1265 int ARG_UNUSED (flags), bool *no_add_attrs)
1266{
1267 if (VAR_P (*node))
1268 DECL_COMMON (*node) = 1;
1269 else
1270 {
1271 warning (OPT_Wattributes, "%qE attribute ignored", name);
1272 *no_add_attrs = true;
1273 }
1274
1275 return NULL_TREE;
1276}
1277
1278/* Handle a "musttail" attribute; arguments as in
1279 struct attribute_spec.handler. */
1280
1281tree
1282handle_musttail_attribute (tree ARG_UNUSED (*node), tree name, tree ARG_UNUSED (args),
1283 int ARG_UNUSED (flags), bool *no_add_attrs)
1284{
1285 /* Currently only a statement attribute, handled directly in parser. */
1286 warning (OPT_Wattributes, "%qE attribute ignored", name);
1287 *no_add_attrs = true;
1288 return NULL_TREE;
1289}
1290
1291/* Handle a "noreturn" attribute; arguments as in
1292 struct attribute_spec.handler. */
1293
1294tree
1295handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1296 int ARG_UNUSED (flags), bool *no_add_attrs)
1297{
1298 tree type = TREE_TYPE (*node);
1299
1300 /* See FIXME comment in c_common_attribute_table. */
1301 if (TREE_CODE (*node) == FUNCTION_DECL
1302 || objc_method_decl (TREE_CODE (*node)))
1303 TREE_THIS_VOLATILE (*node) = 1;
1304 else if (TREE_CODE (type) == POINTER_TYPE
1305 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
1306 TREE_TYPE (*node)
1307 = (build_qualified_type
1308 (build_pointer_type
1309 (build_type_variant (TREE_TYPE (type),
1310 TYPE_READONLY (TREE_TYPE (type)), 1)),
1311 TYPE_QUALS (type)));
1312 else
1313 {
1314 warning (OPT_Wattributes, "%qE attribute ignored", name);
1315 *no_add_attrs = true;
1316 }
1317
1318 return NULL_TREE;
1319}
1320
1321/* Handle a "hot" and attribute; arguments as in
1322 struct attribute_spec.handler. */
1323
1324static tree
1325handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1326 int ARG_UNUSED (flags), bool *no_add_attrs)
1327{
1328 if (TREE_CODE (*node) == FUNCTION_DECL
1329 || TREE_CODE (*node) == LABEL_DECL)
1330 {
1331 /* Attribute hot processing is done later with lookup_attribute. */
1332 }
1333 else if ((TREE_CODE (*node) == RECORD_TYPE
1334 || TREE_CODE (*node) == UNION_TYPE)
1335 && c_dialect_cxx ()
1336 && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1337 {
1338 /* Check conflict here as decl_attributes will otherwise only catch
1339 it late at the function when the attribute is used on a class. */
1340 tree cold_attr = lookup_attribute (attr_name: "cold", TYPE_ATTRIBUTES (*node));
1341 if (cold_attr)
1342 {
1343 warning (OPT_Wattributes, "ignoring attribute %qE because it "
1344 "conflicts with attribute %qs", name, "cold");
1345 *no_add_attrs = true;
1346 }
1347 }
1348 else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
1349 | (int) ATTR_FLAG_DECL_NEXT))
1350 {
1351 /* Avoid applying the attribute to a function return type when
1352 used as: void __attribute ((hot)) foo (void). It will be
1353 passed to the function. */
1354 *no_add_attrs = true;
1355 }
1356 else
1357 {
1358 warning (OPT_Wattributes, "%qE attribute ignored", name);
1359 *no_add_attrs = true;
1360 }
1361
1362 return NULL_TREE;
1363}
1364
1365/* Handle a "cold" and attribute; arguments as in
1366 struct attribute_spec.handler. */
1367
1368static tree
1369handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1370 int ARG_UNUSED (flags), bool *no_add_attrs)
1371{
1372 if (TREE_CODE (*node) == FUNCTION_DECL
1373 || TREE_CODE (*node) == LABEL_DECL)
1374 {
1375 /* Attribute cold processing is done later with lookup_attribute. */
1376 }
1377 else if ((TREE_CODE (*node) == RECORD_TYPE
1378 || TREE_CODE (*node) == UNION_TYPE)
1379 && c_dialect_cxx ()
1380 && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1381 {
1382 /* Check conflict here as decl_attributes will otherwise only catch
1383 it late at the function when the attribute is used on a class. */
1384 tree hot_attr = lookup_attribute (attr_name: "hot", TYPE_ATTRIBUTES (*node));
1385 if (hot_attr)
1386 {
1387 warning (OPT_Wattributes, "ignoring attribute %qE because it "
1388 "conflicts with attribute %qs", name, "hot");
1389 *no_add_attrs = true;
1390 }
1391 }
1392 else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
1393 | (int) ATTR_FLAG_DECL_NEXT))
1394 {
1395 /* Avoid applying the attribute to a function return type when
1396 used as: void __attribute ((cold)) foo (void). It will be
1397 passed to the function. */
1398 *no_add_attrs = true;
1399 }
1400 else
1401 {
1402 warning (OPT_Wattributes, "%qE attribute ignored", name);
1403 *no_add_attrs = true;
1404 }
1405
1406 return NULL_TREE;
1407}
1408
1409/* Add FLAGS for a function NODE to no_sanitize_flags in DECL_ATTRIBUTES. */
1410
1411void
1412add_no_sanitize_value (tree node, unsigned int flags)
1413{
1414 tree attr = lookup_attribute (attr_name: "no_sanitize", DECL_ATTRIBUTES (node));
1415 if (attr)
1416 {
1417 unsigned int old_value = tree_to_uhwi (TREE_VALUE (attr));
1418 flags |= old_value;
1419
1420 if (flags == old_value)
1421 return;
1422
1423 TREE_VALUE (attr) = build_int_cst (unsigned_type_node, flags);
1424 }
1425 else
1426 DECL_ATTRIBUTES (node)
1427 = tree_cons (get_identifier ("no_sanitize"),
1428 build_int_cst (unsigned_type_node, flags),
1429 DECL_ATTRIBUTES (node));
1430}
1431
1432/* Handle a "no_sanitize" attribute; arguments as in
1433 struct attribute_spec.handler. */
1434
1435static tree
1436handle_no_sanitize_attribute (tree *node, tree name, tree args, int,
1437 bool *no_add_attrs)
1438{
1439 unsigned int flags = 0;
1440 *no_add_attrs = true;
1441 if (TREE_CODE (*node) != FUNCTION_DECL)
1442 {
1443 warning (OPT_Wattributes, "%qE attribute ignored", name);
1444 return NULL_TREE;
1445 }
1446
1447 for (; args; args = TREE_CHAIN (args))
1448 {
1449 tree id = TREE_VALUE (args);
1450 if (TREE_CODE (id) != STRING_CST)
1451 {
1452 error ("%qE argument not a string", name);
1453 return NULL_TREE;
1454 }
1455
1456 char *string = ASTRDUP (TREE_STRING_POINTER (id));
1457 flags |= parse_no_sanitize_attribute (value: string);
1458 }
1459
1460 add_no_sanitize_value (node: *node, flags);
1461
1462 return NULL_TREE;
1463}
1464
1465/* Handle a "no_sanitize_address" attribute; arguments as in
1466 struct attribute_spec.handler. */
1467
1468static tree
1469handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
1470 bool *no_add_attrs)
1471{
1472 *no_add_attrs = true;
1473 if (TREE_CODE (*node) != FUNCTION_DECL)
1474 warning (OPT_Wattributes, "%qE attribute ignored", name);
1475 else
1476 add_no_sanitize_value (node: *node, flags: SANITIZE_ADDRESS);
1477
1478 return NULL_TREE;
1479}
1480
1481/* Handle a "no_sanitize_thread" attribute; arguments as in
1482 struct attribute_spec.handler. */
1483
1484static tree
1485handle_no_sanitize_thread_attribute (tree *node, tree name, tree, int,
1486 bool *no_add_attrs)
1487{
1488 *no_add_attrs = true;
1489 if (TREE_CODE (*node) != FUNCTION_DECL)
1490 warning (OPT_Wattributes, "%qE attribute ignored", name);
1491 else
1492 add_no_sanitize_value (node: *node, flags: SANITIZE_THREAD);
1493
1494 return NULL_TREE;
1495}
1496
1497
1498/* Handle a "no_address_safety_analysis" attribute; arguments as in
1499 struct attribute_spec.handler. */
1500
1501static tree
1502handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
1503 bool *no_add_attrs)
1504{
1505 *no_add_attrs = true;
1506 if (TREE_CODE (*node) != FUNCTION_DECL)
1507 warning (OPT_Wattributes, "%qE attribute ignored", name);
1508 else
1509 add_no_sanitize_value (node: *node, flags: SANITIZE_ADDRESS);
1510
1511 return NULL_TREE;
1512}
1513
1514/* Handle a "no_sanitize_undefined" attribute; arguments as in
1515 struct attribute_spec.handler. */
1516
1517static tree
1518handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
1519 bool *no_add_attrs)
1520{
1521 *no_add_attrs = true;
1522 if (TREE_CODE (*node) != FUNCTION_DECL)
1523 warning (OPT_Wattributes, "%qE attribute ignored", name);
1524 else
1525 add_no_sanitize_value (node: *node,
1526 flags: SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
1527
1528 return NULL_TREE;
1529}
1530
1531/* Handle a "no_sanitize_coverage" attribute; arguments as in
1532 struct attribute_spec.handler. */
1533
1534static tree
1535handle_no_sanitize_coverage_attribute (tree *node, tree name, tree, int,
1536 bool *no_add_attrs)
1537{
1538 if (TREE_CODE (*node) != FUNCTION_DECL)
1539 {
1540 warning (OPT_Wattributes, "%qE attribute ignored", name);
1541 *no_add_attrs = true;
1542 }
1543
1544 return NULL_TREE;
1545}
1546
1547/* Handle an "asan odr indicator" attribute; arguments as in
1548 struct attribute_spec.handler. */
1549
1550static tree
1551handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *)
1552{
1553 return NULL_TREE;
1554}
1555
1556/* Handle a "stack_protect" attribute; arguments as in
1557 struct attribute_spec.handler. */
1558
1559static tree
1560handle_stack_protect_attribute (tree *node, tree name, tree, int,
1561 bool *no_add_attrs)
1562{
1563 if (TREE_CODE (*node) != FUNCTION_DECL)
1564 {
1565 warning (OPT_Wattributes, "%qE attribute ignored", name);
1566 *no_add_attrs = true;
1567 }
1568
1569 return NULL_TREE;
1570}
1571
1572/* Handle a "no_stack_protector" attribute; arguments as in
1573 struct attribute_spec.handler. */
1574
1575static tree
1576handle_no_stack_protector_function_attribute (tree *node, tree name, tree,
1577 int, bool *no_add_attrs)
1578{
1579 if (TREE_CODE (*node) != FUNCTION_DECL)
1580 {
1581 warning (OPT_Wattributes, "%qE attribute ignored", name);
1582 *no_add_attrs = true;
1583 }
1584
1585 return NULL_TREE;
1586}
1587
1588/* Handle a "noipa" attribute; arguments as in
1589 struct attribute_spec.handler. */
1590
1591static tree
1592handle_noipa_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1593{
1594 if (TREE_CODE (*node) != FUNCTION_DECL)
1595 {
1596 warning (OPT_Wattributes, "%qE attribute ignored", name);
1597 *no_add_attrs = true;
1598 }
1599
1600 return NULL_TREE;
1601}
1602
1603/* Handle a "strub" attribute; arguments as in
1604 struct attribute_spec.handler. */
1605
1606static tree
1607handle_strub_attribute (tree *node, tree name,
1608 tree args,
1609 int ARG_UNUSED (flags), bool *no_add_attrs)
1610{
1611 bool enable = true;
1612
1613 if (args && FUNCTION_POINTER_TYPE_P (*node))
1614 *node = TREE_TYPE (*node);
1615
1616 if (args && FUNC_OR_METHOD_TYPE_P (*node))
1617 {
1618 switch (strub_validate_fn_attr_parm (TREE_VALUE (args)))
1619 {
1620 case 1:
1621 case 2:
1622 enable = true;
1623 break;
1624
1625 case 0:
1626 warning (OPT_Wattributes,
1627 "%qE attribute ignored because of argument %qE",
1628 name, TREE_VALUE (args));
1629 *no_add_attrs = true;
1630 enable = false;
1631 break;
1632
1633 case -1:
1634 case -2:
1635 enable = false;
1636 break;
1637
1638 default:
1639 gcc_unreachable ();
1640 }
1641
1642 args = TREE_CHAIN (args);
1643 }
1644
1645 if (args)
1646 {
1647 warning (OPT_Wattributes,
1648 "ignoring attribute %qE because of excess arguments"
1649 " starting at %qE",
1650 name, TREE_VALUE (args));
1651 *no_add_attrs = true;
1652 enable = false;
1653 }
1654
1655 /* Warn about unmet expectations that the strub attribute works like a
1656 qualifier. ??? Could/should we extend it to the element/field types
1657 here? */
1658 if (TREE_CODE (*node) == ARRAY_TYPE
1659 || VECTOR_TYPE_P (*node)
1660 || TREE_CODE (*node) == COMPLEX_TYPE)
1661 warning (OPT_Wattributes,
1662 "attribute %qE does not apply to elements"
1663 " of non-scalar type %qT",
1664 name, *node);
1665 else if (RECORD_OR_UNION_TYPE_P (*node))
1666 warning (OPT_Wattributes,
1667 "attribute %qE does not apply to fields"
1668 " of aggregate type %qT",
1669 name, *node);
1670
1671 /* If we see a strub-enabling attribute, and we're at the default setting,
1672 implicitly or explicitly, note that the attribute was seen, so that we can
1673 reduce the compile-time overhead to nearly zero when the strub feature is
1674 not used. */
1675 if (enable && flag_strub < -2)
1676 flag_strub += 2;
1677
1678 return NULL_TREE;
1679}
1680
1681/* Handle a "noinline" attribute; arguments as in
1682 struct attribute_spec.handler. */
1683
1684static tree
1685handle_noinline_attribute (tree *node, tree name,
1686 tree ARG_UNUSED (args),
1687 int ARG_UNUSED (flags), bool *no_add_attrs)
1688{
1689 if (TREE_CODE (*node) == FUNCTION_DECL)
1690 DECL_UNINLINABLE (*node) = 1;
1691 else
1692 {
1693 warning (OPT_Wattributes, "%qE attribute ignored", name);
1694 *no_add_attrs = true;
1695 }
1696
1697 return NULL_TREE;
1698}
1699
1700/* Handle a "noclone" attribute; arguments as in
1701 struct attribute_spec.handler. */
1702
1703static tree
1704handle_noclone_attribute (tree *node, tree name,
1705 tree ARG_UNUSED (args),
1706 int ARG_UNUSED (flags), bool *no_add_attrs)
1707{
1708 if (TREE_CODE (*node) != FUNCTION_DECL)
1709 {
1710 warning (OPT_Wattributes, "%qE attribute ignored", name);
1711 *no_add_attrs = true;
1712 }
1713
1714 return NULL_TREE;
1715}
1716
1717/* Handle a "nocf_check" attribute; arguments as in
1718 struct attribute_spec.handler. */
1719
1720static tree
1721handle_nocf_check_attribute (tree *node, tree name,
1722 tree ARG_UNUSED (args),
1723 int ARG_UNUSED (flags), bool *no_add_attrs)
1724{
1725 if (TREE_CODE (*node) != FUNCTION_TYPE
1726 && TREE_CODE (*node) != METHOD_TYPE)
1727 {
1728 warning (OPT_Wattributes, "%qE attribute ignored", name);
1729 *no_add_attrs = true;
1730 }
1731 else if (!(flag_cf_protection & CF_BRANCH))
1732 {
1733 warning (OPT_Wattributes, "%qE attribute ignored. Use "
1734 "%<-fcf-protection%> option to enable it",
1735 name);
1736 *no_add_attrs = true;
1737 }
1738
1739 return NULL_TREE;
1740}
1741
1742/* Handle a "no_icf" attribute; arguments as in
1743 struct attribute_spec.handler. */
1744
1745static tree
1746handle_noicf_attribute (tree *node, tree name,
1747 tree ARG_UNUSED (args),
1748 int ARG_UNUSED (flags), bool *no_add_attrs)
1749{
1750 if (TREE_CODE (*node) != FUNCTION_DECL
1751 && (TREE_CODE (*node) != VAR_DECL || !is_global_var (t: *node)))
1752 {
1753 warning (OPT_Wattributes, "%qE attribute ignored", name);
1754 *no_add_attrs = true;
1755 }
1756
1757 return NULL_TREE;
1758}
1759
1760
1761/* Handle a "always_inline" attribute; arguments as in
1762 struct attribute_spec.handler. */
1763
1764static tree
1765handle_always_inline_attribute (tree *node, tree name,
1766 tree ARG_UNUSED (args),
1767 int ARG_UNUSED (flags),
1768 bool *no_add_attrs)
1769{
1770 if (TREE_CODE (*node) == FUNCTION_DECL)
1771 {
1772 /* Set the attribute and mark it for disregarding inline
1773 limits. */
1774 DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
1775 }
1776 else
1777 {
1778 warning (OPT_Wattributes, "%qE attribute ignored", name);
1779 *no_add_attrs = true;
1780 }
1781
1782 return NULL_TREE;
1783}
1784
1785/* Handle a "gnu_inline" attribute; arguments as in
1786 struct attribute_spec.handler. */
1787
1788static tree
1789handle_gnu_inline_attribute (tree *node, tree name,
1790 tree ARG_UNUSED (args),
1791 int ARG_UNUSED (flags),
1792 bool *no_add_attrs)
1793{
1794 if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
1795 {
1796 /* Do nothing else, just set the attribute. We'll get at
1797 it later with lookup_attribute. */
1798 }
1799 else
1800 {
1801 warning (OPT_Wattributes, "%qE attribute ignored", name);
1802 *no_add_attrs = true;
1803 }
1804
1805 return NULL_TREE;
1806}
1807
1808/* Handle a "leaf" attribute; arguments as in
1809 struct attribute_spec.handler. */
1810
1811static tree
1812handle_leaf_attribute (tree *node, tree name,
1813 tree ARG_UNUSED (args),
1814 int ARG_UNUSED (flags), bool *no_add_attrs)
1815{
1816 if (TREE_CODE (*node) != FUNCTION_DECL)
1817 {
1818 warning (OPT_Wattributes, "%qE attribute ignored", name);
1819 *no_add_attrs = true;
1820 }
1821 if (!TREE_PUBLIC (*node))
1822 {
1823 warning (OPT_Wattributes, "%qE attribute has no effect on unit local "
1824 "functions", name);
1825 *no_add_attrs = true;
1826 }
1827
1828 return NULL_TREE;
1829}
1830
1831/* Handle an "artificial" attribute; arguments as in
1832 struct attribute_spec.handler. */
1833
1834static tree
1835handle_artificial_attribute (tree *node, tree name,
1836 tree ARG_UNUSED (args),
1837 int ARG_UNUSED (flags),
1838 bool *no_add_attrs)
1839{
1840 if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
1841 {
1842 /* Do nothing else, just set the attribute. We'll get at
1843 it later with lookup_attribute. */
1844 }
1845 else
1846 {
1847 warning (OPT_Wattributes, "%qE attribute ignored", name);
1848 *no_add_attrs = true;
1849 }
1850
1851 return NULL_TREE;
1852}
1853
1854/* Handle a "flatten" attribute; arguments as in
1855 struct attribute_spec.handler. */
1856
1857static tree
1858handle_flatten_attribute (tree *node, tree name,
1859 tree args ATTRIBUTE_UNUSED,
1860 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1861{
1862 if (TREE_CODE (*node) == FUNCTION_DECL)
1863 /* Do nothing else, just set the attribute. We'll get at
1864 it later with lookup_attribute. */
1865 ;
1866 else
1867 {
1868 warning (OPT_Wattributes, "%qE attribute ignored", name);
1869 *no_add_attrs = true;
1870 }
1871
1872 return NULL_TREE;
1873}
1874
1875/* Handle a "warning" or "error" attribute; arguments as in
1876 struct attribute_spec.handler. */
1877
1878static tree
1879handle_error_attribute (tree *node, tree name, tree args,
1880 int ARG_UNUSED (flags), bool *no_add_attrs)
1881{
1882 if (TREE_CODE (*node) == FUNCTION_DECL
1883 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1884 /* Do nothing else, just set the attribute. We'll get at
1885 it later with lookup_attribute. */
1886 ;
1887 else
1888 {
1889 warning (OPT_Wattributes, "%qE attribute ignored", name);
1890 *no_add_attrs = true;
1891 }
1892
1893 return NULL_TREE;
1894}
1895
1896/* Handle a "used" attribute; arguments as in
1897 struct attribute_spec.handler. */
1898
1899static tree
1900handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
1901 int ARG_UNUSED (flags), bool *no_add_attrs)
1902{
1903 tree node = *pnode;
1904
1905 if (TREE_CODE (node) == FUNCTION_DECL
1906 || (VAR_P (node) && TREE_STATIC (node))
1907 || (TREE_CODE (node) == TYPE_DECL))
1908 {
1909 TREE_USED (node) = 1;
1910 DECL_PRESERVE_P (node) = 1;
1911 if (VAR_P (node))
1912 DECL_READ_P (node) = 1;
1913 }
1914 else
1915 {
1916 warning (OPT_Wattributes, "%qE attribute ignored", name);
1917 *no_add_attrs = true;
1918 }
1919
1920 return NULL_TREE;
1921}
1922
1923/* Handle a "unused" attribute; arguments as in
1924 struct attribute_spec.handler. */
1925
1926tree
1927handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1928 int flags, bool *no_add_attrs)
1929{
1930 if (DECL_P (*node))
1931 {
1932 tree decl = *node;
1933
1934 if (TREE_CODE (decl) == PARM_DECL
1935 || VAR_OR_FUNCTION_DECL_P (decl)
1936 || TREE_CODE (decl) == LABEL_DECL
1937 || TREE_CODE (decl) == CONST_DECL
1938 || TREE_CODE (decl) == FIELD_DECL
1939 || TREE_CODE (decl) == TYPE_DECL)
1940 {
1941 TREE_USED (decl) = 1;
1942 if (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)
1943 DECL_READ_P (decl) = 1;
1944 }
1945 else
1946 {
1947 warning (OPT_Wattributes, "%qE attribute ignored", name);
1948 *no_add_attrs = true;
1949 }
1950 }
1951 else
1952 {
1953 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1954 *node = build_variant_type_copy (*node);
1955 TREE_USED (*node) = 1;
1956 }
1957
1958 return NULL_TREE;
1959}
1960
1961/* Handle a "retain" attribute; arguments as in
1962 struct attribute_spec.handler. */
1963
1964static tree
1965handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
1966 int ARG_UNUSED (flags), bool *no_add_attrs)
1967{
1968 tree node = *pnode;
1969
1970 if (SUPPORTS_SHF_GNU_RETAIN
1971 && (TREE_CODE (node) == FUNCTION_DECL
1972 || (VAR_P (node) && TREE_STATIC (node))))
1973 ;
1974 else
1975 {
1976 warning (OPT_Wattributes, "%qE attribute ignored", name);
1977 *no_add_attrs = true;
1978 }
1979
1980 return NULL_TREE;
1981}
1982
1983/* Handle an "uninitialized" attribute; arguments as in
1984 struct attribute_spec.handler. */
1985
1986static tree
1987handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1988 int ARG_UNUSED (flags), bool *no_add_attrs)
1989{
1990 tree decl = *node;
1991 if (!VAR_P (decl))
1992 {
1993 warning (OPT_Wattributes, "%qE attribute ignored because %qD "
1994 "is not a variable", name, decl);
1995 *no_add_attrs = true;
1996 }
1997 else if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1998 {
1999 warning (OPT_Wattributes, "%qE attribute ignored because %qD "
2000 "is not a local variable", name, decl);
2001 *no_add_attrs = true;
2002 }
2003
2004 return NULL_TREE;
2005}
2006
2007/* Handle a "externally_visible" attribute; arguments as in
2008 struct attribute_spec.handler. */
2009
2010static tree
2011handle_externally_visible_attribute (tree *pnode, tree name,
2012 tree ARG_UNUSED (args),
2013 int ARG_UNUSED (flags),
2014 bool *no_add_attrs)
2015{
2016 tree node = *pnode;
2017
2018 if (VAR_OR_FUNCTION_DECL_P (node))
2019 {
2020 if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
2021 && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
2022 {
2023 warning (OPT_Wattributes,
2024 "%qE attribute have effect only on public objects", name);
2025 *no_add_attrs = true;
2026 }
2027 }
2028 else
2029 {
2030 warning (OPT_Wattributes, "%qE attribute ignored", name);
2031 *no_add_attrs = true;
2032 }
2033
2034 return NULL_TREE;
2035}
2036
2037/* Handle the "no_reorder" attribute. Arguments as in
2038 struct attribute_spec.handler. */
2039
2040static tree
2041handle_no_reorder_attribute (tree *pnode,
2042 tree name,
2043 tree,
2044 int,
2045 bool *no_add_attrs)
2046{
2047 tree node = *pnode;
2048
2049 if (!VAR_OR_FUNCTION_DECL_P (node)
2050 && !(TREE_STATIC (node) || DECL_EXTERNAL (node)))
2051 {
2052 warning (OPT_Wattributes,
2053 "%qE attribute only affects top level objects",
2054 name);
2055 *no_add_attrs = true;
2056 }
2057
2058 return NULL_TREE;
2059}
2060
2061/* Handle a "const" attribute; arguments as in
2062 struct attribute_spec.handler. */
2063
2064static tree
2065handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
2066 int flags, bool *no_add_attrs)
2067{
2068 tree type = TREE_TYPE (*node);
2069
2070 /* See FIXME comment on noreturn in c_common_attribute_table. */
2071 if (TREE_CODE (*node) == FUNCTION_DECL)
2072 TREE_READONLY (*node) = 1;
2073 else if (TREE_CODE (type) == POINTER_TYPE
2074 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
2075 TREE_TYPE (*node)
2076 = (build_qualified_type
2077 (build_pointer_type
2078 (build_type_variant (TREE_TYPE (type), 1,
2079 TREE_THIS_VOLATILE (TREE_TYPE (type)))),
2080 TYPE_QUALS (type)));
2081 else
2082 {
2083 warning (OPT_Wattributes, "%qE attribute ignored", name);
2084 *no_add_attrs = true;
2085 }
2086
2087 /* void __builtin_unreachable(void) is const. Accept other such
2088 built-ins but warn on user-defined functions that return void. */
2089 if (!(flags & ATTR_FLAG_BUILT_IN)
2090 && TREE_CODE (*node) == FUNCTION_DECL
2091 && VOID_TYPE_P (TREE_TYPE (type)))
2092 warning (OPT_Wattributes, "%qE attribute on function "
2093 "returning %<void%>", name);
2094
2095 return NULL_TREE;
2096}
2097
2098/* Handle a "scalar_storage_order" attribute; arguments as in
2099 struct attribute_spec.handler. */
2100
2101static tree
2102handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
2103 int flags, bool *no_add_attrs)
2104{
2105 tree id = TREE_VALUE (args);
2106 tree type;
2107
2108 if (TREE_CODE (*node) == TYPE_DECL
2109 && ! (flags & ATTR_FLAG_CXX11))
2110 node = &TREE_TYPE (*node);
2111 type = *node;
2112
2113 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
2114 {
2115 error ("%qE attribute is not supported because endianness is not uniform",
2116 name);
2117 return NULL_TREE;
2118 }
2119
2120 if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ())
2121 {
2122 bool reverse = false;
2123
2124 if (TREE_CODE (id) == STRING_CST
2125 && strcmp (TREE_STRING_POINTER (id), s2: "big-endian") == 0)
2126 reverse = !BYTES_BIG_ENDIAN;
2127 else if (TREE_CODE (id) == STRING_CST
2128 && strcmp (TREE_STRING_POINTER (id), s2: "little-endian") == 0)
2129 reverse = BYTES_BIG_ENDIAN;
2130 else
2131 {
2132 error ("attribute %qE argument must be one of %qs or %qs",
2133 name, "big-endian", "little-endian");
2134 return NULL_TREE;
2135 }
2136
2137 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2138 {
2139 if (reverse)
2140 /* A type variant isn't good enough, since we don't want a cast
2141 to such a type to be removed as a no-op. */
2142 *node = type = build_duplicate_type (type);
2143 }
2144
2145 TYPE_REVERSE_STORAGE_ORDER (type) = reverse;
2146 return NULL_TREE;
2147 }
2148
2149 warning (OPT_Wattributes, "%qE attribute ignored", name);
2150 *no_add_attrs = true;
2151 return NULL_TREE;
2152}
2153
2154/* Handle a "transparent_union" attribute; arguments as in
2155 struct attribute_spec.handler. */
2156
2157static tree
2158handle_transparent_union_attribute (tree *node, tree name,
2159 tree ARG_UNUSED (args), int flags,
2160 bool *no_add_attrs)
2161{
2162 tree type;
2163
2164 *no_add_attrs = true;
2165
2166 if (TREE_CODE (*node) == TYPE_DECL
2167 && ! (flags & ATTR_FLAG_CXX11))
2168 node = &TREE_TYPE (*node);
2169 type = *node;
2170
2171 if (TREE_CODE (type) == UNION_TYPE)
2172 {
2173 /* Make sure that the first field will work for a transparent union.
2174 If the type isn't complete yet, leave the check to the code in
2175 finish_struct. */
2176 if (TYPE_SIZE (type))
2177 {
2178 tree first = first_field (type);
2179 if (first == NULL_TREE
2180 || DECL_ARTIFICIAL (first)
2181 || TYPE_MODE (type) != DECL_MODE (first))
2182 goto ignored;
2183 }
2184
2185 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2186 {
2187 /* If the type isn't complete yet, setting the flag
2188 on a variant wouldn't ever be checked. */
2189 if (!TYPE_SIZE (type))
2190 goto ignored;
2191
2192 /* build_duplicate_type doesn't work for C++. */
2193 if (c_dialect_cxx ())
2194 goto ignored;
2195
2196 /* A type variant isn't good enough, since we don't want a cast
2197 to such a type to be removed as a no-op. */
2198 *node = type = build_duplicate_type (type);
2199 }
2200
2201 for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
2202 TYPE_TRANSPARENT_AGGR (t) = 1;
2203 return NULL_TREE;
2204 }
2205
2206 ignored:
2207 warning (OPT_Wattributes, "%qE attribute ignored", name);
2208 return NULL_TREE;
2209}
2210
2211/* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to
2212 get the requested priority for a constructor or destructor,
2213 possibly issuing diagnostics for invalid or reserved
2214 priorities. */
2215
2216static priority_type
2217get_priority (tree args, bool is_destructor)
2218{
2219 HOST_WIDE_INT pri;
2220 tree arg;
2221
2222 if (!args)
2223 return DEFAULT_INIT_PRIORITY;
2224
2225 if (!SUPPORTS_INIT_PRIORITY)
2226 {
2227 if (is_destructor)
2228 error ("destructor priorities are not supported");
2229 else
2230 error ("constructor priorities are not supported");
2231 return DEFAULT_INIT_PRIORITY;
2232 }
2233
2234 arg = TREE_VALUE (args);
2235 if (TREE_CODE (arg) == IDENTIFIER_NODE || TREE_CODE (arg) == FUNCTION_DECL)
2236 goto invalid;
2237 if (arg == error_mark_node)
2238 return DEFAULT_INIT_PRIORITY;
2239 arg = default_conversion (arg);
2240 if (!tree_fits_shwi_p (arg)
2241 || !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
2242 goto invalid;
2243
2244 pri = tree_to_shwi (arg);
2245 if (pri < 0 || pri > MAX_INIT_PRIORITY)
2246 goto invalid;
2247
2248 if (pri <= MAX_RESERVED_INIT_PRIORITY)
2249 {
2250 if (is_destructor)
2251 warning (OPT_Wprio_ctor_dtor,
2252 "destructor priorities from 0 to %d are reserved "
2253 "for the implementation",
2254 MAX_RESERVED_INIT_PRIORITY);
2255 else
2256 warning (OPT_Wprio_ctor_dtor,
2257 "constructor priorities from 0 to %d are reserved "
2258 "for the implementation",
2259 MAX_RESERVED_INIT_PRIORITY);
2260 }
2261 return pri;
2262
2263 invalid:
2264 if (is_destructor)
2265 error ("destructor priorities must be integers from 0 to %d inclusive",
2266 MAX_INIT_PRIORITY);
2267 else
2268 error ("constructor priorities must be integers from 0 to %d inclusive",
2269 MAX_INIT_PRIORITY);
2270 return DEFAULT_INIT_PRIORITY;
2271}
2272
2273/* Handle a "constructor" attribute; arguments as in
2274 struct attribute_spec.handler. */
2275
2276static tree
2277handle_constructor_attribute (tree *node, tree name, tree args,
2278 int ARG_UNUSED (flags),
2279 bool *no_add_attrs)
2280{
2281 tree decl = *node;
2282 tree type = TREE_TYPE (decl);
2283
2284 if (TREE_CODE (decl) == FUNCTION_DECL
2285 && TREE_CODE (type) == FUNCTION_TYPE
2286 && decl_function_context (decl) == 0)
2287 {
2288 priority_type priority;
2289 DECL_STATIC_CONSTRUCTOR (decl) = 1;
2290 priority = get_priority (args, /*is_destructor=*/false);
2291 SET_DECL_INIT_PRIORITY (decl, priority);
2292 TREE_USED (decl) = 1;
2293 }
2294 else
2295 {
2296 warning (OPT_Wattributes, "%qE attribute ignored", name);
2297 *no_add_attrs = true;
2298 }
2299
2300 return NULL_TREE;
2301}
2302
2303/* Handle a "destructor" attribute; arguments as in
2304 struct attribute_spec.handler. */
2305
2306static tree
2307handle_destructor_attribute (tree *node, tree name, tree args,
2308 int ARG_UNUSED (flags),
2309 bool *no_add_attrs)
2310{
2311 tree decl = *node;
2312 tree type = TREE_TYPE (decl);
2313
2314 if (TREE_CODE (decl) == FUNCTION_DECL
2315 && TREE_CODE (type) == FUNCTION_TYPE
2316 && decl_function_context (decl) == 0)
2317 {
2318 priority_type priority;
2319 DECL_STATIC_DESTRUCTOR (decl) = 1;
2320 priority = get_priority (args, /*is_destructor=*/true);
2321 SET_DECL_FINI_PRIORITY (decl, priority);
2322 TREE_USED (decl) = 1;
2323 }
2324 else
2325 {
2326 warning (OPT_Wattributes, "%qE attribute ignored", name);
2327 *no_add_attrs = true;
2328 }
2329
2330 return NULL_TREE;
2331}
2332
2333/* Nonzero if the mode is a valid vector mode for this architecture.
2334 This returns nonzero even if there is no hardware support for the
2335 vector mode, but we can emulate with narrower modes. */
2336
2337static bool
2338vector_mode_valid_p (machine_mode mode)
2339{
2340 enum mode_class mclass = GET_MODE_CLASS (mode);
2341
2342 /* Doh! What's going on? */
2343 if (mclass != MODE_VECTOR_INT
2344 && mclass != MODE_VECTOR_FLOAT
2345 && mclass != MODE_VECTOR_FRACT
2346 && mclass != MODE_VECTOR_UFRACT
2347 && mclass != MODE_VECTOR_ACCUM
2348 && mclass != MODE_VECTOR_UACCUM)
2349 return false;
2350
2351 /* Hardware support. Woo hoo! */
2352 if (targetm.vector_mode_supported_p (mode))
2353 return true;
2354
2355 /* We should probably return 1 if requesting V4DI and we have no DI,
2356 but we have V2DI, but this is probably very unlikely. */
2357
2358 /* If we have support for the inner mode, we can safely emulate it.
2359 We may not have V2DI, but me can emulate with a pair of DIs. */
2360 return targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
2361}
2362
2363
2364/* Handle a "mode" attribute; arguments as in
2365 struct attribute_spec.handler. */
2366
2367static tree
2368handle_mode_attribute (tree *node, tree name, tree args,
2369 int ARG_UNUSED (flags), bool *no_add_attrs)
2370{
2371 tree type = *node;
2372 tree ident = TREE_VALUE (args);
2373
2374 *no_add_attrs = true;
2375
2376 if (TREE_CODE (ident) != IDENTIFIER_NODE)
2377 warning (OPT_Wattributes, "%qE attribute ignored", name);
2378 else
2379 {
2380 int j;
2381 const char *p = IDENTIFIER_POINTER (ident);
2382 int len = strlen (s: p);
2383 machine_mode mode = VOIDmode;
2384 tree typefm;
2385 bool valid_mode;
2386
2387 if (len > 4 && p[0] == '_' && p[1] == '_'
2388 && p[len - 1] == '_' && p[len - 2] == '_')
2389 {
2390 char *newp = (char *) alloca (len - 1);
2391
2392 strcpy (dest: newp, src: &p[2]);
2393 newp[len - 4] = '\0';
2394 p = newp;
2395 }
2396
2397 /* Change this type to have a type with the specified mode.
2398 First check for the special modes. */
2399 if (!strcmp (s1: p, s2: "byte"))
2400 mode = byte_mode;
2401 else if (!strcmp (s1: p, s2: "word"))
2402 mode = word_mode;
2403 else if (!strcmp (s1: p, s2: "pointer"))
2404 mode = ptr_mode;
2405 else if (!strcmp (s1: p, s2: "libgcc_cmp_return"))
2406 mode = targetm.libgcc_cmp_return_mode ();
2407 else if (!strcmp (s1: p, s2: "libgcc_shift_count"))
2408 mode = targetm.libgcc_shift_count_mode ();
2409 else if (!strcmp (s1: p, s2: "unwind_word"))
2410 mode = targetm.unwind_word_mode ();
2411 else
2412 for (j = 0; j < NUM_MACHINE_MODES; j++)
2413 if (!strcmp (s1: p, GET_MODE_NAME (j)))
2414 {
2415 mode = (machine_mode) j;
2416 break;
2417 }
2418
2419 if (mode == VOIDmode)
2420 {
2421 error ("unknown machine mode %qE", ident);
2422 return NULL_TREE;
2423 }
2424
2425 /* Allow the target a chance to translate MODE into something supported.
2426 See PR86324. */
2427 mode = targetm.translate_mode_attribute (mode);
2428
2429 valid_mode = false;
2430 switch (GET_MODE_CLASS (mode))
2431 {
2432 case MODE_INT:
2433 case MODE_PARTIAL_INT:
2434 case MODE_FLOAT:
2435 case MODE_DECIMAL_FLOAT:
2436 case MODE_FRACT:
2437 case MODE_UFRACT:
2438 case MODE_ACCUM:
2439 case MODE_UACCUM:
2440 valid_mode
2441 = targetm.scalar_mode_supported_p (as_a <scalar_mode> (m: mode));
2442 break;
2443
2444 case MODE_COMPLEX_INT:
2445 case MODE_COMPLEX_FLOAT:
2446 valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
2447 break;
2448
2449 case MODE_VECTOR_INT:
2450 case MODE_VECTOR_FLOAT:
2451 case MODE_VECTOR_FRACT:
2452 case MODE_VECTOR_UFRACT:
2453 case MODE_VECTOR_ACCUM:
2454 case MODE_VECTOR_UACCUM:
2455 warning (OPT_Wattributes, "specifying vector types with "
2456 "%<__attribute__ ((mode))%> is deprecated");
2457 inform (input_location,
2458 "use %<__attribute__ ((vector_size))%> instead");
2459 valid_mode = vector_mode_valid_p (mode);
2460 break;
2461
2462 default:
2463 break;
2464 }
2465 if (!valid_mode)
2466 {
2467 error ("unable to emulate %qs", p);
2468 return NULL_TREE;
2469 }
2470
2471 if (POINTER_TYPE_P (type))
2472 {
2473 scalar_int_mode addr_mode;
2474 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
2475 tree (*fn)(tree, machine_mode, bool);
2476
2477 if (!is_a <scalar_int_mode> (m: mode, result: &addr_mode)
2478 || !targetm.addr_space.valid_pointer_mode (addr_mode, as))
2479 {
2480 error ("invalid pointer mode %qs", p);
2481 return NULL_TREE;
2482 }
2483
2484 if (TREE_CODE (type) == POINTER_TYPE)
2485 fn = build_pointer_type_for_mode;
2486 else
2487 fn = build_reference_type_for_mode;
2488 typefm = fn (TREE_TYPE (type), addr_mode, false);
2489 }
2490 else
2491 {
2492 /* For fixed-point modes, we need to test if the signness of type
2493 and the machine mode are consistent. */
2494 if (ALL_FIXED_POINT_MODE_P (mode)
2495 && TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode))
2496 {
2497 error ("signedness of type and machine mode %qs don%'t match", p);
2498 return NULL_TREE;
2499 }
2500 /* For fixed-point modes, we need to pass saturating info. */
2501 typefm = lang_hooks.types.type_for_mode (mode,
2502 ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type)
2503 : TYPE_UNSIGNED (type));
2504 }
2505
2506 if (typefm == NULL_TREE)
2507 {
2508 error ("no data type for mode %qs", p);
2509 return NULL_TREE;
2510 }
2511 else if (TREE_CODE (type) == ENUMERAL_TYPE)
2512 {
2513 /* For enumeral types, copy the precision from the integer
2514 type returned above. If not an INTEGER_TYPE, we can't use
2515 this mode for this type. */
2516 if (TREE_CODE (typefm) != INTEGER_TYPE)
2517 {
2518 error ("cannot use mode %qs for enumerated types", p);
2519 return NULL_TREE;
2520 }
2521
2522 if (flags & ATTR_FLAG_TYPE_IN_PLACE)
2523 {
2524 TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
2525 typefm = type;
2526 }
2527 else
2528 {
2529 /* We cannot build a type variant, as there's code that assumes
2530 that TYPE_MAIN_VARIANT has the same mode. This includes the
2531 debug generators. Instead, create a subrange type. This
2532 results in all of the enumeral values being emitted only once
2533 in the original, and the subtype gets them by reference. */
2534 if (TYPE_UNSIGNED (type))
2535 typefm = make_unsigned_type (TYPE_PRECISION (typefm));
2536 else
2537 typefm = make_signed_type (TYPE_PRECISION (typefm));
2538 TREE_TYPE (typefm) = type;
2539 }
2540 *no_add_attrs = false;
2541 }
2542 else if (VECTOR_MODE_P (mode)
2543 ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
2544 : TREE_CODE (type) != TREE_CODE (typefm))
2545 {
2546 error ("mode %qs applied to inappropriate type", p);
2547 return NULL_TREE;
2548 }
2549
2550 /* Copy any quals and attributes to the new type. */
2551 *node = build_type_attribute_qual_variant (typefm, TYPE_ATTRIBUTES (type),
2552 TYPE_QUALS (type));
2553 if (TYPE_USER_ALIGN (type))
2554 *node = build_aligned_type (*node, TYPE_ALIGN (type));
2555 }
2556
2557 return NULL_TREE;
2558}
2559
2560/* Handle a "section" attribute; arguments as in
2561 struct attribute_spec.handler. */
2562
2563static tree
2564handle_section_attribute (tree *node, tree name, tree args,
2565 int flags, bool *no_add_attrs)
2566{
2567 tree decl = *node;
2568 tree res = NULL_TREE;
2569 tree argval = TREE_VALUE (args);
2570 const char* new_section_name;
2571
2572 if (!targetm_common.have_named_sections)
2573 {
2574 error_at (DECL_SOURCE_LOCATION (*node),
2575 "section attributes are not supported for this target");
2576 goto fail;
2577 }
2578
2579 if (!VAR_OR_FUNCTION_DECL_P (decl))
2580 {
2581 error ("section attribute not allowed for %q+D", *node);
2582 goto fail;
2583 }
2584
2585 if (TREE_CODE (argval) != STRING_CST)
2586 {
2587 error ("section attribute argument not a string constant");
2588 goto fail;
2589 }
2590
2591 if (VAR_P (decl)
2592 && current_function_decl != NULL_TREE
2593 && !TREE_STATIC (decl))
2594 {
2595 error_at (DECL_SOURCE_LOCATION (decl),
2596 "section attribute cannot be specified for local variables");
2597 goto fail;
2598 }
2599
2600 new_section_name = TREE_STRING_POINTER (argval);
2601
2602 /* The decl may have already been given a section attribute
2603 from a previous declaration. Ensure they match. */
2604 if (const char* const old_section_name = DECL_SECTION_NAME (decl))
2605 if (strcmp (s1: old_section_name, s2: new_section_name) != 0)
2606 {
2607 error ("section of %q+D conflicts with previous declaration",
2608 *node);
2609 goto fail;
2610 }
2611
2612 if (VAR_P (decl)
2613 && !targetm.have_tls && targetm.emutls.tmpl_section
2614 && DECL_THREAD_LOCAL_P (decl))
2615 {
2616 error ("section of %q+D cannot be overridden", *node);
2617 goto fail;
2618 }
2619
2620 if (!validate_attr_arg (node, name, newarg: argval))
2621 goto fail;
2622
2623 res = targetm.handle_generic_attribute (node, name, args, flags,
2624 no_add_attrs);
2625
2626 /* If the back end confirms the attribute can be added then continue onto
2627 final processing. */
2628 if (!(*no_add_attrs))
2629 {
2630 set_decl_section_name (decl, new_section_name);
2631 return res;
2632 }
2633
2634fail:
2635 *no_add_attrs = true;
2636 return res;
2637}
2638
2639/* Common codes shared by handle_warn_if_not_aligned_attribute and
2640 handle_aligned_attribute. */
2641
2642static tree
2643common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
2644 bool *no_add_attrs,
2645 bool warn_if_not_aligned_p)
2646{
2647 tree decl = NULL_TREE;
2648 tree *type = NULL;
2649 bool is_type = false;
2650 tree align_expr;
2651
2652 /* The last (already pushed) declaration with all validated attributes
2653 merged in or the current about-to-be-pushed one if one hasn't been
2654 yet. */
2655 tree last_decl = node[1] ? node[1] : *node;
2656
2657 if (args)
2658 {
2659 align_expr = TREE_VALUE (args);
2660 if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE
2661 && TREE_CODE (align_expr) != FUNCTION_DECL)
2662 align_expr = default_conversion (align_expr);
2663 }
2664 else
2665 align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT);
2666
2667 if (DECL_P (*node))
2668 {
2669 decl = *node;
2670 type = &TREE_TYPE (decl);
2671 is_type = TREE_CODE (*node) == TYPE_DECL;
2672 }
2673 else if (TYPE_P (*node))
2674 type = node, is_type = true;
2675
2676 /* True to consider invalid alignments greater than MAX_OFILE_ALIGNMENT. */
2677 bool objfile = (TREE_CODE (*node) == FUNCTION_DECL
2678 || (VAR_P (*node) && TREE_STATIC (*node)));
2679 /* Log2 of specified alignment. */
2680 int pow2align = check_user_alignment (align_expr, objfile,
2681 /* warn_zero = */ true);
2682 if (pow2align == -1)
2683 {
2684 *no_add_attrs = true;
2685 return NULL_TREE;
2686 }
2687
2688 /* The alignment in bits corresponding to the specified alignment. */
2689 unsigned bitalign = (1U << pow2align) * BITS_PER_UNIT;
2690
2691 /* The alignment of the current declaration and that of the last
2692 pushed declaration, determined on demand below. */
2693 unsigned curalign = 0;
2694 unsigned lastalign = 0;
2695
2696 /* True when SET_DECL_ALIGN() should be called for the decl when
2697 *NO_ADD_ATTRS is false. */
2698 bool set_align = true;
2699 if (is_type)
2700 {
2701 if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2702 /* OK, modify the type in place. */;
2703 /* If we have a TYPE_DECL, then copy the type, so that we
2704 don't accidentally modify a builtin type. See pushdecl. */
2705 else if (decl && TREE_TYPE (decl) != error_mark_node
2706 && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
2707 {
2708 tree tt = TREE_TYPE (decl);
2709 *type = build_variant_type_copy (*type);
2710 DECL_ORIGINAL_TYPE (decl) = tt;
2711 TYPE_NAME (*type) = decl;
2712 TREE_USED (*type) = TREE_USED (decl);
2713 TREE_TYPE (decl) = *type;
2714 }
2715 else
2716 *type = build_variant_type_copy (*type);
2717
2718 if (warn_if_not_aligned_p)
2719 {
2720 SET_TYPE_WARN_IF_NOT_ALIGN (*type, bitalign);
2721 warn_if_not_aligned_p = false;
2722 }
2723 else
2724 {
2725 SET_TYPE_ALIGN (*type, bitalign);
2726 TYPE_USER_ALIGN (*type) = 1;
2727 }
2728 }
2729 else if (! VAR_OR_FUNCTION_DECL_P (decl)
2730 && TREE_CODE (decl) != FIELD_DECL)
2731 {
2732 error ("alignment may not be specified for %q+D", decl);
2733 *no_add_attrs = true;
2734 }
2735 else if (TREE_CODE (decl) == FUNCTION_DECL
2736 && (((curalign = DECL_ALIGN (decl)) > bitalign)
2737 | ((lastalign = DECL_ALIGN (last_decl)) > bitalign)))
2738 {
2739 /* Either a prior attribute on the same declaration or one
2740 on a prior declaration of the same function specifies
2741 stricter alignment than this attribute. */
2742 bool note = (lastalign > curalign
2743 || (lastalign == curalign
2744 && (DECL_USER_ALIGN (last_decl)
2745 > DECL_USER_ALIGN (decl))));
2746 if (note)
2747 curalign = lastalign;
2748
2749 curalign /= BITS_PER_UNIT;
2750 unsigned newalign = bitalign / BITS_PER_UNIT;
2751
2752 auto_diagnostic_group d;
2753 if ((DECL_USER_ALIGN (decl)
2754 || DECL_USER_ALIGN (last_decl)))
2755 {
2756 if (warning (OPT_Wattributes,
2757 "ignoring attribute %<%E (%u)%> because it conflicts "
2758 "with attribute %<%E (%u)%>",
2759 name, newalign, name, curalign)
2760 && note)
2761 inform (DECL_SOURCE_LOCATION (last_decl),
2762 "previous declaration here");
2763 /* Only reject attempts to relax/override an alignment
2764 explicitly specified previously and accept declarations
2765 that appear to relax the implicit function alignment for
2766 the target. Both increasing and increasing the alignment
2767 set by -falign-functions setting is permitted. */
2768 *no_add_attrs = true;
2769 }
2770 else if (!warn_if_not_aligned_p)
2771 {
2772 /* Do not fail for attribute warn_if_not_aligned. Otherwise,
2773 silently avoid applying the alignment to the declaration
2774 because it's implicitly satisfied by the target. Apply
2775 the attribute nevertheless so it can be retrieved by
2776 __builtin_has_attribute. */
2777 set_align = false;
2778 }
2779 }
2780 else if (DECL_USER_ALIGN (decl)
2781 && DECL_ALIGN (decl) > bitalign)
2782 /* C++-11 [dcl.align/4]:
2783
2784 When multiple alignment-specifiers are specified for an
2785 entity, the alignment requirement shall be set to the
2786 strictest specified alignment.
2787
2788 This formally comes from the c++11 specification but we are
2789 doing it for the GNU attribute syntax as well. */
2790 *no_add_attrs = true;
2791 else if (warn_if_not_aligned_p
2792 && TREE_CODE (decl) == FIELD_DECL
2793 && !DECL_C_BIT_FIELD (decl))
2794 {
2795 SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
2796 warn_if_not_aligned_p = false;
2797 set_align = false;
2798 }
2799
2800 if (warn_if_not_aligned_p)
2801 {
2802 error ("%<warn_if_not_aligned%> may not be specified for %q+D",
2803 decl);
2804 *no_add_attrs = true;
2805 }
2806 else if (!is_type && !*no_add_attrs && set_align)
2807 {
2808 SET_DECL_ALIGN (decl, bitalign);
2809 DECL_USER_ALIGN (decl) = 1;
2810 }
2811
2812 return NULL_TREE;
2813}
2814
2815/* Handle a "aligned" attribute; arguments as in
2816 struct attribute_spec.handler. */
2817
2818tree
2819handle_aligned_attribute (tree *node, tree name, tree args,
2820 int flags, bool *no_add_attrs)
2821{
2822 return common_handle_aligned_attribute (node, name, args, flags,
2823 no_add_attrs, warn_if_not_aligned_p: false);
2824}
2825
2826/* Handle a "warn_if_not_aligned" attribute; arguments as in
2827 struct attribute_spec.handler. */
2828
2829static tree
2830handle_warn_if_not_aligned_attribute (tree *node, tree name,
2831 tree args, int flags,
2832 bool *no_add_attrs)
2833{
2834 return common_handle_aligned_attribute (node, name, args, flags,
2835 no_add_attrs, warn_if_not_aligned_p: true);
2836}
2837
2838/* Handle a "strict_flex_array" attribute; arguments as in
2839 struct attribute_spec.handler. */
2840
2841static tree
2842handle_strict_flex_array_attribute (tree *node, tree name,
2843 tree args, int ARG_UNUSED (flags),
2844 bool *no_add_attrs)
2845{
2846 tree decl = *node;
2847 tree argval = TREE_VALUE (args);
2848
2849 /* This attribute only applies to field decls of a structure. */
2850 if (TREE_CODE (decl) != FIELD_DECL)
2851 {
2852 error_at (DECL_SOURCE_LOCATION (decl),
2853 "%qE attribute may not be specified for %q+D", name, decl);
2854 *no_add_attrs = true;
2855 }
2856 /* This attribute only applies to field with array type. */
2857 else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
2858 {
2859 error_at (DECL_SOURCE_LOCATION (decl),
2860 "%qE attribute may not be specified for a non-array field",
2861 name);
2862 *no_add_attrs = true;
2863 }
2864 else if (TREE_CODE (argval) != INTEGER_CST)
2865 {
2866 error_at (DECL_SOURCE_LOCATION (decl),
2867 "%qE attribute argument not an integer", name);
2868 *no_add_attrs = true;
2869 }
2870 else if (!tree_fits_uhwi_p (argval) || tree_to_uhwi (argval) > 3)
2871 {
2872 error_at (DECL_SOURCE_LOCATION (decl),
2873 "%qE attribute argument %qE is not an integer constant"
2874 " between 0 and 3", name, argval);
2875 *no_add_attrs = true;
2876 }
2877
2878 return NULL_TREE;
2879}
2880
2881/* Handle a "counted_by" attribute; arguments as in
2882 struct attribute_spec.handler. */
2883
2884static tree
2885handle_counted_by_attribute (tree *node, tree name,
2886 tree args, int ARG_UNUSED (flags),
2887 bool *no_add_attrs)
2888{
2889 tree decl = *node;
2890 tree argval = TREE_VALUE (args);
2891 tree old_counted_by = lookup_attribute (attr_name: "counted_by", DECL_ATTRIBUTES (decl));
2892
2893 /* This attribute is not supported in C++. */
2894 if (c_dialect_cxx ())
2895 {
2896 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
2897 "%qE attribute is not supported for C++ for now, ignored",
2898 name);
2899 *no_add_attrs = true;
2900 }
2901 /* This attribute only applies to field decls of a structure. */
2902 else if (TREE_CODE (decl) != FIELD_DECL)
2903 {
2904 error_at (DECL_SOURCE_LOCATION (decl),
2905 "%qE attribute is not allowed for a non-field"
2906 " declaration %q+D", name, decl);
2907 *no_add_attrs = true;
2908 }
2909 /* This attribute only applies to field with array type. */
2910 else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
2911 {
2912 error_at (DECL_SOURCE_LOCATION (decl),
2913 "%qE attribute is not allowed for a non-array field",
2914 name);
2915 *no_add_attrs = true;
2916 }
2917 /* This attribute only applies to a C99 flexible array member type. */
2918 else if (! c_flexible_array_member_type_p (TREE_TYPE (decl)))
2919 {
2920 error_at (DECL_SOURCE_LOCATION (decl),
2921 "%qE attribute is not allowed for a non-flexible"
2922 " array member field", name);
2923 *no_add_attrs = true;
2924 }
2925 /* The argument should be an identifier. */
2926 else if (TREE_CODE (argval) != IDENTIFIER_NODE)
2927 {
2928 error_at (DECL_SOURCE_LOCATION (decl),
2929 "%<counted_by%> argument is not an identifier");
2930 *no_add_attrs = true;
2931 }
2932 /* Issue error when there is a counted_by attribute with a different
2933 field as the argument for the same flexible array member field. */
2934 else if (old_counted_by != NULL_TREE)
2935 {
2936 tree old_fieldname = TREE_VALUE (TREE_VALUE (old_counted_by));
2937 if (strcmp (IDENTIFIER_POINTER (old_fieldname),
2938 IDENTIFIER_POINTER (argval)) != 0)
2939 {
2940 error_at (DECL_SOURCE_LOCATION (decl),
2941 "%<counted_by%> argument %qE conflicts with"
2942 " previous declaration %qE", argval, old_fieldname);
2943 *no_add_attrs = true;
2944 }
2945 }
2946
2947 return NULL_TREE;
2948}
2949
2950/* Handle a "weak" attribute; arguments as in
2951 struct attribute_spec.handler. */
2952
2953static tree
2954handle_weak_attribute (tree *node, tree name,
2955 tree ARG_UNUSED (args),
2956 int ARG_UNUSED (flags),
2957 bool * ARG_UNUSED (no_add_attrs))
2958{
2959 if (TREE_CODE (*node) == FUNCTION_DECL
2960 && DECL_DECLARED_INLINE_P (*node))
2961 {
2962 warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
2963 *no_add_attrs = true;
2964 }
2965 else if (lookup_attribute (attr_name: "ifunc", DECL_ATTRIBUTES (*node)))
2966 {
2967 error ("indirect function %q+D cannot be declared weak", *node);
2968 *no_add_attrs = true;
2969 return NULL_TREE;
2970 }
2971 else if (VAR_OR_FUNCTION_DECL_P (*node))
2972 declare_weak (*node);
2973 else
2974 warning (OPT_Wattributes, "%qE attribute ignored", name);
2975
2976 return NULL_TREE;
2977}
2978
2979/* Handle a "noinit" or "persistent" attribute; arguments as in
2980 struct attribute_spec.handler.
2981 This generic handler is used for "special variable sections" that allow the
2982 section name to be set using a dedicated attribute. Additional validation
2983 is performed for the specific properties of the section corresponding to the
2984 attribute.
2985 The ".noinit" section *is not* loaded by the program loader, and is not
2986 initialized by the runtime startup code.
2987 The ".persistent" section *is* loaded by the program loader, but is not
2988 initialized by the runtime startup code. */
2989static tree
2990handle_special_var_sec_attribute (tree *node, tree name, tree args,
2991 int flags, bool *no_add_attrs)
2992{
2993 tree decl = *node;
2994 tree res = NULL_TREE;
2995
2996 /* First perform generic validation common to "noinit" and "persistent"
2997 attributes. */
2998 if (!targetm_common.have_named_sections)
2999 {
3000 error_at (DECL_SOURCE_LOCATION (decl),
3001 "section attributes are not supported for this target");
3002 goto fail;
3003 }
3004
3005 if (!VAR_P (decl))
3006 {
3007 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
3008 "ignoring %qE attribute not set on a variable",
3009 name);
3010 goto fail;
3011 }
3012
3013 if (VAR_P (decl)
3014 && current_function_decl != NULL_TREE
3015 && !TREE_STATIC (decl))
3016 {
3017 error_at (DECL_SOURCE_LOCATION (decl),
3018 "%qE attribute cannot be specified for local variables",
3019 name);
3020 goto fail;
3021 }
3022
3023 if (VAR_P (decl)
3024 && !targetm.have_tls && targetm.emutls.tmpl_section
3025 && DECL_THREAD_LOCAL_P (decl))
3026 {
3027 error ("section of %q+D cannot be overridden", decl);
3028 goto fail;
3029 }
3030
3031 if (!targetm.have_switchable_bss_sections)
3032 {
3033 error ("%qE attribute is specific to ELF targets", name);
3034 goto fail;
3035 }
3036
3037 if (TREE_READONLY (decl))
3038 {
3039 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
3040 "ignoring %qE attribute set on const variable",
3041 name);
3042 goto fail;
3043 }
3044
3045 /* Now validate noinit/persistent individually. */
3046 if (strcmp (IDENTIFIER_POINTER (name), s2: "noinit") == 0)
3047 {
3048 if (DECL_INITIAL (decl))
3049 {
3050 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
3051 "ignoring %qE attribute set on initialized variable",
3052 name);
3053 goto fail;
3054 }
3055 /* If this var is thought to be common, then change this. "noinit"
3056 variables must be placed in an explicit ".noinit" section. */
3057 DECL_COMMON (decl) = 0;
3058 }
3059 else if (strcmp (IDENTIFIER_POINTER (name), s2: "persistent") == 0)
3060 {
3061 if (DECL_COMMON (decl) || DECL_INITIAL (decl) == NULL_TREE)
3062 {
3063 warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
3064 "ignoring %qE attribute set on uninitialized variable",
3065 name);
3066 goto fail;
3067 }
3068 }
3069 else
3070 gcc_unreachable ();
3071
3072 res = targetm.handle_generic_attribute (node, name, args, flags,
3073 no_add_attrs);
3074
3075 /* If the back end confirms the attribute can be added then continue onto
3076 final processing. */
3077 if (!(*no_add_attrs))
3078 return res;
3079
3080fail:
3081 *no_add_attrs = true;
3082 return res;
3083}
3084
3085/* Handle a "noplt" attribute; arguments as in
3086 struct attribute_spec.handler. */
3087
3088static tree
3089handle_noplt_attribute (tree *node, tree name,
3090 tree ARG_UNUSED (args),
3091 int ARG_UNUSED (flags),
3092 bool * ARG_UNUSED (no_add_attrs))
3093{
3094 if (TREE_CODE (*node) != FUNCTION_DECL)
3095 {
3096 warning (OPT_Wattributes,
3097 "%qE attribute is only applicable on functions", name);
3098 *no_add_attrs = true;
3099 return NULL_TREE;
3100 }
3101 return NULL_TREE;
3102}
3103
3104/* Handle a "symver" attribute. */
3105
3106static tree
3107handle_symver_attribute (tree *node, tree ARG_UNUSED (name), tree args,
3108 int ARG_UNUSED (flags), bool *no_add_attrs)
3109{
3110 tree symver;
3111 const char *symver_str;
3112
3113 if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
3114 {
3115 warning (OPT_Wattributes,
3116 "%<symver%> attribute only applies to functions and variables");
3117 *no_add_attrs = true;
3118 return NULL_TREE;
3119 }
3120
3121 if (!decl_in_symtab_p (decl: *node))
3122 {
3123 warning (OPT_Wattributes,
3124 "%<symver%> attribute is only applicable to symbols");
3125 *no_add_attrs = true;
3126 return NULL_TREE;
3127 }
3128
3129 for (; args; args = TREE_CHAIN (args))
3130 {
3131 symver = TREE_VALUE (args);
3132 if (TREE_CODE (symver) != STRING_CST)
3133 {
3134 error ("%<symver%> attribute argument not a string constant");
3135 *no_add_attrs = true;
3136 return NULL_TREE;
3137 }
3138
3139 symver_str = TREE_STRING_POINTER (symver);
3140
3141 int ats = 0;
3142 for (int n = 0; (int)n < TREE_STRING_LENGTH (symver); n++)
3143 if (symver_str[n] == '@')
3144 ats++;
3145
3146 if (ats != 1 && ats != 2)
3147 {
3148 error ("symver attribute argument must have format %<name@nodename%>");
3149 error ("%<symver%> attribute argument %qs must contain one or two "
3150 "%<@%>", symver_str);
3151 *no_add_attrs = true;
3152 return NULL_TREE;
3153 }
3154 }
3155
3156 return NULL_TREE;
3157}
3158
3159
3160/* Handle an "alias" or "ifunc" attribute; arguments as in
3161 struct attribute_spec.handler, except that IS_ALIAS tells us
3162 whether this is an alias as opposed to ifunc attribute. */
3163
3164static tree
3165handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
3166 bool *no_add_attrs)
3167{
3168 tree decl = *node;
3169
3170 if (TREE_CODE (decl) != FUNCTION_DECL
3171 && (!is_alias || !VAR_P (decl)))
3172 {
3173 warning (OPT_Wattributes, "%qE attribute ignored", name);
3174 *no_add_attrs = true;
3175 }
3176 else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
3177 || (TREE_CODE (decl) != FUNCTION_DECL
3178 && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
3179 /* A static variable declaration is always a tentative definition,
3180 but the alias is a non-tentative definition which overrides. */
3181 || (TREE_CODE (decl) != FUNCTION_DECL
3182 && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
3183 {
3184 error ("%q+D defined both normally and as %qE attribute", decl, name);
3185 *no_add_attrs = true;
3186 return NULL_TREE;
3187 }
3188 else if (!is_alias
3189 && (lookup_attribute (attr_name: "weak", DECL_ATTRIBUTES (decl))
3190 || lookup_attribute (attr_name: "weakref", DECL_ATTRIBUTES (decl))))
3191 {
3192 error ("weak %q+D cannot be defined %qE", decl, name);
3193 *no_add_attrs = true;
3194 return NULL_TREE;
3195 }
3196
3197 /* Note that the very first time we process a nested declaration,
3198 decl_function_context will not be set. Indeed, *would* never
3199 be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
3200 we do below. After such frobbery, pushdecl would set the context.
3201 In any case, this is never what we want. */
3202 else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
3203 {
3204 tree id;
3205
3206 id = TREE_VALUE (args);
3207 if (TREE_CODE (id) != STRING_CST)
3208 {
3209 error ("attribute %qE argument not a string", name);
3210 *no_add_attrs = true;
3211 return NULL_TREE;
3212 }
3213 id = get_identifier (TREE_STRING_POINTER (id));
3214 /* This counts as a use of the object pointed to. */
3215 TREE_USED (id) = 1;
3216
3217 if (TREE_CODE (decl) == FUNCTION_DECL)
3218 DECL_INITIAL (decl) = error_mark_node;
3219 else
3220 TREE_STATIC (decl) = 1;
3221
3222 if (!is_alias)
3223 {
3224 /* ifuncs are also aliases, so set that attribute too. */
3225 DECL_ATTRIBUTES (decl)
3226 = tree_cons (get_identifier ("alias"), args,
3227 DECL_ATTRIBUTES (decl));
3228 DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
3229 NULL, DECL_ATTRIBUTES (decl));
3230 }
3231 }
3232 else
3233 {
3234 warning (OPT_Wattributes, "%qE attribute ignored", name);
3235 *no_add_attrs = true;
3236 }
3237
3238 if (decl_in_symtab_p (decl: *node))
3239 {
3240 struct symtab_node *n = symtab_node::get (decl);
3241 if (n && n->refuse_visibility_changes)
3242 error ("%+qD declared %qs after being used",
3243 decl, is_alias ? "alias" : "ifunc");
3244 }
3245
3246
3247 return NULL_TREE;
3248}
3249
3250/* Handle an "alias" or "ifunc" attribute; arguments as in
3251 struct attribute_spec.handler. */
3252
3253static tree
3254handle_ifunc_attribute (tree *node, tree name, tree args,
3255 int ARG_UNUSED (flags), bool *no_add_attrs)
3256{
3257 return handle_alias_ifunc_attribute (is_alias: false, node, name, args, no_add_attrs);
3258}
3259
3260/* Handle an "alias" or "ifunc" attribute; arguments as in
3261 struct attribute_spec.handler. */
3262
3263static tree
3264handle_alias_attribute (tree *node, tree name, tree args,
3265 int ARG_UNUSED (flags), bool *no_add_attrs)
3266{
3267 return handle_alias_ifunc_attribute (is_alias: true, node, name, args, no_add_attrs);
3268}
3269
3270/* Handle the "copy" attribute NAME by copying the set of attributes
3271 from the symbol referenced by ARGS to the declaration of *NODE. */
3272
3273static tree
3274handle_copy_attribute (tree *node, tree name, tree args,
3275 int flags, bool *no_add_attrs)
3276{
3277 /* Do not apply the copy attribute itself. It serves no purpose
3278 other than to copy other attributes. */
3279 *no_add_attrs = true;
3280
3281 tree decl = *node;
3282
3283 tree ref = TREE_VALUE (args);
3284 if (ref == error_mark_node)
3285 return NULL_TREE;
3286
3287 location_t loc = input_location;
3288 if (DECL_P (decl))
3289 loc = DECL_SOURCE_LOCATION (decl);
3290 if (TREE_CODE (ref) == STRING_CST)
3291 {
3292 /* Explicitly handle this case since using a string literal
3293 as an argument is a likely mistake. */
3294 error_at (loc, "%qE attribute argument cannot be a string", name);
3295 return NULL_TREE;
3296 }
3297
3298 if (CONSTANT_CLASS_P (ref)
3299 && (INTEGRAL_TYPE_P (TREE_TYPE (ref))
3300 || FLOAT_TYPE_P (TREE_TYPE (ref))))
3301 {
3302 /* Similar to the string case, since some function attributes
3303 accept literal numbers as arguments (e.g., alloc_size or
3304 nonnull) using one here is a likely mistake. */
3305 error_at (loc, "%qE attribute argument cannot be a constant arithmetic "
3306 "expression", name);
3307 return NULL_TREE;
3308 }
3309
3310 if (ref == node[1])
3311 {
3312 /* Another possible mistake (but indirect self-references aren't
3313 and diagnosed and shouldn't be). */
3314 if (warning_at (loc, OPT_Wattributes,
3315 "%qE attribute ignored on a redeclaration "
3316 "of the referenced symbol", name)
3317 && DECL_P (node[1]))
3318 inform (DECL_SOURCE_LOCATION (node[1]), "previous declaration here");
3319 return NULL_TREE;
3320 }
3321
3322 /* Consider address-of expressions in the attribute argument
3323 as requests to copy from the referenced entity. */
3324 if (TREE_CODE (ref) == ADDR_EXPR)
3325 ref = TREE_OPERAND (ref, 0);
3326
3327 do
3328 {
3329 /* Drill down into references to find the referenced decl. */
3330 tree_code refcode = TREE_CODE (ref);
3331 if (refcode == ARRAY_REF
3332 || refcode == INDIRECT_REF)
3333 ref = TREE_OPERAND (ref, 0);
3334 else if (refcode == COMPONENT_REF)
3335 ref = TREE_OPERAND (ref, 1);
3336 else
3337 break;
3338 }
3339 while (!DECL_P (ref));
3340
3341 /* For object pointer expressions, consider those to be requests
3342 to copy from their type, such as in:
3343 struct __attribute__ (copy ((struct T *)0)) U { ... };
3344 which copies type attributes from struct T to the declaration
3345 of struct U. */
3346 if ((CONSTANT_CLASS_P (ref) || EXPR_P (ref))
3347 && POINTER_TYPE_P (TREE_TYPE (ref))
3348 && !FUNCTION_POINTER_TYPE_P (TREE_TYPE (ref)))
3349 ref = TREE_TYPE (ref);
3350
3351 tree reftype = TYPE_P (ref) ? ref : TREE_TYPE (ref);
3352
3353 if (DECL_P (decl))
3354 {
3355 if ((VAR_P (decl)
3356 && (TREE_CODE (ref) == FUNCTION_DECL
3357 || (EXPR_P (ref)
3358 && POINTER_TYPE_P (reftype)
3359 && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (reftype)))))
3360 || (TREE_CODE (decl) == FUNCTION_DECL
3361 && (VAR_P (ref)
3362 || (EXPR_P (ref)
3363 && !FUNC_OR_METHOD_TYPE_P (reftype)
3364 && (!POINTER_TYPE_P (reftype)
3365 || !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (reftype)))))))
3366 {
3367 /* It makes no sense to try to copy function attributes
3368 to a variable, or variable attributes to a function. */
3369 if (warning (OPT_Wattributes,
3370 "%qE attribute ignored on a declaration of "
3371 "a different kind than referenced symbol", name)
3372 && DECL_P (ref))
3373 inform (DECL_SOURCE_LOCATION (ref),
3374 "symbol %qD referenced by %qD declared here", ref, decl);
3375 return NULL_TREE;
3376 }
3377
3378 tree attrs = NULL_TREE;
3379 if (DECL_P (ref))
3380 attrs = DECL_ATTRIBUTES (ref);
3381 else if (TYPE_P (ref))
3382 attrs = TYPE_ATTRIBUTES (ref);
3383
3384 /* Copy decl attributes from REF to DECL. */
3385 for (tree at = attrs; at; at = TREE_CHAIN (at))
3386 {
3387 /* Avoid copying attributes that affect a symbol linkage,
3388 inlining, or visibility since those in all likelihood
3389 only apply to the target.
3390 FIXME: make it possible to specify which attributes to
3391 copy or not to copy in the copy attribute itself. */
3392 tree atname = get_attribute_name (at);
3393 if (is_attribute_p (attr_name: "alias", ident: atname)
3394 || is_attribute_p (attr_name: "always_inline", ident: atname)
3395 || is_attribute_p (attr_name: "gnu_inline", ident: atname)
3396 || is_attribute_p (attr_name: "ifunc", ident: atname)
3397 || is_attribute_p (attr_name: "noinline", ident: atname)
3398 || is_attribute_p (attr_name: "visibility", ident: atname)
3399 || is_attribute_p (attr_name: "weak", ident: atname)
3400 || is_attribute_p (attr_name: "weakref", ident: atname)
3401 || is_attribute_p (attr_name: "target_clones", ident: atname))
3402 continue;
3403
3404 /* Attribute leaf only applies to extern functions.
3405 Avoid copying it to static ones. */
3406 if (!TREE_PUBLIC (decl)
3407 && is_attribute_p (attr_name: "leaf", ident: atname))
3408 continue;
3409
3410 tree atargs = TREE_VALUE (at);
3411 /* Create a copy of just the one attribute ar AT, including
3412 its argumentsm and add it to DECL. */
3413 tree attr = tree_cons (atname, copy_list (atargs), NULL_TREE);
3414 decl_attributes (node, attr, flags, EXPR_P (ref) ? NULL_TREE : ref);
3415 }
3416
3417 /* Proceed to copy type attributes below. */
3418 }
3419 else if (!TYPE_P (decl))
3420 {
3421 error_at (loc, "%qE attribute must apply to a declaration", name);
3422 return NULL_TREE;
3423 }
3424
3425 /* A function declared with attribute nothrow has the attribute
3426 attached to it, but a C++ throw() function does not. */
3427 if (TREE_NOTHROW (ref))
3428 TREE_NOTHROW (decl) = true;
3429
3430 /* Similarly, a function declared with attribute noreturn has it
3431 attached on to it, but a C11 _Noreturn function does not. */
3432 if (DECL_P (ref)
3433 && TREE_THIS_VOLATILE (ref)
3434 && FUNC_OR_METHOD_TYPE_P (reftype))
3435 TREE_THIS_VOLATILE (decl) = true;
3436
3437 if (POINTER_TYPE_P (reftype))
3438 reftype = TREE_TYPE (reftype);
3439
3440 if (!TYPE_P (reftype))
3441 return NULL_TREE;
3442
3443 tree attrs = TYPE_ATTRIBUTES (reftype);
3444
3445 /* Copy type attributes from REF to DECL. Pass in REF if it's a DECL
3446 or a type but not if it's an expression. Set ATTR_FLAG_INTERNAL
3447 since the attributes' arguments may be in their internal form. */
3448 for (tree at = attrs; at; at = TREE_CHAIN (at))
3449 decl_attributes (node, at, flags | ATTR_FLAG_INTERNAL,
3450 EXPR_P (ref) ? NULL_TREE : ref);
3451
3452 return NULL_TREE;
3453}
3454
3455/* Handle a "weakref" attribute; arguments as in struct
3456 attribute_spec.handler. */
3457
3458static tree
3459handle_weakref_attribute (tree *node, tree name, tree args,
3460 int flags, bool *no_add_attrs)
3461{
3462 tree attr = NULL_TREE;
3463
3464 /* We must ignore the attribute when it is associated with
3465 local-scoped decls, since attribute alias is ignored and many
3466 such symbols do not even have a DECL_WEAK field. */
3467 if (decl_function_context (*node)
3468 || current_function_decl
3469 || !VAR_OR_FUNCTION_DECL_P (*node))
3470 {
3471 warning (OPT_Wattributes, "%qE attribute ignored", name);
3472 *no_add_attrs = true;
3473 return NULL_TREE;
3474 }
3475
3476 if (lookup_attribute (attr_name: "ifunc", DECL_ATTRIBUTES (*node)))
3477 {
3478 error ("indirect function %q+D cannot be declared %qE",
3479 *node, name);
3480 *no_add_attrs = true;
3481 return NULL_TREE;
3482 }
3483
3484 /* The idea here is that `weakref("name")' mutates into `weakref,
3485 alias("name")', and weakref without arguments, in turn,
3486 implicitly adds weak. */
3487
3488 if (args)
3489 {
3490 attr = tree_cons (get_identifier ("alias"), args, attr);
3491 attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
3492
3493 *no_add_attrs = true;
3494
3495 decl_attributes (node, attr, flags);
3496 }
3497 else
3498 {
3499 if (lookup_attribute (attr_name: "alias", DECL_ATTRIBUTES (*node)))
3500 error_at (DECL_SOURCE_LOCATION (*node),
3501 "%qE attribute must appear before %qs attribute",
3502 name, "alias");
3503
3504 /* Can't call declare_weak because it wants this to be TREE_PUBLIC,
3505 and that isn't supported; and because it wants to add it to
3506 the list of weak decls, which isn't helpful. */
3507 DECL_WEAK (*node) = 1;
3508 }
3509
3510 if (decl_in_symtab_p (decl: *node))
3511 {
3512 struct symtab_node *n = symtab_node::get (decl: *node);
3513 if (n && n->refuse_visibility_changes)
3514 error ("%+qD declared %qE after being used", *node, name);
3515 }
3516
3517 return NULL_TREE;
3518}
3519
3520/* Handle an "visibility" attribute; arguments as in
3521 struct attribute_spec.handler. */
3522
3523static tree
3524handle_visibility_attribute (tree *node, tree name, tree args,
3525 int ARG_UNUSED (flags),
3526 bool *ARG_UNUSED (no_add_attrs))
3527{
3528 tree decl = *node;
3529 tree id = TREE_VALUE (args);
3530 enum symbol_visibility vis;
3531
3532 if (TYPE_P (*node))
3533 {
3534 if (TREE_CODE (*node) == ENUMERAL_TYPE)
3535 /* OK */;
3536 else if (!RECORD_OR_UNION_TYPE_P (*node))
3537 {
3538 warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
3539 name);
3540 return NULL_TREE;
3541 }
3542 else if (TYPE_FIELDS (*node))
3543 {
3544 error ("%qE attribute ignored because %qT is already defined",
3545 name, *node);
3546 return NULL_TREE;
3547 }
3548 }
3549 else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
3550 {
3551 warning (OPT_Wattributes, "%qE attribute ignored", name);
3552 return NULL_TREE;
3553 }
3554
3555 if (TREE_CODE (id) != STRING_CST)
3556 {
3557 error ("visibility argument not a string");
3558 return NULL_TREE;
3559 }
3560
3561 /* If this is a type, set the visibility on the type decl. */
3562 if (TYPE_P (decl))
3563 {
3564 decl = TYPE_NAME (decl);
3565 if (!decl)
3566 return NULL_TREE;
3567 if (TREE_CODE (decl) == IDENTIFIER_NODE)
3568 {
3569 warning (OPT_Wattributes, "%qE attribute ignored on types",
3570 name);
3571 return NULL_TREE;
3572 }
3573 }
3574
3575 if (strcmp (TREE_STRING_POINTER (id), s2: "default") == 0)
3576 vis = VISIBILITY_DEFAULT;
3577 else if (strcmp (TREE_STRING_POINTER (id), s2: "internal") == 0)
3578 vis = VISIBILITY_INTERNAL;
3579 else if (strcmp (TREE_STRING_POINTER (id), s2: "hidden") == 0)
3580 vis = VISIBILITY_HIDDEN;
3581 else if (strcmp (TREE_STRING_POINTER (id), s2: "protected") == 0)
3582 vis = VISIBILITY_PROTECTED;
3583 else
3584 {
3585 error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs",
3586 name, "default", "hidden", "protected", "internal");
3587 vis = VISIBILITY_DEFAULT;
3588 }
3589
3590 if (DECL_VISIBILITY_SPECIFIED (decl)
3591 && vis != DECL_VISIBILITY (decl))
3592 {
3593 tree attributes = (TYPE_P (*node)
3594 ? TYPE_ATTRIBUTES (*node)
3595 : DECL_ATTRIBUTES (decl));
3596 if (lookup_attribute (attr_name: "visibility", list: attributes))
3597 error ("%qD redeclared with different visibility", decl);
3598 else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
3599 && lookup_attribute (attr_name: "dllimport", list: attributes))
3600 error ("%qD was declared %qs which implies default visibility",
3601 decl, "dllimport");
3602 else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
3603 && lookup_attribute (attr_name: "dllexport", list: attributes))
3604 error ("%qD was declared %qs which implies default visibility",
3605 decl, "dllexport");
3606 }
3607
3608 DECL_VISIBILITY (decl) = vis;
3609 DECL_VISIBILITY_SPECIFIED (decl) = 1;
3610
3611 /* Go ahead and attach the attribute to the node as well. This is needed
3612 so we can determine whether we have VISIBILITY_DEFAULT because the
3613 visibility was not specified, or because it was explicitly overridden
3614 from the containing scope. */
3615
3616 return NULL_TREE;
3617}
3618
3619/* Handle an "tls_model" attribute; arguments as in
3620 struct attribute_spec.handler. */
3621
3622static tree
3623handle_tls_model_attribute (tree *node, tree name, tree args,
3624 int ARG_UNUSED (flags),
3625 bool *ARG_UNUSED (no_add_attrs))
3626{
3627 tree id;
3628 tree decl = *node;
3629 enum tls_model kind;
3630
3631 if (!VAR_P (decl))
3632 {
3633 warning (OPT_Wattributes, "%qE attribute ignored because %qD "
3634 "is not a variable",
3635 name, decl);
3636 return NULL_TREE;
3637 }
3638
3639 if (!DECL_THREAD_LOCAL_P (decl))
3640 {
3641 warning (OPT_Wattributes, "%qE attribute ignored because %qD does "
3642 "not have thread storage duration", name, decl);
3643 return NULL_TREE;
3644 }
3645
3646 kind = DECL_TLS_MODEL (decl);
3647 id = TREE_VALUE (args);
3648 if (TREE_CODE (id) != STRING_CST)
3649 {
3650 error ("%qE argument not a string", name);
3651 return NULL_TREE;
3652 }
3653
3654 if (!strcmp (TREE_STRING_POINTER (id), s2: "local-exec"))
3655 kind = TLS_MODEL_LOCAL_EXEC;
3656 else if (!strcmp (TREE_STRING_POINTER (id), s2: "initial-exec"))
3657 kind = TLS_MODEL_INITIAL_EXEC;
3658 else if (!strcmp (TREE_STRING_POINTER (id), s2: "local-dynamic"))
3659 kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
3660 else if (!strcmp (TREE_STRING_POINTER (id), s2: "global-dynamic"))
3661 kind = TLS_MODEL_GLOBAL_DYNAMIC;
3662 else
3663 error ("%qE argument must be one of %qs, %qs, %qs, or %qs",
3664 name,
3665 "local-exec", "initial-exec", "local-dynamic", "global-dynamic");
3666
3667 set_decl_tls_model (decl, kind);
3668 return NULL_TREE;
3669}
3670
3671/* Handle a "no_instrument_function" attribute; arguments as in
3672 struct attribute_spec.handler. */
3673
3674static tree
3675handle_no_instrument_function_attribute (tree *node, tree name,
3676 tree ARG_UNUSED (args),
3677 int ARG_UNUSED (flags),
3678 bool *no_add_attrs)
3679{
3680 tree decl = *node;
3681
3682 if (TREE_CODE (decl) != FUNCTION_DECL)
3683 {
3684 error_at (DECL_SOURCE_LOCATION (decl),
3685 "%qE attribute applies only to functions", name);
3686 *no_add_attrs = true;
3687 }
3688 else
3689 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
3690
3691 return NULL_TREE;
3692}
3693
3694/* Handle a "no_profile_instrument_function" attribute; arguments as in
3695 struct attribute_spec.handler. */
3696
3697static tree
3698handle_no_profile_instrument_function_attribute (tree *node, tree name, tree,
3699 int, bool *no_add_attrs)
3700{
3701 if (TREE_CODE (*node) != FUNCTION_DECL)
3702 {
3703 warning (OPT_Wattributes, "%qE attribute ignored", name);
3704 *no_add_attrs = true;
3705 }
3706
3707 return NULL_TREE;
3708}
3709
3710/* If ALLOC_DECL and DEALLOC_DECL are a pair of user-defined functions,
3711 if they are declared inline issue warnings and return null. Otherwise
3712 create attribute noinline, install it in ALLOC_DECL, and return it.
3713 Otherwise return null. */
3714
3715static tree
3716maybe_add_noinline (tree name, tree alloc_decl, tree dealloc_decl,
3717 bool *no_add_attrs)
3718{
3719 if (fndecl_built_in_p (node: alloc_decl) || fndecl_built_in_p (node: dealloc_decl))
3720 return NULL_TREE;
3721
3722 /* When inlining (or optimization) is enabled and the allocator and
3723 deallocator are not built-in functions, ignore the attribute on
3724 functions declared inline since it could lead to false positives
3725 when inlining one or the other call would wind up calling
3726 a mismatched allocator or deallocator. */
3727 if ((optimize && DECL_DECLARED_INLINE_P (alloc_decl))
3728 || lookup_attribute (attr_name: "always_inline", DECL_ATTRIBUTES (alloc_decl)))
3729 {
3730 warning (OPT_Wattributes,
3731 "%<%E (%E)%> attribute ignored on functions "
3732 "declared %qs", name, DECL_NAME (dealloc_decl), "inline");
3733 *no_add_attrs = true;
3734 return NULL_TREE;
3735 }
3736
3737 if ((optimize && DECL_DECLARED_INLINE_P (dealloc_decl))
3738 || lookup_attribute (attr_name: "always_inline", DECL_ATTRIBUTES (dealloc_decl)))
3739 {
3740 warning (OPT_Wattributes,
3741 "%<%E (%E)%> attribute ignored with deallocation "
3742 "functions declared %qs",
3743 name, DECL_NAME (dealloc_decl), "inline");
3744 inform (DECL_SOURCE_LOCATION (dealloc_decl),
3745 "deallocation function declared here" );
3746 *no_add_attrs = true;
3747 return NULL_TREE;
3748 }
3749
3750 /* Disable inlining for non-standard deallocators to avoid false
3751 positives due to mismatches between the inlined implementation
3752 of one and not the other pair of functions. */
3753 tree attr = tree_cons (get_identifier ("noinline"), NULL_TREE, NULL_TREE);
3754 decl_attributes (&alloc_decl, attr, 0);
3755 return attr;
3756}
3757
3758/* Handle the "malloc" attribute. */
3759
3760static tree
3761handle_malloc_attribute (tree *node, tree name, tree args, int flags,
3762 bool *no_add_attrs)
3763{
3764 if (flags & ATTR_FLAG_INTERNAL)
3765 /* Recursive call. */
3766 return NULL_TREE;
3767
3768 tree fndecl = *node;
3769
3770 if (TREE_CODE (*node) != FUNCTION_DECL)
3771 {
3772 warning (OPT_Wattributes, "%qE attribute ignored; valid only "
3773 "for functions",
3774 name);
3775 *no_add_attrs = true;
3776 return NULL_TREE;
3777 }
3778
3779 tree rettype = TREE_TYPE (TREE_TYPE (*node));
3780 if (!POINTER_TYPE_P (rettype))
3781 {
3782 warning (OPT_Wattributes, "%qE attribute ignored on functions "
3783 "returning %qT; valid only for pointer return types",
3784 name, rettype);
3785 *no_add_attrs = true;
3786 return NULL_TREE;
3787 }
3788
3789 if (!args)
3790 {
3791 /* Only the form of the attribute with no arguments declares
3792 a function malloc-like. */
3793 DECL_IS_MALLOC (*node) = 1;
3794 return NULL_TREE;
3795 }
3796
3797 tree dealloc = TREE_VALUE (args);
3798 if (error_operand_p (t: dealloc))
3799 {
3800 /* If the argument is in error it will have already been diagnosed.
3801 Avoid issuing redundant errors here. */
3802 *no_add_attrs = true;
3803 return NULL_TREE;
3804 }
3805
3806 STRIP_NOPS (dealloc);
3807 if (TREE_CODE (dealloc) == ADDR_EXPR)
3808 {
3809 /* In C++ the argument may be wrapped in a cast to disambiguate
3810 one of a number of overloads (such as operator delete). To
3811 make things interesting, the cast looks different between
3812 different C++ versions. Strip it and install the attribute
3813 with the disambiguated function. */
3814 dealloc = TREE_OPERAND (dealloc, 0);
3815
3816 *no_add_attrs = true;
3817 tree attr = tree_cons (NULL_TREE, dealloc, TREE_CHAIN (args));
3818 attr = build_tree_list (name, attr);
3819 return decl_attributes (node, attr, 0);
3820 }
3821
3822 if (TREE_CODE (dealloc) != FUNCTION_DECL)
3823 {
3824 if (TREE_CODE (dealloc) == OVERLOAD)
3825 {
3826 /* Handle specially the common case of specifying one of a number
3827 of overloads, such as operator delete. */
3828 error ("%qE attribute argument 1 is ambiguous", name);
3829 inform (input_location,
3830 "use a cast to the expected type to disambiguate");
3831 *no_add_attrs = true;
3832 return NULL_TREE;
3833 }
3834
3835 error ("%qE attribute argument 1 does not name a function", name);
3836 if (DECL_P (dealloc))
3837 inform (DECL_SOURCE_LOCATION (dealloc),
3838 "argument references a symbol declared here");
3839 *no_add_attrs = true;
3840 return NULL_TREE;
3841 }
3842
3843 /* Mentioning the deallocation function qualifies as its use. */
3844 TREE_USED (dealloc) = 1;
3845
3846 tree fntype = TREE_TYPE (dealloc);
3847 tree argpos = TREE_CHAIN (args) ? TREE_VALUE (TREE_CHAIN (args)) : NULL_TREE;
3848 if (!argpos)
3849 {
3850 tree argtypes = TYPE_ARG_TYPES (fntype);
3851 if (!argtypes)
3852 {
3853 /* Reject functions without a prototype. */
3854 error ("%qE attribute argument 1 must take a pointer "
3855 "type as its first argument", name);
3856 inform (DECL_SOURCE_LOCATION (dealloc),
3857 "referenced symbol declared here");
3858 *no_add_attrs = true;
3859 return NULL_TREE;
3860 }
3861
3862 tree argtype = TREE_VALUE (argtypes);
3863 if (TREE_CODE (argtype) != POINTER_TYPE)
3864 {
3865 /* Reject functions that don't take a pointer as their first
3866 argument. */
3867 error ("%qE attribute argument 1 must take a pointer type "
3868 "as its first argument; have %qT", name, argtype);
3869 inform (DECL_SOURCE_LOCATION (dealloc),
3870 "referenced symbol declared here");
3871 *no_add_attrs = true;
3872 return NULL_TREE;
3873 }
3874
3875 /* Disable inlining for non-standard deallocators to avoid false
3876 positives (or warn if either function is explicitly inline). */
3877 tree at_noinline =
3878 maybe_add_noinline (name, alloc_decl: fndecl, dealloc_decl: dealloc, no_add_attrs);
3879 if (*no_add_attrs)
3880 return NULL_TREE;
3881
3882 /* Add attribute *dealloc to the deallocator function associating
3883 it with this one. Ideally, the attribute would reference
3884 the DECL of the deallocator but since that changes for each
3885 redeclaration, use DECL_NAME instead. (DECL_ASSEMBLER_NAME
3886 need not be set at this point and setting it here is too early. */
3887 tree attrs = build_tree_list (NULL_TREE, DECL_NAME (fndecl));
3888 attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
3889 decl_attributes (&dealloc, attrs, 0);
3890 return NULL_TREE;
3891 }
3892
3893 /* Validate the positional argument. */
3894 argpos = positional_argument (fn: fntype, atname: name, pos&: argpos, code: POINTER_TYPE);
3895 if (!argpos)
3896 {
3897 *no_add_attrs = true;
3898 return NULL_TREE;
3899 }
3900
3901 /* As above, disable inlining for non-standard deallocators to avoid
3902 false positives (or warn). */
3903 tree at_noinline =
3904 maybe_add_noinline (name, alloc_decl: fndecl, dealloc_decl: dealloc, no_add_attrs);
3905 if (*no_add_attrs)
3906 return NULL_TREE;
3907
3908 /* It's valid to declare the same function with multiple instances
3909 of attribute malloc, each naming the same or different deallocator
3910 functions, and each referencing either the same or a different
3911 positional argument. */
3912 tree attrs = tree_cons (NULL_TREE, argpos, NULL_TREE);
3913 attrs = tree_cons (NULL_TREE, DECL_NAME (fndecl), attrs);
3914 attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
3915 decl_attributes (&dealloc, attrs, 0);
3916 return NULL_TREE;
3917}
3918
3919/* Handle the internal "*dealloc" attribute added for functions declared
3920 with the one- and two-argument forms of attribute malloc. Add it
3921 to *NODE unless it's already there with the same arguments. */
3922
3923static tree
3924handle_dealloc_attribute (tree *node, tree name, tree args, int,
3925 bool *no_add_attrs)
3926{
3927 tree fndecl = *node;
3928
3929 tree attrs = DECL_ATTRIBUTES (fndecl);
3930 if (!attrs)
3931 return NULL_TREE;
3932
3933 tree arg = TREE_VALUE (args);
3934 args = TREE_CHAIN (args);
3935 tree arg_pos = args ? TREE_VALUE (args) : integer_zero_node;
3936
3937 gcc_checking_assert ((DECL_P (arg)
3938 && fndecl_built_in_p (arg, BUILT_IN_NORMAL))
3939 || TREE_CODE (arg) == IDENTIFIER_NODE);
3940
3941 const char* const namestr = IDENTIFIER_POINTER (name);
3942 for (tree at = attrs; (at = lookup_attribute (attr_name: namestr, list: at));
3943 at = TREE_CHAIN (at))
3944 {
3945 tree alloc = TREE_VALUE (at);
3946 if (!alloc)
3947 continue;
3948
3949 tree pos = TREE_CHAIN (alloc);
3950 alloc = TREE_VALUE (alloc);
3951 pos = pos ? TREE_VALUE (pos) : integer_zero_node;
3952 gcc_checking_assert ((DECL_P (alloc)
3953 && fndecl_built_in_p (alloc, BUILT_IN_NORMAL))
3954 || TREE_CODE (alloc) == IDENTIFIER_NODE);
3955
3956 if (alloc == arg && tree_int_cst_equal (pos, arg_pos))
3957 {
3958 /* The function already has the attribute either without any
3959 arguments or with the same arguments as the attribute that's
3960 being added. Return without adding another copy. */
3961 *no_add_attrs = true;
3962 return NULL_TREE;
3963 }
3964 }
3965
3966 return NULL_TREE;
3967}
3968
3969/* Handle the "alloc_size (argpos1 [, argpos2])" function type attribute.
3970 *NODE is the type of the function the attribute is being applied to. */
3971
3972static tree
3973handle_alloc_size_attribute (tree *node, tree name, tree args,
3974 int ARG_UNUSED (flags), bool *no_add_attrs)
3975{
3976 tree fntype = *node;
3977 tree rettype = TREE_TYPE (fntype);
3978 if (!POINTER_TYPE_P (rettype))
3979 {
3980 warning (OPT_Wattributes,
3981 "%qE attribute ignored on a function returning %qT",
3982 name, rettype);
3983 *no_add_attrs = true;
3984 return NULL_TREE;
3985 }
3986
3987 tree newargs[2] = { NULL_TREE, NULL_TREE };
3988 for (int i = 1; args; ++i)
3989 {
3990 tree pos = TREE_VALUE (args);
3991 /* NEXT is null when the attribute includes just one argument.
3992 That's used to tell positional_argument to avoid mentioning
3993 the argument number in diagnostics (since there's just one
3994 mentioning it is unnecessary and coule be confusing). */
3995 tree next = TREE_CHAIN (args);
3996 if (tree val = positional_argument (fn: fntype, atname: name, pos, code: INTEGER_TYPE,
3997 argno: next || i > 1 ? i : 0))
3998 {
3999 TREE_VALUE (args) = val;
4000 newargs[i - 1] = val;
4001 }
4002 else
4003 {
4004 *no_add_attrs = true;
4005 return NULL_TREE;
4006 }
4007
4008 args = next;
4009 }
4010
4011 if (!validate_attr_args (node, name, newargs))
4012 *no_add_attrs = true;
4013
4014 return NULL_TREE;
4015}
4016
4017
4018/* Handle an "alloc_align (argpos)" attribute. */
4019
4020static tree
4021handle_alloc_align_attribute (tree *node, tree name, tree args, int,
4022 bool *no_add_attrs)
4023{
4024 tree fntype = *node;
4025 tree rettype = TREE_TYPE (fntype);
4026 if (!POINTER_TYPE_P (rettype))
4027 {
4028 warning (OPT_Wattributes,
4029 "%qE attribute ignored on a function returning %qT",
4030 name, rettype);
4031 *no_add_attrs = true;
4032 return NULL_TREE;
4033 }
4034
4035 if (tree val = positional_argument (fn: *node, atname: name, TREE_VALUE (args),
4036 code: INTEGER_TYPE))
4037 if (validate_attr_arg (node, name, newarg: val))
4038 return NULL_TREE;
4039
4040 *no_add_attrs = true;
4041 return NULL_TREE;
4042}
4043
4044/* Handle a "assume_aligned" attribute; arguments as in
4045 struct attribute_spec.handler. */
4046
4047static tree
4048handle_assume_aligned_attribute (tree *node, tree name, tree args, int,
4049 bool *no_add_attrs)
4050{
4051 tree decl = *node;
4052 tree rettype = TREE_TYPE (decl);
4053 if (TREE_CODE (rettype) != POINTER_TYPE)
4054 {
4055 warning (OPT_Wattributes,
4056 "%qE attribute ignored on a function returning %qT",
4057 name, rettype);
4058 *no_add_attrs = true;
4059 return NULL_TREE;
4060 }
4061
4062 /* The alignment specified by the first argument. */
4063 tree align = NULL_TREE;
4064
4065 for (; args; args = TREE_CHAIN (args))
4066 {
4067 tree val = TREE_VALUE (args);
4068 if (val && TREE_CODE (val) != IDENTIFIER_NODE
4069 && TREE_CODE (val) != FUNCTION_DECL)
4070 val = default_conversion (val);
4071
4072 if (!tree_fits_shwi_p (val))
4073 {
4074 warning (OPT_Wattributes,
4075 "%qE attribute argument %E is not an integer constant",
4076 name, val);
4077 *no_add_attrs = true;
4078 return NULL_TREE;
4079 }
4080 else if (tree_int_cst_sgn (val) < 0)
4081 {
4082 warning (OPT_Wattributes,
4083 "%qE attribute argument %E is not positive", name, val);
4084 *no_add_attrs = true;
4085 return NULL_TREE;
4086 }
4087
4088 if (!align)
4089 {
4090 /* Validate and save the alignment. */
4091 if (!integer_pow2p (val))
4092 {
4093 warning (OPT_Wattributes,
4094 "%qE attribute argument %E is not a power of 2",
4095 name, val);
4096 *no_add_attrs = true;
4097 return NULL_TREE;
4098 }
4099
4100 align = val;
4101 }
4102 else if (tree_int_cst_le (t1: align, t2: val))
4103 {
4104 /* The misalignment specified by the second argument
4105 must be non-negative and less than the alignment. */
4106 warning (OPT_Wattributes,
4107 "%qE attribute argument %E is not in the range [0, %wu]",
4108 name, val, tree_to_uhwi (align) - 1);
4109 *no_add_attrs = true;
4110 return NULL_TREE;
4111 }
4112 }
4113 return NULL_TREE;
4114}
4115
4116/* Handle the internal-only "arg spec" attribute. */
4117
4118static tree
4119handle_argspec_attribute (tree *, tree, tree args, int, bool *)
4120{
4121 /* Verify the attribute has one or two arguments and their kind. */
4122 gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST);
4123 for (tree next = TREE_CHAIN (args); next; next = TREE_CHAIN (next))
4124 {
4125 tree val = TREE_VALUE (next);
4126 gcc_assert (DECL_P (val) || EXPR_P (val));
4127 }
4128 return NULL_TREE;
4129}
4130
4131/* Handle the internal-only "fn spec" attribute. */
4132
4133static tree
4134handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
4135 tree args, int ARG_UNUSED (flags),
4136 bool *no_add_attrs ATTRIBUTE_UNUSED)
4137{
4138 gcc_assert (args
4139 && TREE_CODE (TREE_VALUE (args)) == STRING_CST
4140 && !TREE_CHAIN (args));
4141 return NULL_TREE;
4142}
4143
4144/* Handle a "warn_unused" attribute; arguments as in
4145 struct attribute_spec.handler. */
4146
4147static tree
4148handle_warn_unused_attribute (tree *node, tree name,
4149 tree args ATTRIBUTE_UNUSED,
4150 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
4151{
4152 if (TYPE_P (*node))
4153 /* Do nothing else, just set the attribute. We'll get at
4154 it later with lookup_attribute. */
4155 ;
4156 else
4157 {
4158 warning (OPT_Wattributes, "%qE attribute ignored", name);
4159 *no_add_attrs = true;
4160 }
4161
4162 return NULL_TREE;
4163}
4164
4165/* Handle an "omp declare simd" attribute; arguments as in
4166 struct attribute_spec.handler. */
4167
4168static tree
4169handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
4170{
4171 return NULL_TREE;
4172}
4173
4174/* Handle an "omp declare variant {base,variant}" attribute; arguments as in
4175 struct attribute_spec.handler. */
4176
4177static tree
4178handle_omp_declare_variant_attribute (tree *, tree, tree, int, bool *)
4179{
4180 return NULL_TREE;
4181}
4182
4183/* Handle a "simd" attribute. */
4184
4185static tree
4186handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs)
4187{
4188 if (TREE_CODE (*node) == FUNCTION_DECL)
4189 {
4190 tree t = get_identifier ("omp declare simd");
4191 tree attr = NULL_TREE;
4192 if (args)
4193 {
4194 tree id = TREE_VALUE (args);
4195
4196 if (TREE_CODE (id) != STRING_CST)
4197 {
4198 error ("attribute %qE argument not a string", name);
4199 *no_add_attrs = true;
4200 return NULL_TREE;
4201 }
4202
4203 if (strcmp (TREE_STRING_POINTER (id), s2: "notinbranch") == 0)
4204 attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
4205 OMP_CLAUSE_NOTINBRANCH);
4206 else if (strcmp (TREE_STRING_POINTER (id), s2: "inbranch") == 0)
4207 attr = build_omp_clause (DECL_SOURCE_LOCATION (*node),
4208 OMP_CLAUSE_INBRANCH);
4209 else
4210 {
4211 error ("only %<inbranch%> and %<notinbranch%> flags are "
4212 "allowed for %<__simd__%> attribute");
4213 *no_add_attrs = true;
4214 return NULL_TREE;
4215 }
4216 }
4217
4218 DECL_ATTRIBUTES (*node)
4219 = tree_cons (t, build_tree_list (NULL_TREE, attr),
4220 DECL_ATTRIBUTES (*node));
4221 }
4222 else
4223 {
4224 warning (OPT_Wattributes, "%qE attribute ignored", name);
4225 *no_add_attrs = true;
4226 }
4227
4228 return NULL_TREE;
4229}
4230
4231/* Handle an "omp declare target" attribute; arguments as in
4232 struct attribute_spec.handler. */
4233
4234static tree
4235handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
4236{
4237 return NULL_TREE;
4238}
4239
4240/* Handle an "non overlapping" attribute; arguments as in
4241 struct attribute_spec.handler. */
4242
4243static tree
4244handle_non_overlapping_attribute (tree *, tree, tree, int, bool *)
4245{
4246 return NULL_TREE;
4247}
4248
4249/* Handle a "returns_twice" attribute; arguments as in
4250 struct attribute_spec.handler. */
4251
4252static tree
4253handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4254 int ARG_UNUSED (flags), bool *no_add_attrs)
4255{
4256 if (TREE_CODE (*node) == FUNCTION_DECL)
4257 DECL_IS_RETURNS_TWICE (*node) = 1;
4258 else
4259 {
4260 warning (OPT_Wattributes, "%qE attribute ignored", name);
4261 *no_add_attrs = true;
4262 }
4263
4264 return NULL_TREE;
4265}
4266
4267/* Handle a "no_limit_stack" attribute; arguments as in
4268 struct attribute_spec.handler. */
4269
4270static tree
4271handle_no_limit_stack_attribute (tree *node, tree name,
4272 tree ARG_UNUSED (args),
4273 int ARG_UNUSED (flags),
4274 bool *no_add_attrs)
4275{
4276 tree decl = *node;
4277
4278 if (TREE_CODE (decl) != FUNCTION_DECL)
4279 {
4280 error_at (DECL_SOURCE_LOCATION (decl),
4281 "%qE attribute applies only to functions", name);
4282 *no_add_attrs = true;
4283 }
4284 else if (DECL_INITIAL (decl))
4285 {
4286 error_at (DECL_SOURCE_LOCATION (decl),
4287 "cannot set %qE attribute after definition", name);
4288 *no_add_attrs = true;
4289 }
4290 else
4291 DECL_NO_LIMIT_STACK (decl) = 1;
4292
4293 return NULL_TREE;
4294}
4295
4296/* Handle a "pure" attribute; arguments as in
4297 struct attribute_spec.handler. */
4298
4299static tree
4300handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4301 int ARG_UNUSED (flags), bool *no_add_attrs)
4302{
4303 if (TREE_CODE (*node) == FUNCTION_DECL)
4304 {
4305 tree type = TREE_TYPE (*node);
4306 if (VOID_TYPE_P (TREE_TYPE (type)))
4307 warning (OPT_Wattributes, "%qE attribute on function "
4308 "returning %<void%>", name);
4309
4310 DECL_PURE_P (*node) = 1;
4311 /* ??? TODO: Support types. */
4312 }
4313 else
4314 {
4315 warning (OPT_Wattributes, "%qE attribute ignored", name);
4316 *no_add_attrs = true;
4317 }
4318
4319 return NULL_TREE;
4320}
4321
4322/* Handle an "unsequenced" attribute; arguments as in
4323 struct attribute_spec.handler. */
4324
4325tree
4326handle_unsequenced_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4327 int flags, bool *no_add_attrs)
4328{
4329 tree fntype = *node;
4330 for (tree argtype = TYPE_ARG_TYPES (fntype); argtype;
4331 argtype = TREE_CHAIN (argtype))
4332 /* If any of the arguments have pointer or reference type, just
4333 add the attribute alone. */
4334 if (POINTER_TYPE_P (TREE_VALUE (argtype)))
4335 return NULL_TREE;
4336
4337 if (VOID_TYPE_P (TREE_TYPE (fntype)))
4338 warning (OPT_Wattributes, "%qE attribute on function type "
4339 "without pointer arguments returning %<void%>", name);
4340 const char *name2;
4341 if (IDENTIFIER_LENGTH (name) == sizeof ("unsequenced") - 1)
4342 name2 = "unsequenced noptr";
4343 else
4344 name2 = "reproducible noptr";
4345 if (!lookup_attribute (attr_name: name2, TYPE_ATTRIBUTES (fntype)))
4346 {
4347 *no_add_attrs = true;
4348 gcc_assert ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE) == 0);
4349 tree attr = tree_cons (get_identifier (name2), NULL_TREE,
4350 TYPE_ATTRIBUTES (fntype));
4351 if (!lookup_attribute (IDENTIFIER_POINTER (name),
4352 TYPE_ATTRIBUTES (fntype)))
4353 attr = tree_cons (name, NULL_TREE, attr);
4354 *node = build_type_attribute_variant (*node, attr);
4355 }
4356 return NULL_TREE;
4357}
4358
4359/* Handle a "reproducible" attribute; arguments as in
4360 struct attribute_spec.handler. */
4361
4362tree
4363handle_reproducible_attribute (tree *node, tree name, tree args, int flags,
4364 bool *no_add_attrs)
4365{
4366 return handle_unsequenced_attribute (node, name, args, flags, no_add_attrs);
4367}
4368
4369/* Digest an attribute list destined for a transactional memory statement.
4370 ALLOWED is the set of attributes that are allowed for this statement;
4371 return the attribute we parsed. Multiple attributes are never allowed. */
4372
4373int
4374parse_tm_stmt_attr (tree attrs, int allowed)
4375{
4376 tree a_seen = NULL;
4377 int m_seen = 0;
4378
4379 for ( ; attrs ; attrs = TREE_CHAIN (attrs))
4380 {
4381 tree a = get_attribute_name (attrs);
4382 tree ns = get_attribute_namespace (attrs);
4383 int m = 0;
4384
4385 if (is_attribute_p (attr_name: "outer", ident: a)
4386 && (ns == NULL_TREE || strcmp (IDENTIFIER_POINTER (ns), s2: "gnu") == 0))
4387 m = TM_STMT_ATTR_OUTER;
4388
4389 if ((m & allowed) == 0)
4390 {
4391 warning (OPT_Wattributes, "%qE attribute directive ignored", a);
4392 continue;
4393 }
4394
4395 if (m_seen == 0)
4396 {
4397 a_seen = a;
4398 m_seen = m;
4399 }
4400 else if (m_seen == m)
4401 warning (OPT_Wattributes, "%qE attribute duplicated", a);
4402 else
4403 warning (OPT_Wattributes, "%qE attribute follows %qE", a, a_seen);
4404 }
4405
4406 return m_seen;
4407}
4408
4409/* Transform a TM attribute name into a maskable integer and back.
4410 Note that NULL (i.e. no attribute) is mapped to UNKNOWN, corresponding
4411 to how the lack of an attribute is treated. */
4412
4413int
4414tm_attr_to_mask (tree attr)
4415{
4416 if (attr == NULL)
4417 return 0;
4418 if (is_attribute_p (attr_name: "transaction_safe", ident: attr))
4419 return TM_ATTR_SAFE;
4420 if (is_attribute_p (attr_name: "transaction_callable", ident: attr))
4421 return TM_ATTR_CALLABLE;
4422 if (is_attribute_p (attr_name: "transaction_pure", ident: attr))
4423 return TM_ATTR_PURE;
4424 if (is_attribute_p (attr_name: "transaction_unsafe", ident: attr))
4425 return TM_ATTR_IRREVOCABLE;
4426 if (is_attribute_p (attr_name: "transaction_may_cancel_outer", ident: attr))
4427 return TM_ATTR_MAY_CANCEL_OUTER;
4428 return 0;
4429}
4430
4431tree
4432tm_mask_to_attr (int mask)
4433{
4434 const char *str;
4435 switch (mask)
4436 {
4437 case TM_ATTR_SAFE:
4438 str = "transaction_safe";
4439 break;
4440 case TM_ATTR_CALLABLE:
4441 str = "transaction_callable";
4442 break;
4443 case TM_ATTR_PURE:
4444 str = "transaction_pure";
4445 break;
4446 case TM_ATTR_IRREVOCABLE:
4447 str = "transaction_unsafe";
4448 break;
4449 case TM_ATTR_MAY_CANCEL_OUTER:
4450 str = "transaction_may_cancel_outer";
4451 break;
4452 default:
4453 gcc_unreachable ();
4454 }
4455 return get_identifier (str);
4456}
4457
4458/* Return the first TM attribute seen in LIST. */
4459
4460tree
4461find_tm_attribute (tree list)
4462{
4463 for (; list ; list = TREE_CHAIN (list))
4464 {
4465 tree name = get_attribute_name (list);
4466 if (tm_attr_to_mask (attr: name) != 0)
4467 return name;
4468 }
4469 return NULL_TREE;
4470}
4471
4472/* Handle the TM attributes; arguments as in struct attribute_spec.handler.
4473 Here we accept only function types, and verify that none of the other
4474 function TM attributes are also applied. */
4475/* ??? We need to accept class types for C++, but not C. This greatly
4476 complicates this function, since we can no longer rely on the extra
4477 processing given by function_type_required. */
4478
4479static tree
4480handle_tm_attribute (tree *node, tree name, tree args,
4481 int flags, bool *no_add_attrs)
4482{
4483 /* Only one path adds the attribute; others don't. */
4484 *no_add_attrs = true;
4485
4486 switch (TREE_CODE (*node))
4487 {
4488 case RECORD_TYPE:
4489 case UNION_TYPE:
4490 /* Only tm_callable and tm_safe apply to classes. */
4491 if (tm_attr_to_mask (attr: name) & ~(TM_ATTR_SAFE | TM_ATTR_CALLABLE))
4492 goto ignored;
4493 /* FALLTHRU */
4494
4495 case FUNCTION_TYPE:
4496 case METHOD_TYPE:
4497 {
4498 tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node));
4499 if (old_name == name)
4500 ;
4501 else if (old_name != NULL_TREE)
4502 error ("type was previously declared %qE", old_name);
4503 else
4504 *no_add_attrs = false;
4505 }
4506 break;
4507
4508 case FUNCTION_DECL:
4509 {
4510 /* transaction_safe_dynamic goes on the FUNCTION_DECL, but we also
4511 want to set transaction_safe on the type. */
4512 gcc_assert (is_attribute_p ("transaction_safe_dynamic", name));
4513 if (!TYPE_P (DECL_CONTEXT (*node)))
4514 error_at (DECL_SOURCE_LOCATION (*node),
4515 "%<transaction_safe_dynamic%> may only be specified for "
4516 "a virtual function");
4517 *no_add_attrs = false;
4518 decl_attributes (&TREE_TYPE (*node),
4519 build_tree_list (get_identifier ("transaction_safe"),
4520 NULL_TREE),
4521 0);
4522 break;
4523 }
4524
4525 case POINTER_TYPE:
4526 {
4527 enum tree_code subcode = TREE_CODE (TREE_TYPE (*node));
4528 if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
4529 {
4530 tree fn_tmp = TREE_TYPE (*node);
4531 decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
4532 *node = build_pointer_type (fn_tmp);
4533 break;
4534 }
4535 }
4536 /* FALLTHRU */
4537
4538 default:
4539 /* If a function is next, pass it on to be tried next. */
4540 if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
4541 return tree_cons (name, args, NULL);
4542
4543 ignored:
4544 warning (OPT_Wattributes, "%qE attribute ignored", name);
4545 break;
4546 }
4547
4548 return NULL_TREE;
4549}
4550
4551/* Handle the TM_WRAP attribute; arguments as in
4552 struct attribute_spec.handler. */
4553
4554static tree
4555handle_tm_wrap_attribute (tree *node, tree name, tree args,
4556 int ARG_UNUSED (flags), bool *no_add_attrs)
4557{
4558 tree decl = *node;
4559
4560 /* We don't need the attribute even on success, since we
4561 record the entry in an external table. */
4562 *no_add_attrs = true;
4563
4564 if (TREE_CODE (decl) != FUNCTION_DECL)
4565 warning (OPT_Wattributes, "%qE attribute ignored", name);
4566 else
4567 {
4568 tree wrap_decl = TREE_VALUE (args);
4569 if (error_operand_p (t: wrap_decl))
4570 ;
4571 else if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
4572 && !VAR_OR_FUNCTION_DECL_P (wrap_decl))
4573 error ("%qE argument not an identifier", name);
4574 else
4575 {
4576 if (TREE_CODE (wrap_decl) == IDENTIFIER_NODE)
4577 wrap_decl = lookup_name (wrap_decl);
4578 if (wrap_decl && TREE_CODE (wrap_decl) == FUNCTION_DECL)
4579 {
4580 if (lang_hooks.types_compatible_p (TREE_TYPE (decl),
4581 TREE_TYPE (wrap_decl)))
4582 record_tm_replacement (wrap_decl, decl);
4583 else
4584 error ("%qD is not compatible with %qD", wrap_decl, decl);
4585 }
4586 else
4587 error ("%qE argument is not a function", name);
4588 }
4589 }
4590
4591 return NULL_TREE;
4592}
4593
4594/* Ignore the given attribute. Used when this attribute may be usefully
4595 overridden by the target, but is not used generically. */
4596
4597static tree
4598ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
4599 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4600 bool *no_add_attrs)
4601{
4602 *no_add_attrs = true;
4603 return NULL_TREE;
4604}
4605
4606/* Handle a "no vops" attribute; arguments as in
4607 struct attribute_spec.handler. */
4608
4609static tree
4610handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
4611 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4612 bool *ARG_UNUSED (no_add_attrs))
4613{
4614 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
4615 DECL_IS_NOVOPS (*node) = 1;
4616 return NULL_TREE;
4617}
4618
4619/* Handle a "deprecated" attribute; arguments as in
4620 struct attribute_spec.handler. */
4621
4622tree
4623handle_deprecated_attribute (tree *node, tree name,
4624 tree args, int flags,
4625 bool *no_add_attrs)
4626{
4627 tree type = NULL_TREE;
4628 int warn = 0;
4629 tree what = NULL_TREE;
4630
4631 if (!args)
4632 *no_add_attrs = true;
4633 else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
4634 {
4635 error ("deprecated message is not a string");
4636 *no_add_attrs = true;
4637 }
4638
4639 if (DECL_P (*node))
4640 {
4641 tree decl = *node;
4642 type = TREE_TYPE (decl);
4643
4644 if (TREE_CODE (decl) == TYPE_DECL
4645 || TREE_CODE (decl) == PARM_DECL
4646 || VAR_OR_FUNCTION_DECL_P (decl)
4647 || TREE_CODE (decl) == FIELD_DECL
4648 || TREE_CODE (decl) == CONST_DECL
4649 || objc_method_decl (TREE_CODE (decl))
4650 || TREE_CODE (decl) == CONCEPT_DECL)
4651 TREE_DEPRECATED (decl) = 1;
4652 else if (TREE_CODE (decl) == LABEL_DECL)
4653 {
4654 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
4655 name);
4656 *no_add_attrs = true;
4657 return NULL_TREE;
4658 }
4659 else
4660 warn = 1;
4661 }
4662 else if (TYPE_P (*node))
4663 {
4664 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
4665 *node = build_variant_type_copy (*node);
4666 TREE_DEPRECATED (*node) = 1;
4667 type = *node;
4668 }
4669 else
4670 warn = 1;
4671
4672 if (warn)
4673 {
4674 *no_add_attrs = true;
4675 if (type && TYPE_NAME (type))
4676 {
4677 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4678 what = TYPE_NAME (type);
4679 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4680 && DECL_NAME (TYPE_NAME (type)))
4681 what = DECL_NAME (TYPE_NAME (type));
4682 }
4683 if (what)
4684 warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
4685 else
4686 warning (OPT_Wattributes, "%qE attribute ignored", name);
4687 }
4688
4689 return NULL_TREE;
4690}
4691
4692/* Handle a "unavailable" attribute; arguments as in
4693 struct attribute_spec.handler. */
4694
4695static tree
4696handle_unavailable_attribute (tree *node, tree name,
4697 tree args, int flags,
4698 bool *no_add_attrs)
4699{
4700 tree type = NULL_TREE;
4701 int warn = 0;
4702 tree what = NULL_TREE;
4703
4704 if (!args)
4705 *no_add_attrs = true;
4706 else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
4707 {
4708 error ("the message attached to %<unavailable%> is not a string");
4709 *no_add_attrs = true;
4710 }
4711
4712 if (DECL_P (*node))
4713 {
4714 tree decl = *node;
4715 type = TREE_TYPE (decl);
4716
4717 if (TREE_CODE (decl) == TYPE_DECL
4718 || TREE_CODE (decl) == PARM_DECL
4719 || VAR_OR_FUNCTION_DECL_P (decl)
4720 || TREE_CODE (decl) == FIELD_DECL
4721 || TREE_CODE (decl) == CONST_DECL
4722 || objc_method_decl (TREE_CODE (decl)))
4723 TREE_UNAVAILABLE (decl) = 1;
4724 else
4725 warn = 1;
4726 }
4727 else if (TYPE_P (*node))
4728 {
4729 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
4730 *node = build_variant_type_copy (*node);
4731 TREE_UNAVAILABLE (*node) = 1;
4732 type = *node;
4733 }
4734 else
4735 warn = 1;
4736
4737 if (warn)
4738 {
4739 *no_add_attrs = true;
4740 if (type && TYPE_NAME (type))
4741 {
4742 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4743 what = TYPE_NAME (*node);
4744 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4745 && DECL_NAME (TYPE_NAME (type)))
4746 what = DECL_NAME (TYPE_NAME (type));
4747 }
4748 if (what)
4749 warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
4750 else
4751 warning (OPT_Wattributes, "%qE attribute ignored", name);
4752 }
4753
4754 return NULL_TREE;
4755}
4756
4757/* Return the "base" type from TYPE that is suitable to apply attribute
4758 vector_size to by stripping arrays, function types, etc. */
4759static tree
4760type_for_vector_size (tree type)
4761{
4762 /* We need to provide for vector pointers, vector arrays, and
4763 functions returning vectors. For example:
4764
4765 __attribute__((vector_size(16))) short *foo;
4766
4767 In this case, the mode is SI, but the type being modified is
4768 HI, so we need to look further. */
4769
4770 while (POINTER_TYPE_P (type)
4771 || TREE_CODE (type) == FUNCTION_TYPE
4772 || TREE_CODE (type) == METHOD_TYPE
4773 || TREE_CODE (type) == ARRAY_TYPE
4774 || TREE_CODE (type) == OFFSET_TYPE)
4775 type = TREE_TYPE (type);
4776
4777 return type;
4778}
4779
4780/* Given TYPE, return the base type to which the vector_size attribute
4781 ATNAME with ARGS, when non-null, can be applied, if one exists.
4782 On success and when both ARGS and PTRNUNITS are non-null, set
4783 *PTRNUNINTS to the number of vector units. When PTRNUNITS is not
4784 null, issue a warning when the attribute argument is not constant
4785 and an error if there is no such type. Otherwise issue a warning
4786 in the latter case and return null. */
4787
4788static tree
4789type_valid_for_vector_size (tree type, tree atname, tree args,
4790 unsigned HOST_WIDE_INT *ptrnunits)
4791{
4792 bool hardbool_p = c_hardbool_type_attr (type);
4793 bool error_p = ptrnunits != NULL || hardbool_p;
4794
4795 /* Get the mode of the type being modified. */
4796 machine_mode orig_mode = TYPE_MODE (type);
4797
4798 if ((!INTEGRAL_TYPE_P (type)
4799 && !SCALAR_FLOAT_TYPE_P (type)
4800 && !FIXED_POINT_TYPE_P (type))
4801 || (!SCALAR_FLOAT_MODE_P (orig_mode)
4802 && GET_MODE_CLASS (orig_mode) != MODE_INT
4803 && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
4804 || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
4805 || TREE_CODE (type) == BOOLEAN_TYPE
4806 || hardbool_p
4807 || TREE_CODE (type) == BITINT_TYPE)
4808 {
4809 if (error_p)
4810 error ("invalid vector type for attribute %qE", atname);
4811 else
4812 warning (OPT_Wattributes, "invalid vector type for attribute %qE",
4813 atname);
4814 return NULL_TREE;
4815 }
4816
4817 /* When no argument has been provided this is just a request to validate
4818 the type above. Return TYPE to indicate success. */
4819 if (!args)
4820 return type;
4821
4822 tree size = TREE_VALUE (args);
4823 /* Erroneous arguments have already been diagnosed. */
4824 if (size == error_mark_node)
4825 return NULL_TREE;
4826
4827 if (size && TREE_CODE (size) != IDENTIFIER_NODE
4828 && TREE_CODE (size) != FUNCTION_DECL)
4829 size = default_conversion (size);
4830
4831 if (TREE_CODE (size) != INTEGER_CST)
4832 {
4833 if (error_p)
4834 error ("%qE attribute argument value %qE is not an integer constant",
4835 atname, size);
4836 else
4837 warning (OPT_Wattributes,
4838 "%qE attribute argument value %qE is not an integer constant",
4839 atname, size);
4840 return NULL_TREE;
4841 }
4842
4843 if (!TYPE_UNSIGNED (TREE_TYPE (size))
4844 && tree_int_cst_sgn (size) < 0)
4845 {
4846 if (error_p)
4847 error ("%qE attribute argument value %qE is negative",
4848 atname, size);
4849 else
4850 warning (OPT_Wattributes,
4851 "%qE attribute argument value %qE is negative",
4852 atname, size);
4853 return NULL_TREE;
4854 }
4855
4856 /* The attribute argument value is constrained by the maximum bit
4857 alignment representable in unsigned int on the host. */
4858 unsigned HOST_WIDE_INT vecsize;
4859 unsigned HOST_WIDE_INT maxsize = tree_to_uhwi (max_object_size ());
4860 if (!tree_fits_uhwi_p (size)
4861 || (vecsize = tree_to_uhwi (size)) > maxsize)
4862 {
4863 if (error_p)
4864 error ("%qE attribute argument value %qE exceeds %wu",
4865 atname, size, maxsize);
4866 else
4867 warning (OPT_Wattributes,
4868 "%qE attribute argument value %qE exceeds %wu",
4869 atname, size, maxsize);
4870 return NULL_TREE;
4871 }
4872
4873 if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
4874 {
4875 if (error_p)
4876 error ("vector size not an integral multiple of component size");
4877 return NULL_TREE;
4878 }
4879
4880 if (vecsize == 0)
4881 {
4882 error ("zero vector size");
4883 return NULL;
4884 }
4885
4886 /* Calculate how many units fit in the vector. */
4887 unsigned HOST_WIDE_INT nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
4888 if (nunits & (nunits - 1))
4889 {
4890 if (error_p)
4891 error ("number of vector components %wu not a power of two", nunits);
4892 else
4893 warning (OPT_Wattributes,
4894 "number of vector components %wu not a power of two", nunits);
4895 return NULL_TREE;
4896 }
4897
4898 if (nunits >= (unsigned HOST_WIDE_INT)INT_MAX)
4899 {
4900 if (error_p)
4901 error ("number of vector components %wu exceeds %d",
4902 nunits, INT_MAX - 1);
4903 else
4904 warning (OPT_Wattributes,
4905 "number of vector components %wu exceeds %d",
4906 nunits, INT_MAX - 1);
4907 return NULL_TREE;
4908 }
4909
4910 if (ptrnunits)
4911 *ptrnunits = nunits;
4912
4913 return type;
4914}
4915
4916/* Handle a "vector_size" attribute; arguments as in
4917 struct attribute_spec.handler. */
4918
4919static tree
4920handle_vector_size_attribute (tree *node, tree name, tree args,
4921 int ARG_UNUSED (flags),
4922 bool *no_add_attrs)
4923{
4924 *no_add_attrs = true;
4925
4926 /* Determine the "base" type to apply the attribute to. */
4927 tree type = type_for_vector_size (type: *node);
4928
4929 /* Get the vector size (in bytes) and let the function compute
4930 the number of vector units. */
4931 unsigned HOST_WIDE_INT nunits;
4932 type = type_valid_for_vector_size (type, atname: name, args, ptrnunits: &nunits);
4933 if (!type)
4934 return NULL_TREE;
4935
4936 gcc_checking_assert (args != NULL);
4937
4938 tree new_type = build_vector_type (type, nunits);
4939
4940 /* Build back pointers if needed. */
4941 *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
4942
4943 return NULL_TREE;
4944}
4945
4946/* Handle a "vector_mask" attribute; arguments as in
4947 struct attribute_spec.handler. */
4948
4949static tree
4950handle_vector_mask_attribute (tree *node, tree name, tree,
4951 int ARG_UNUSED (flags),
4952 bool *no_add_attrs)
4953{
4954 *no_add_attrs = true;
4955 if (!flag_gimple)
4956 {
4957 warning (OPT_Wattributes, "%qE attribute ignored", name);
4958 return NULL_TREE;
4959 }
4960
4961 /* Determine the "base" type to apply the attribute to. */
4962 tree type = type_for_vector_size (type: *node);
4963 if (!VECTOR_TYPE_P (type) || VECTOR_BOOLEAN_TYPE_P (type))
4964 {
4965 warning (OPT_Wattributes, "%qE attribute only supported on "
4966 "non-mask vector types", name);
4967 return NULL_TREE;
4968 }
4969
4970 tree new_type = truth_type_for (type);
4971
4972 /* Build back pointers if needed. */
4973 *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
4974
4975 return NULL_TREE;
4976}
4977
4978/* Handle the "nonnull" attribute. */
4979
4980static tree
4981handle_nonnull_attribute (tree *node, tree name,
4982 tree args, int ARG_UNUSED (flags),
4983 bool *no_add_attrs)
4984{
4985 tree type = *node;
4986
4987 /* If no arguments are specified, all pointer arguments should be
4988 non-null. Verify a full prototype is given so that the arguments
4989 will have the correct types when we actually check them later.
4990 Avoid diagnosing type-generic built-ins since those have no
4991 prototype. */
4992 if (!args)
4993 {
4994 if (!prototype_p (type)
4995 && (!TYPE_ATTRIBUTES (type)
4996 || !lookup_attribute (attr_name: "type generic", TYPE_ATTRIBUTES (type))))
4997 {
4998 error ("%qE attribute without arguments on a non-prototype",
4999 name);
5000 *no_add_attrs = true;
5001 }
5002 return NULL_TREE;
5003 }
5004
5005 for (int i = 1; args; ++i)
5006 {
5007 tree pos = TREE_VALUE (args);
5008 /* NEXT is null when the attribute includes just one argument.
5009 That's used to tell positional_argument to avoid mentioning
5010 the argument number in diagnostics (since there's just one
5011 mentioning it is unnecessary and could be confusing). */
5012 tree next = TREE_CHAIN (args);
5013 if (tree val = positional_argument (fn: type, atname: name, pos, code: POINTER_TYPE,
5014 argno: next || i > 1 ? i : 0))
5015 TREE_VALUE (args) = val;
5016 else
5017 {
5018 *no_add_attrs = true;
5019 break;
5020 }
5021 args = next;
5022 }
5023
5024 return NULL_TREE;
5025}
5026
5027/* Handle the "nonnull_if_nonzero" attribute. */
5028
5029static tree
5030handle_nonnull_if_nonzero_attribute (tree *node, tree name,
5031 tree args, int ARG_UNUSED (flags),
5032 bool *no_add_attrs)
5033{
5034 tree type = *node;
5035 tree pos = TREE_VALUE (args);
5036 tree pos2 = TREE_VALUE (TREE_CHAIN (args));
5037 tree val = positional_argument (fn: type, atname: name, pos, code: POINTER_TYPE, argno: 1);
5038 tree val2 = positional_argument (fn: type, atname: name, pos&: pos2, code: INTEGER_TYPE, argno: 2);
5039 if (val && val2)
5040 {
5041 TREE_VALUE (args) = val;
5042 TREE_VALUE (TREE_CHAIN (args)) = val2;
5043 }
5044 else
5045 *no_add_attrs = true;
5046
5047 return NULL_TREE;
5048}
5049
5050/* Handle the "fd_arg", "fd_arg_read" and "fd_arg_write" attributes */
5051
5052static tree
5053handle_fd_arg_attribute (tree *node, tree name, tree args,
5054 int ARG_UNUSED (flags), bool *no_add_attrs)
5055{
5056 tree type = *node;
5057 if (!args)
5058 {
5059 if (!prototype_p (type))
5060 {
5061 error ("%qE attribute without arguments on a non-prototype", name);
5062 *no_add_attrs = true;
5063 }
5064 return NULL_TREE;
5065 }
5066
5067 if (positional_argument (fn: *node, atname: name, TREE_VALUE (args), code: INTEGER_TYPE))
5068 return NULL_TREE;
5069
5070 *no_add_attrs = true;
5071 return NULL_TREE;
5072}
5073
5074/* Handle the "flag_enum" attribute. */
5075
5076static tree
5077handle_flag_enum_attribute (tree *node, tree ARG_UNUSED (name),
5078 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
5079 bool *no_add_attrs)
5080{
5081 if (TREE_CODE (*node) != ENUMERAL_TYPE)
5082 {
5083 warning (OPT_Wattributes, "%qE attribute ignored on non-enum", name);
5084 *no_add_attrs = true;
5085 }
5086
5087 return NULL_TREE;
5088}
5089
5090/* Handle the "null_terminated_string_arg" attribute. */
5091
5092static tree
5093handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args,
5094 int ARG_UNUSED (flags),
5095 bool *no_add_attrs)
5096{
5097 if (positional_argument (fn: *node, atname: name, TREE_VALUE (args), code: POINTER_TYPE))
5098 return NULL_TREE;
5099
5100 *no_add_attrs = true;
5101 return NULL_TREE;
5102}
5103
5104/* Handle the "nonstring" variable attribute. */
5105
5106static tree
5107handle_nonstring_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5108 int ARG_UNUSED (flags), bool *no_add_attrs)
5109{
5110 gcc_assert (!args);
5111 tree_code code = TREE_CODE (*node);
5112
5113 if (VAR_P (*node)
5114 || code == FIELD_DECL
5115 || code == PARM_DECL)
5116 {
5117 tree type = TREE_TYPE (*node);
5118
5119 if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
5120 {
5121 /* Accept the attribute on arrays and pointers to all three
5122 narrow character types, including multi-dimensional arrays
5123 or pointers to them. */
5124 tree eltype = strip_array_types (TREE_TYPE (type));
5125 eltype = TYPE_MAIN_VARIANT (eltype);
5126 if (eltype == char_type_node
5127 || eltype == signed_char_type_node
5128 || eltype == unsigned_char_type_node)
5129 return NULL_TREE;
5130 }
5131
5132 warning (OPT_Wattributes,
5133 "%qE attribute ignored on objects of type %qT",
5134 name, type);
5135 *no_add_attrs = true;
5136 return NULL_TREE;
5137 }
5138
5139 if (code == FUNCTION_DECL)
5140 warning (OPT_Wattributes,
5141 "%qE attribute does not apply to functions", name);
5142 else if (code == TYPE_DECL)
5143 warning (OPT_Wattributes,
5144 "%qE attribute does not apply to types", name);
5145 else
5146 warning (OPT_Wattributes, "%qE attribute ignored", name);
5147
5148 *no_add_attrs = true;
5149 return NULL_TREE;
5150}
5151
5152/* Given a function type FUNCTYPE, returns the type of the parameter
5153 ARGNO or null if ARGNO exceeds the number of parameters. On failure
5154 set *NARGS to the number of function parameters. */
5155
5156static tree
5157get_argument_type (tree functype, unsigned argno, unsigned *nargs)
5158{
5159 function_args_iterator iter;
5160 function_args_iter_init (i: &iter, fntype: functype);
5161
5162 unsigned count = 0;
5163
5164 for ( ; iter.next; ++count, function_args_iter_next (i: &iter))
5165 {
5166 if (count + 1 == argno)
5167 {
5168 tree argtype = function_args_iter_cond (i: &iter);
5169 if (VOID_TYPE_P (argtype))
5170 break;
5171 if (argtype != error_mark_node)
5172 return argtype;
5173 }
5174 }
5175
5176 *nargs = count;
5177 return NULL_TREE;
5178}
5179
5180/* Given a function FNDECL return the function argument at the zero-
5181 based position ARGNO or null if it can't be found. */
5182
5183static tree
5184get_argument (tree fndecl, unsigned argno)
5185{
5186 if (!DECL_P (fndecl))
5187 return NULL_TREE;
5188
5189 unsigned i = 0;
5190 for (tree arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
5191 if (i++ == argno)
5192 return arg;
5193
5194 return NULL_TREE;
5195}
5196
5197/* Attempt to append attribute access specification ATTRSPEC, optionally
5198 described by the human-readable string ATTRSTR, for type T, to one in
5199 ATTRS. VBLIST is an optional list of bounds of variable length array
5200 parameters described by ATTRSTR.
5201 Issue warning for conflicts and return null if any are found.
5202 Return the concatenated access string on success. */
5203
5204static tree
5205append_access_attr (tree node[3], tree attrs, const char *attrstr,
5206 const char *attrspec, tree vblist = NULL_TREE)
5207{
5208 tree argstr = build_string (strlen (s: attrspec) + 1, attrspec);
5209 tree ataccess = tree_cons (NULL_TREE, argstr, vblist);
5210 ataccess = tree_cons (get_identifier ("access"), ataccess, NULL_TREE);
5211
5212 /* The access specification being applied. This may be an implicit
5213 access spec synthesized for array (or VLA) parameters even for
5214 a declaration with an explicit access spec already applied, if
5215 this call corresponds to the first declaration of the function. */
5216 rdwr_map new_idxs;
5217 init_attr_rdwr_indices (&new_idxs, ataccess);
5218
5219 /* The current access specification alrady applied. */
5220 rdwr_map cur_idxs;
5221 init_attr_rdwr_indices (&cur_idxs, attrs);
5222
5223 tree args = TYPE_ARG_TYPES (node[0]);
5224 int argpos = 0;
5225 std::string spec;
5226 for (tree arg = args; arg; arg = TREE_CHAIN (arg), argpos++)
5227 {
5228 const attr_access* const newa = new_idxs.get (k: argpos);
5229
5230 if (!newa)
5231 continue;
5232
5233 /* The map has two equal entries for each pointer argument that
5234 has an associated size argument. Process just the entry for
5235 the former. */
5236 if ((unsigned)argpos != newa->ptrarg)
5237 continue;
5238
5239 const attr_access* const cura = cur_idxs.get (k: argpos);
5240 if (!cura)
5241 {
5242 /* The new attribute needs to be added. */
5243 tree str = newa->to_internal_string ();
5244 spec += TREE_STRING_POINTER (str);
5245 continue;
5246 }
5247
5248 /* The new access spec refers to an array/pointer argument for
5249 which an access spec already exists. Check and diagnose any
5250 conflicts. If no conflicts are found, merge the two. */
5251
5252 if (!attrstr)
5253 {
5254 tree str = NULL_TREE;
5255 if (newa->mode != access_deferred)
5256 str = newa->to_external_string ();
5257 else if (cura->mode != access_deferred)
5258 str = cura->to_external_string ();
5259 if (str)
5260 attrstr = TREE_STRING_POINTER (str);
5261 }
5262
5263 location_t curloc = input_location;
5264 if (node[2] && DECL_P (node[2]))
5265 curloc = DECL_SOURCE_LOCATION (node[2]);
5266
5267 location_t prevloc = UNKNOWN_LOCATION;
5268 if (node[1] && DECL_P (node[1]))
5269 prevloc = DECL_SOURCE_LOCATION (node[1]);
5270
5271 if (newa->mode != cura->mode
5272 && newa->mode != access_deferred
5273 && cura->mode != access_deferred
5274 && newa->internal_p == cura->internal_p)
5275 {
5276 /* Mismatch in access mode. */
5277 auto_diagnostic_group d;
5278 if (warning_at (curloc, OPT_Wattributes,
5279 "attribute %qs mismatch with mode %qs",
5280 attrstr, cura->mode_names[cura->mode])
5281 && prevloc != UNKNOWN_LOCATION)
5282 inform (prevloc, "previous declaration here");
5283 continue;
5284 }
5285
5286 /* Set if PTRARG refers to a VLA with an unspecified bound (T[*]).
5287 Be prepared for either CURA or NEWA to refer to it, depending
5288 on which happens to come first in the declaration. */
5289 const bool cur_vla_ub = (cura->internal_p
5290 && cura->sizarg == UINT_MAX
5291 && cura->minsize == HOST_WIDE_INT_M1U);
5292 const bool new_vla_ub = (newa->internal_p
5293 && newa->sizarg == UINT_MAX
5294 && newa->minsize == HOST_WIDE_INT_M1U);
5295
5296 if (newa->sizarg != cura->sizarg
5297 && attrstr
5298 && (!(cur_vla_ub ^ new_vla_ub)
5299 || (!cura->internal_p && !newa->internal_p)))
5300 {
5301 /* Avoid diagnosing redeclarations of functions with no explicit
5302 attribute access that add one. */
5303 if (newa->mode == access_deferred
5304 && cura->mode != access_deferred
5305 && newa->sizarg == UINT_MAX
5306 && cura->sizarg != UINT_MAX)
5307 continue;
5308
5309 if (cura->mode == access_deferred
5310 && newa->mode != access_deferred
5311 && cura->sizarg == UINT_MAX
5312 && newa->sizarg != UINT_MAX)
5313 continue;
5314
5315 /* The two specs designate different size arguments. It's okay
5316 for the explicit spec to specify a size where none is provided
5317 by the implicit (VLA) one, as in:
5318 __attribute__ ((access (read_write, 1, 2)))
5319 void f (int*, int);
5320 but not for two explicit access attributes to do that. */
5321 bool warned = false;
5322
5323 auto_diagnostic_group d;
5324
5325 if (newa->sizarg == UINT_MAX)
5326 /* Mismatch in the presence of the size argument. */
5327 warned = warning_at (curloc, OPT_Wattributes,
5328 "attribute %qs missing positional argument 2 "
5329 "provided in previous designation by argument "
5330 "%u", attrstr, cura->sizarg + 1);
5331 else if (cura->sizarg == UINT_MAX)
5332 /* Mismatch in the presence of the size argument. */
5333 warned = warning_at (curloc, OPT_Wattributes,
5334 "attribute %qs positional argument 2 "
5335 "missing in previous designation",
5336 attrstr);
5337 else if (newa->internal_p || cura->internal_p)
5338 /* Mismatch in the value of the size argument and a VLA bound. */
5339 warned = warning_at (curloc, OPT_Wattributes,
5340 "attribute %qs positional argument 2 "
5341 "conflicts with previous designation "
5342 "by argument %u",
5343 attrstr, cura->sizarg + 1);
5344 else
5345 /* Mismatch in the value of the size argument between two
5346 explicit access attributes. */
5347 warned = warning_at (curloc, OPT_Wattributes,
5348 "attribute %qs mismatched positional argument "
5349 "values %i and %i",
5350 attrstr, newa->sizarg + 1, cura->sizarg + 1);
5351
5352 if (warned)
5353 {
5354 /* If the previous declaration is a function (as opposed
5355 to a typedef of one), find the location of the array
5356 or pointer argument that uses the conflicting VLA bound
5357 and point to it in the note. */
5358 const attr_access* const pa = cura->size ? cura : newa;
5359 tree size = pa->size ? TREE_VALUE (pa->size) : NULL_TREE;
5360 if (size && DECL_P (size))
5361 {
5362 location_t argloc = UNKNOWN_LOCATION;
5363 if (tree arg = get_argument (fndecl: node[2], argno: pa->ptrarg))
5364 argloc = DECL_SOURCE_LOCATION (arg);
5365
5366 gcc_rich_location richloc (DECL_SOURCE_LOCATION (size));
5367 if (argloc != UNKNOWN_LOCATION)
5368 richloc.add_range (loc: argloc);
5369
5370 inform (&richloc, "designating the bound of variable "
5371 "length array argument %u",
5372 pa->ptrarg + 1);
5373 }
5374 else if (prevloc != UNKNOWN_LOCATION)
5375 inform (prevloc, "previous declaration here");
5376 }
5377
5378 continue;
5379 }
5380
5381 if (newa->internal_p == cura->internal_p)
5382 continue;
5383
5384 /* Merge the CURA and NEWA. */
5385 attr_access merged = *newa;
5386
5387 /* VLA seen in a declaration takes precedence. */
5388 if (cura->minsize == HOST_WIDE_INT_M1U)
5389 merged.minsize = HOST_WIDE_INT_M1U;
5390
5391 /* Use the explicitly specified size positional argument. */
5392 if (cura->sizarg != UINT_MAX)
5393 merged.sizarg = cura->sizarg;
5394
5395 /* Use the explicitly specified mode. */
5396 if (merged.mode == access_deferred)
5397 merged.mode = cura->mode;
5398
5399 tree str = merged.to_internal_string ();
5400 spec += TREE_STRING_POINTER (str);
5401 }
5402
5403 if (!spec.length ())
5404 return NULL_TREE;
5405
5406 return build_string (spec.length (), spec.c_str ());
5407}
5408
5409/* Convenience wrapper for the above. */
5410
5411static tree
5412append_access_attr_idxs (tree node[3], tree attrs, const char *attrstr,
5413 char code, HOST_WIDE_INT idxs[2])
5414{
5415 char attrspec[80];
5416 int n = sprintf (s: attrspec, format: "%c%u", code, (unsigned) idxs[0] - 1);
5417 if (idxs[1])
5418 n += sprintf (s: attrspec + n, format: ",%u", (unsigned) idxs[1] - 1);
5419
5420 return append_access_attr (node, attrs, attrstr, attrspec);
5421}
5422
5423/* Handle the access attribute for function type NODE[0], with the function
5424 DECL optionally in NODE[1]. The handler is called both in response to
5425 an explict attribute access on a declaration with a mode and one or two
5426 positional arguments, and for internally synthesized access specifications
5427 with a string argument optionally followd by a DECL or expression
5428 representing a VLA bound. To speed up parsing, the handler transforms
5429 the attribute and its arguments into a string. */
5430
5431static tree
5432handle_access_attribute (tree node[3], tree name, tree args, int flags,
5433 bool *no_add_attrs)
5434{
5435 tree attrs = TYPE_ATTRIBUTES (*node);
5436 tree type = *node;
5437 if (POINTER_TYPE_P (type))
5438 {
5439 tree ptype = TREE_TYPE (type);
5440 if (FUNC_OR_METHOD_TYPE_P (ptype))
5441 type = ptype;
5442 }
5443
5444 *no_add_attrs = true;
5445
5446 /* Verify a full prototype is provided so that the argument types
5447 can be validated. Avoid diagnosing type-generic built-ins since
5448 those have no prototype. */
5449 if (!args
5450 && !prototype_p (type)
5451 && (!attrs || !lookup_attribute (attr_name: "type generic", list: attrs)))
5452 {
5453 error ("attribute %qE without arguments on a non-prototype", name);
5454 return NULL_TREE;
5455 }
5456
5457 tree access_mode = TREE_VALUE (args);
5458 if (TREE_CODE (access_mode) == STRING_CST)
5459 {
5460 const char* const str = TREE_STRING_POINTER (access_mode);
5461 if (*str == '+')
5462 {
5463 /* This is a request to merge an internal specification for
5464 a function declaration involving arrays but no explicit
5465 attribute access. */
5466 tree vblist = TREE_CHAIN (args);
5467 tree axstr = append_access_attr (node, attrs, NULL, attrspec: str + 1,
5468 vblist);
5469 if (!axstr)
5470 return NULL_TREE;
5471
5472 /* Replace any existing access attribute specification with
5473 the concatenation above. */
5474 tree axsat = tree_cons (NULL_TREE, axstr, vblist);
5475 axsat = tree_cons (name, axsat, NULL_TREE);
5476
5477 /* Recursively call self to "replace" the documented/external
5478 form of the attribute with the condensend internal form. */
5479 decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL);
5480 return NULL_TREE;
5481 }
5482
5483 if (flags & ATTR_FLAG_INTERNAL)
5484 {
5485 /* This is a recursive call to handle the condensed internal
5486 form of the attribute (see below). Since all validation
5487 has been done simply return here, accepting the attribute
5488 as is. */
5489 *no_add_attrs = false;
5490 return NULL_TREE;
5491 }
5492 }
5493
5494 /* Set to true when the access mode has the form of a function call
5495 as in 'attribute (read_only (1, 2))'. That's an easy mistake to
5496 make and so worth a special diagnostic. */
5497 bool funcall = false;
5498 if (TREE_CODE (access_mode) == CALL_EXPR)
5499 {
5500 access_mode = CALL_EXPR_FN (access_mode);
5501 if (TREE_CODE (access_mode) != ADDR_EXPR)
5502 {
5503 error ("attribute %qE invalid mode", name);
5504 return NULL_TREE;
5505 }
5506 access_mode = TREE_OPERAND (access_mode, 0);
5507 access_mode = DECL_NAME (access_mode);
5508 funcall = true;
5509 }
5510 else if (TREE_CODE (access_mode) != IDENTIFIER_NODE)
5511 {
5512 error ("attribute %qE mode %qE is not an identifier; expected one of "
5513 "%qs, %qs, %qs, or %qs", name, access_mode,
5514 "read_only", "read_write", "write_only", "none");
5515 return NULL_TREE;
5516 }
5517
5518 const char* const access_str = IDENTIFIER_POINTER (access_mode);
5519 const char *ps = access_str;
5520 if (ps[0] == '_' && ps[1] == '_')
5521 {
5522 size_t len = strlen (s: ps);
5523 if (ps[len - 1] == '_' && ps[len - 2] == '_')
5524 ps += 2;
5525 }
5526
5527 int imode;
5528
5529 {
5530 const int nmodes = ARRAY_SIZE (attr_access::mode_names);
5531
5532 for (imode = 0; imode != nmodes; ++imode)
5533 if (!strncmp (s1: ps, s2: attr_access::mode_names[imode],
5534 n: strlen (s: attr_access::mode_names[imode])))
5535 break;
5536
5537 if (imode == nmodes)
5538 {
5539 error ("attribute %qE invalid mode %qs; expected one of "
5540 "%qs, %qs, %qs, or %qs", name, access_str,
5541 "read_only", "read_write", "write_only", "none");
5542 return NULL_TREE;
5543 }
5544 }
5545
5546 const ::access_mode mode = static_cast<::access_mode>(imode);
5547
5548 if (funcall)
5549 {
5550 error ("attribute %qE unexpected %<(%> after mode %qs; expected "
5551 "a positional argument or %<)%>",
5552 name, access_str);
5553 return NULL_TREE;
5554 }
5555
5556 args = TREE_CHAIN (args);
5557 if (!args)
5558 {
5559 /* The first positional argument is required. It may be worth
5560 dropping the requirement at some point and having read_only
5561 apply to all const-qualified pointers and read_write or
5562 write_only to the rest. */
5563 error ("attribute %<%E(%s)%> missing an argument",
5564 name, access_str);
5565 return NULL_TREE;
5566 }
5567
5568 /* One or more positional arguments have been specified. Validate
5569 them. */
5570 tree idxnodes[2] = { NULL_TREE, NULL_TREE };
5571 tree argtypes[2] = { NULL_TREE, NULL_TREE };
5572 /* 1-based attribute positional arguments or zero if not specified.
5573 Invalid negative or excessive values are also stored but used
5574 only in diagnostics. */
5575 HOST_WIDE_INT idxs[2] = { 0, 0 };
5576
5577 /* Number of function formal arguments (used in diagnostics). */
5578 unsigned nfuncargs = 0;
5579 /* Number of (optional) attribute positional arguments. */
5580 unsigned nattrargs = 0;
5581
5582 for (unsigned i = 0; i != 2; ++i, args = TREE_CHAIN (args), ++nattrargs)
5583 {
5584 if (!args)
5585 break;
5586
5587 idxnodes[i] = TREE_VALUE (args);
5588
5589 if (TREE_CODE (idxnodes[i]) != IDENTIFIER_NODE
5590 && TREE_CODE (idxnodes[i]) != FUNCTION_DECL)
5591 idxnodes[i] = default_conversion (idxnodes[i]);
5592
5593 if (tree_fits_shwi_p (idxnodes[i]))
5594 {
5595 idxs[i] = tree_to_shwi (idxnodes[i]);
5596 argtypes[i] = get_argument_type (functype: type, argno: idxs[i], nargs: &nfuncargs);
5597 }
5598 }
5599
5600 if ((nattrargs == 1 && !idxs[0])
5601 || (nattrargs == 2 && (!idxs[0] || !idxs[1])))
5602 {
5603 if (idxnodes[1])
5604 error ("attribute %<%E(%s, %E, %E)%> invalid positional argument %i",
5605 name, access_str, idxnodes[0], idxnodes[1], idxs[0] ? 2 : 1);
5606 else
5607 error ("attribute %<%E(%s, %E)%> invalid positional argument %i",
5608 name, access_str, idxnodes[0], idxs[0] ? 2 : 1);
5609 return NULL_TREE;
5610 }
5611
5612 /* Format the attribute specification to include in diagnostics. */
5613 char attrstr[80];
5614 if (idxnodes[1])
5615 snprintf (s: attrstr, maxlen: sizeof attrstr, format: "%s(%s, %lli, %lli)",
5616 IDENTIFIER_POINTER (name), access_str,
5617 (long long) idxs[0], (long long) idxs[1]);
5618 else if (idxnodes[0])
5619 snprintf (s: attrstr, maxlen: sizeof attrstr, format: "%s(%s, %lli)",
5620 IDENTIFIER_POINTER (name), access_str,
5621 (long long) idxs[0]);
5622 else
5623 snprintf (s: attrstr, maxlen: sizeof attrstr, format: "%s(%s)",
5624 IDENTIFIER_POINTER (name), access_str);
5625
5626 /* Verify the positional argument values are in range. */
5627 if (!argtypes[0] || (idxnodes[1] && !argtypes[1]))
5628 {
5629 if (idxnodes[0])
5630 {
5631 if (idxs[0] < 0 || idxs[1] < 0)
5632 error ("attribute %qs positional argument %i invalid value %wi",
5633 attrstr, idxs[0] < 0 ? 1 : 2,
5634 idxs[0] < 0 ? idxs[0] : idxs[1]);
5635 else
5636 error ("attribute %qs positional argument %i value %wi exceeds "
5637 "number of function arguments %u",
5638 attrstr, idxs[0] ? 1 : 2,
5639 idxs[0] ? idxs[0] : idxs[1],
5640 nfuncargs);
5641 }
5642 else
5643 error ("attribute %qs invalid positional argument", attrstr);
5644
5645 return NULL_TREE;
5646 }
5647
5648 if (!POINTER_TYPE_P (argtypes[0]))
5649 {
5650 /* The first argument must have a pointer or reference type. */
5651 error ("attribute %qs positional argument 1 references "
5652 "non-pointer argument type %qT",
5653 attrstr, argtypes[0]);
5654 return NULL_TREE;
5655 }
5656
5657 {
5658 /* Pointers to functions are not allowed. */
5659 tree ptrtype = TREE_TYPE (argtypes[0]);
5660 if (FUNC_OR_METHOD_TYPE_P (ptrtype))
5661 {
5662 error ("attribute %qs positional argument 1 references "
5663 "argument of function type %qT",
5664 attrstr, ptrtype);
5665 return NULL_TREE;
5666 }
5667 }
5668
5669 if (mode == access_read_write || mode == access_write_only)
5670 {
5671 /* Read_write and write_only modes must reference non-const
5672 arguments. */
5673 if (TYPE_READONLY (TREE_TYPE (argtypes[0])))
5674 {
5675 error ("attribute %qs positional argument 1 references "
5676 "%qs-qualified argument type %qT",
5677 attrstr, "const", argtypes[0]);
5678 return NULL_TREE;
5679 }
5680 }
5681 else if (!TYPE_READONLY (TREE_TYPE (argtypes[0])))
5682 {
5683 /* A read_only mode should ideally reference const-qualified
5684 arguments but it's not diagnosed error if one doesn't.
5685 This makes it possible to annotate legacy, const-incorrect
5686 APIs. It might be worth a diagnostic along the lines of
5687 -Wsuggest-const. */
5688 ;
5689 }
5690
5691 if (argtypes[1] && !INTEGRAL_TYPE_P (argtypes[1]))
5692 {
5693 error ("attribute %qs positional argument 2 references "
5694 "non-integer argument type %qT",
5695 attrstr, argtypes[1]);
5696 return NULL_TREE;
5697 }
5698
5699 /* Verify that the new attribute doesn't conflict with any existing
5700 attributes specified on previous declarations of the same type
5701 and if not, concatenate the two. */
5702 const char code = attr_access::mode_chars[mode];
5703 tree new_attrs = append_access_attr_idxs (node, attrs, attrstr, code, idxs);
5704 if (!new_attrs)
5705 return NULL_TREE;
5706
5707 /* Replace any existing access attribute specification with
5708 the concatenation above. */
5709 new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
5710 new_attrs = tree_cons (name, new_attrs, NULL_TREE);
5711
5712 if (node[1])
5713 {
5714 /* Repeat for the previously declared type. */
5715 attrs = TYPE_ATTRIBUTES (TREE_TYPE (node[1]));
5716 new_attrs = append_access_attr_idxs (node, attrs, attrstr, code, idxs);
5717 if (!new_attrs)
5718 return NULL_TREE;
5719
5720 new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
5721 new_attrs = tree_cons (name, new_attrs, NULL_TREE);
5722 }
5723
5724 /* Recursively call self to "replace" the documented/external form
5725 of the attribute with the condensed internal form. */
5726 decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL);
5727 return NULL_TREE;
5728}
5729
5730/* Extract attribute "arg spec" from each FNDECL argument that has it,
5731 build a single attribute access corresponding to all the arguments,
5732 and return the result. SKIP_VOIDPTR set to ignore void* parameters
5733 (used for user-defined functions for which, unlike in for built-ins,
5734 void* cannot be relied on to determine anything about the access
5735 through it or whether it even takes place).
5736
5737 For example, the parameters in the declaration:
5738
5739 void f (int x, int y, char [x][1][y][3], char [y][2][y][5]);
5740
5741 result in the following attribute access:
5742
5743 value: "+^2[*],$0$1^3[*],$1$1"
5744 list: < <0, x> <1, y> >
5745
5746 where the list has a single value which itself is a list, each
5747 of whose <node>s corresponds to one VLA bound for each of the two
5748 parameters. */
5749
5750tree
5751build_attr_access_from_parms (tree parms, bool skip_voidptr)
5752{
5753 /* Maps each named integral argument DECL seen so far to its position
5754 in the argument list; used to associate VLA sizes with arguments. */
5755 hash_map<tree, unsigned> arg2pos;
5756
5757 /* The string representation of the access specification for all
5758 arguments. */
5759 std::string spec;
5760 unsigned argpos = 0;
5761
5762 /* A TREE_LIST of VLA bounds. */
5763 tree vblist = NULL_TREE;
5764
5765 for (tree arg = parms; arg; arg = TREE_CHAIN (arg), ++argpos)
5766 {
5767 if (!DECL_P (arg))
5768 continue;
5769
5770 tree argtype = TREE_TYPE (arg);
5771 if (DECL_NAME (arg) && INTEGRAL_TYPE_P (argtype))
5772 arg2pos.put (k: arg, v: argpos);
5773 }
5774
5775 tree nnlist = NULL_TREE;
5776 argpos = 0;
5777 for (tree arg = parms; arg; arg = TREE_CHAIN (arg), ++argpos)
5778 {
5779 if (!DECL_P (arg))
5780 continue;
5781
5782 tree argtype = TREE_TYPE (arg);
5783
5784 tree argspec = DECL_ATTRIBUTES (arg);
5785 if (!argspec)
5786 continue;
5787
5788 if (POINTER_TYPE_P (argtype))
5789 {
5790 /* void* arguments in user-defined functions could point to
5791 anything; skip them. */
5792 tree reftype = TREE_TYPE (argtype);
5793 if (skip_voidptr && VOID_TYPE_P (reftype))
5794 continue;
5795 }
5796
5797 /* Each parameter should have at most one "arg spec" attribute. */
5798 argspec = lookup_attribute (attr_name: "arg spec", list: argspec);
5799 if (!argspec)
5800 continue;
5801
5802 /* Attribute arg spec should have one or two arguments. */
5803 argspec = TREE_VALUE (argspec);
5804
5805 /* The attribute arg spec string. */
5806 tree str = TREE_VALUE (argspec);
5807 const char *s = TREE_STRING_POINTER (str);
5808
5809 /* Collect the list of nonnull arguments which use "[static ..]". */
5810 if (s != NULL && s[0] == '[' && s[1] == 's')
5811 nnlist = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
5812 argpos + 1), nnlist);
5813
5814 /* Create the attribute access string from the arg spec string,
5815 optionally followed by position of the VLA bound argument if
5816 it is one. */
5817 {
5818 size_t specend = spec.length ();
5819 if (!specend)
5820 {
5821 spec = '+';
5822 specend = 1;
5823 }
5824
5825 /* Format the access string in place. */
5826 int len = snprintf (NULL, maxlen: 0, format: "%c%u%s",
5827 attr_access::mode_chars[access_deferred],
5828 argpos, s);
5829 spec.resize (n: specend + len + 1);
5830 sprintf (s: &spec[specend], format: "%c%u%s",
5831 attr_access::mode_chars[access_deferred],
5832 argpos, s);
5833 /* Trim the trailing NUL. */
5834 spec.resize (n: specend + len);
5835 }
5836
5837 /* The (optional) list of expressions denoting the VLA bounds
5838 N in ARGTYPE <arg>[Ni]...[Nj]...[Nk]. */
5839 tree argvbs = TREE_CHAIN (argspec);
5840 if (argvbs)
5841 {
5842 spec += ',';
5843 /* Add ARGVBS to the list. Their presence is indicated by
5844 appending a comma followed by the dollar sign and, when
5845 it corresponds to a function parameter, the position of
5846 each bound Ni, so it can be distinguished from
5847 an unspecified bound (as in T[*]). The list is in reverse
5848 order of arguments and needs to be reversed to access in
5849 order. */
5850 vblist = tree_cons (NULL_TREE, argvbs, vblist);
5851
5852 unsigned nelts = 0;
5853 for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb), ++nelts)
5854 {
5855 tree bound = TREE_VALUE (vb);
5856 if (const unsigned *psizpos = arg2pos.get (k: bound))
5857 {
5858 /* BOUND previously seen in the parameter list. */
5859 TREE_PURPOSE (vb) = size_int (*psizpos);
5860 /* Format the position string in place. */
5861 int len = snprintf (NULL, maxlen: 0, format: "$%u", *psizpos);
5862 size_t specend = spec.length ();
5863 spec.resize (n: specend + len + 1);
5864 sprintf (s: &spec[specend], format: "$%u", *psizpos);
5865 /* Trim the trailing NUL. */
5866 spec.resize (n: specend + len);
5867 }
5868 else
5869 {
5870 /* BOUND doesn't name a parameter (it could be a global
5871 variable or an expression such as a function call). */
5872 spec += '$';
5873 }
5874 }
5875 }
5876 }
5877
5878 if (!spec.length ())
5879 return NULL_TREE;
5880
5881 /* If we have nonnull arguments, synthesize an attribute. */
5882 if (nnlist != NULL_TREE)
5883 nnlist = build_tree_list (get_identifier ("nonnull"), nnlist);
5884
5885 /* Attribute access takes a two or three arguments. Wrap VBLIST in
5886 another list in case it has more nodes than would otherwise fit. */
5887 vblist = build_tree_list (NULL_TREE, vblist);
5888
5889 /* Build a single attribute access with the string describing all
5890 array arguments and an optional list of any non-parameter VLA
5891 bounds in order. */
5892 tree str = build_string (spec.length (), spec.c_str ());
5893 tree attrargs = tree_cons (NULL_TREE, str, vblist);
5894 tree name = get_identifier ("access");
5895 return tree_cons (name, attrargs, nnlist);
5896}
5897
5898/* Handle a "nothrow" attribute; arguments as in
5899 struct attribute_spec.handler. */
5900
5901static tree
5902handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5903 int ARG_UNUSED (flags), bool *no_add_attrs)
5904{
5905 if (TREE_CODE (*node) == FUNCTION_DECL)
5906 TREE_NOTHROW (*node) = 1;
5907 /* ??? TODO: Support types. */
5908 else
5909 {
5910 warning (OPT_Wattributes, "%qE attribute ignored", name);
5911 *no_add_attrs = true;
5912 }
5913
5914 return NULL_TREE;
5915}
5916
5917/* Handle a "nothrow" attribute; arguments as in
5918 struct attribute_spec.handler. */
5919
5920static tree
5921handle_expected_throw_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5922 int ARG_UNUSED (flags), bool *no_add_attrs)
5923{
5924 if (TREE_CODE (*node) == FUNCTION_DECL)
5925 /* No flag to set here. */;
5926 /* ??? TODO: Support types. */
5927 else
5928 {
5929 warning (OPT_Wattributes, "%qE attribute ignored", name);
5930 *no_add_attrs = true;
5931 }
5932
5933 return NULL_TREE;
5934}
5935
5936/* Handle a "cleanup" attribute; arguments as in
5937 struct attribute_spec.handler. */
5938
5939static tree
5940handle_cleanup_attribute (tree *node, tree name, tree args,
5941 int ARG_UNUSED (flags), bool *no_add_attrs)
5942{
5943 tree decl = *node;
5944 tree cleanup_id, cleanup_decl;
5945
5946 /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
5947 for global destructors in C++. This requires infrastructure that
5948 we don't have generically at the moment. It's also not a feature
5949 we'd be missing too much, since we do have attribute constructor. */
5950 if (!VAR_P (decl) || TREE_STATIC (decl))
5951 {
5952 warning (OPT_Wattributes, "%qE attribute ignored", name);
5953 *no_add_attrs = true;
5954 return NULL_TREE;
5955 }
5956
5957 /* Verify that the argument is a function in scope. */
5958 /* ??? We could support pointers to functions here as well, if
5959 that was considered desirable. */
5960 cleanup_id = TREE_VALUE (args);
5961 if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
5962 {
5963 error ("cleanup argument not an identifier");
5964 *no_add_attrs = true;
5965 return NULL_TREE;
5966 }
5967 cleanup_decl = lookup_name (cleanup_id);
5968 if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
5969 {
5970 error ("cleanup argument not a function");
5971 *no_add_attrs = true;
5972 return NULL_TREE;
5973 }
5974
5975 /* That the function has proper type is checked with the
5976 eventual call to build_function_call. */
5977
5978 return NULL_TREE;
5979}
5980
5981/* Handle a "warn_unused_result" attribute. No special handling. */
5982
5983static tree
5984handle_warn_unused_result_attribute (tree *node, tree name,
5985 tree ARG_UNUSED (args),
5986 int ARG_UNUSED (flags), bool *no_add_attrs)
5987{
5988 /* Ignore the attribute for functions not returning any value. */
5989 if (VOID_TYPE_P (TREE_TYPE (*node)))
5990 {
5991 warning (OPT_Wattributes, "%qE attribute ignored", name);
5992 *no_add_attrs = true;
5993 }
5994
5995 return NULL_TREE;
5996}
5997
5998/* Handle a "sentinel" attribute. */
5999
6000static tree
6001handle_sentinel_attribute (tree *node, tree name, tree args,
6002 int ARG_UNUSED (flags), bool *no_add_attrs)
6003{
6004 if (!prototype_p (*node))
6005 {
6006 warning (OPT_Wattributes,
6007 "%qE attribute requires prototypes with named arguments", name);
6008 *no_add_attrs = true;
6009 }
6010 else
6011 {
6012 if (!stdarg_p (*node))
6013 {
6014 warning (OPT_Wattributes,
6015 "%qE attribute only applies to variadic functions", name);
6016 *no_add_attrs = true;
6017 }
6018 }
6019
6020 if (args)
6021 {
6022 tree position = TREE_VALUE (args);
6023 if (position && TREE_CODE (position) != IDENTIFIER_NODE
6024 && TREE_CODE (position) != FUNCTION_DECL)
6025 position = default_conversion (position);
6026
6027 if (TREE_CODE (position) != INTEGER_CST
6028 || !INTEGRAL_TYPE_P (TREE_TYPE (position)))
6029 {
6030 warning (OPT_Wattributes,
6031 "requested position is not an integer constant");
6032 *no_add_attrs = true;
6033 }
6034 else
6035 {
6036 if (tree_int_cst_lt (t1: position, integer_zero_node))
6037 {
6038 warning (OPT_Wattributes,
6039 "requested position is less than zero");
6040 *no_add_attrs = true;
6041 }
6042 }
6043 }
6044
6045 return NULL_TREE;
6046}
6047
6048/* Handle a "type_generic" attribute. */
6049
6050static tree
6051handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
6052 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
6053 bool * ARG_UNUSED (no_add_attrs))
6054{
6055 /* Ensure we have a function type. */
6056 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
6057
6058 /* Ensure we have a variadic function. */
6059 gcc_assert (!prototype_p (*node) || stdarg_p (*node));
6060
6061 return NULL_TREE;
6062}
6063
6064/* Handle a "target" attribute. */
6065
6066static tree
6067handle_target_attribute (tree *node, tree name, tree args, int flags,
6068 bool *no_add_attrs)
6069{
6070 /* Ensure we have a function declaration. */
6071 if (TREE_CODE (*node) != FUNCTION_DECL)
6072 {
6073 warning (OPT_Wattributes, "%qE attribute ignored", name);
6074 *no_add_attrs = true;
6075 }
6076 else if (! targetm.target_option.valid_attribute_p (*node, name, args,
6077 flags))
6078 *no_add_attrs = true;
6079
6080 /* Check that there's no empty string in values of the attribute. */
6081 for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
6082 {
6083 tree value = TREE_VALUE (t);
6084 if (TREE_CODE (value) == STRING_CST
6085 && TREE_STRING_LENGTH (value) == 1
6086 && TREE_STRING_POINTER (value)[0] == '\0')
6087 {
6088 warning (OPT_Wattributes, "empty string in attribute %<target%>");
6089 *no_add_attrs = true;
6090 }
6091 }
6092
6093 return NULL_TREE;
6094}
6095
6096/* Handle a "target_version" attribute. */
6097
6098static tree
6099handle_target_version_attribute (tree *node, tree name, tree args, int flags,
6100 bool *no_add_attrs)
6101{
6102 /* Ensure we have a function declaration. */
6103 if (TREE_CODE (*node) != FUNCTION_DECL)
6104 {
6105 warning (OPT_Wattributes, "%qE attribute ignored", name);
6106 *no_add_attrs = true;
6107 }
6108 else if (!targetm.target_option.valid_version_attribute_p (*node, name, args,
6109 flags))
6110 *no_add_attrs = true;
6111
6112 return NULL_TREE;
6113}
6114
6115/* Handle a "target_clones" attribute. */
6116
6117static tree
6118handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6119 int ARG_UNUSED (flags), bool *no_add_attrs)
6120{
6121 /* Ensure we have a function declaration. */
6122 if (TREE_CODE (*node) == FUNCTION_DECL)
6123 {
6124 for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
6125 {
6126 tree value = TREE_VALUE (t);
6127 if (TREE_CODE (value) != STRING_CST)
6128 {
6129 error ("%qE attribute argument not a string constant", name);
6130 *no_add_attrs = true;
6131 return NULL_TREE;
6132 }
6133 }
6134
6135 if (get_target_clone_attr_len (args) == -1)
6136 {
6137 warning (OPT_Wattributes,
6138 "single %<target_clones%> attribute is ignored");
6139 *no_add_attrs = true;
6140 }
6141 else
6142 /* Do not inline functions with multiple clone targets. */
6143 DECL_UNINLINABLE (*node) = 1;
6144 }
6145 else
6146 {
6147 warning (OPT_Wattributes, "%qE attribute ignored", name);
6148 *no_add_attrs = true;
6149 }
6150 return NULL_TREE;
6151}
6152
6153/* For handling "optimize" attribute. arguments as in
6154 struct attribute_spec.handler. */
6155
6156static tree
6157handle_optimize_attribute (tree *node, tree name, tree args,
6158 int ARG_UNUSED (flags), bool *no_add_attrs)
6159{
6160 /* Ensure we have a function type. */
6161 if (TREE_CODE (*node) != FUNCTION_DECL)
6162 {
6163 warning (OPT_Wattributes, "%qE attribute ignored", name);
6164 *no_add_attrs = true;
6165 }
6166 else
6167 {
6168 struct cl_optimization cur_opts;
6169 tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
6170
6171 /* Save current options. */
6172 cl_optimization_save (&cur_opts, &global_options, &global_options_set);
6173 tree prev_target_node = build_target_option_node (opts: &global_options,
6174 opts_set: &global_options_set);
6175
6176 /* If we previously had some optimization options, use them as the
6177 default. */
6178 gcc_options *saved_global_options = NULL;
6179
6180 /* When #pragma GCC optimize pragma is used, it modifies global_options
6181 without calling targetm.override_options_after_change. That can leave
6182 target flags inconsistent for comparison. */
6183 if (flag_checking && optimization_current_node == optimization_default_node)
6184 {
6185 saved_global_options = XNEW (gcc_options);
6186 *saved_global_options = global_options;
6187 }
6188
6189 if (old_opts)
6190 cl_optimization_restore (&global_options, &global_options_set,
6191 TREE_OPTIMIZATION (old_opts));
6192
6193 /* Parse options, and update the vector. */
6194 parse_optimize_options (args, true);
6195 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
6196 = build_optimization_node (opts: &global_options, opts_set: &global_options_set);
6197 tree target_node = build_target_option_node (opts: &global_options,
6198 opts_set: &global_options_set);
6199 if (prev_target_node != target_node)
6200 DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
6201
6202 /* Also update the cgraph_node, if it's already built. */
6203 if (cgraph_node *cn = cgraph_node::get (decl: *node))
6204 cn->semantic_interposition = flag_semantic_interposition;
6205
6206 /* Restore current options. */
6207 cl_optimization_restore (&global_options, &global_options_set,
6208 &cur_opts);
6209 cl_target_option_restore (&global_options, &global_options_set,
6210 TREE_TARGET_OPTION (prev_target_node));
6211
6212 if (saved_global_options != NULL)
6213 {
6214 if (!seen_error ())
6215 cl_optimization_compare (ptr1: saved_global_options, ptr2: &global_options);
6216 free (ptr: saved_global_options);
6217 }
6218 }
6219
6220 return NULL_TREE;
6221}
6222
6223/* Handle a "no_split_stack" attribute. */
6224
6225static tree
6226handle_no_split_stack_attribute (tree *node, tree name,
6227 tree ARG_UNUSED (args),
6228 int ARG_UNUSED (flags),
6229 bool *no_add_attrs)
6230{
6231 tree decl = *node;
6232
6233 if (TREE_CODE (decl) != FUNCTION_DECL)
6234 {
6235 error_at (DECL_SOURCE_LOCATION (decl),
6236 "%qE attribute applies only to functions", name);
6237 *no_add_attrs = true;
6238 }
6239 else if (DECL_INITIAL (decl))
6240 {
6241 error_at (DECL_SOURCE_LOCATION (decl),
6242 "cannot set %qE attribute after definition", name);
6243 *no_add_attrs = true;
6244 }
6245
6246 return NULL_TREE;
6247}
6248
6249/* Handle a "zero_call_used_regs" attribute; arguments as in
6250 struct attribute_spec.handler. */
6251
6252static tree
6253handle_zero_call_used_regs_attribute (tree *node, tree name, tree args,
6254 int ARG_UNUSED (flags),
6255 bool *no_add_attrs)
6256{
6257 tree decl = *node;
6258 tree id = TREE_VALUE (args);
6259
6260 if (TREE_CODE (decl) != FUNCTION_DECL)
6261 {
6262 error_at (DECL_SOURCE_LOCATION (decl),
6263 "%qE attribute applies only to functions", name);
6264 *no_add_attrs = true;
6265 return NULL_TREE;
6266 }
6267
6268 if (TREE_CODE (id) != STRING_CST)
6269 {
6270 error_at (DECL_SOURCE_LOCATION (decl),
6271 "%qE argument not a string", name);
6272 *no_add_attrs = true;
6273 return NULL_TREE;
6274 }
6275
6276 bool found = false;
6277 for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
6278 if (strcmp (TREE_STRING_POINTER (id),
6279 s2: zero_call_used_regs_opts[i].name) == 0)
6280 {
6281 found = true;
6282 break;
6283 }
6284
6285 if (!found)
6286 {
6287 error_at (DECL_SOURCE_LOCATION (decl),
6288 "unrecognized %qE attribute argument %qs",
6289 name, TREE_STRING_POINTER (id));
6290 *no_add_attrs = true;
6291 }
6292
6293 return NULL_TREE;
6294}
6295
6296/* Handle a "returns_nonnull" attribute; arguments as in
6297 struct attribute_spec.handler. */
6298
6299static tree
6300handle_returns_nonnull_attribute (tree *node, tree name, tree, int,
6301 bool *no_add_attrs)
6302{
6303 // Even without a prototype we still have a return type we can check.
6304 if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
6305 {
6306 error ("%qE attribute on a function not returning a pointer", name);
6307 *no_add_attrs = true;
6308 }
6309 return NULL_TREE;
6310}
6311
6312/* Handle a "designated_init" attribute; arguments as in
6313 struct attribute_spec.handler. */
6314
6315static tree
6316handle_designated_init_attribute (tree *node, tree name, tree, int,
6317 bool *no_add_attrs)
6318{
6319 if (TREE_CODE (*node) != RECORD_TYPE)
6320 {
6321 error ("%qE attribute is only valid on %<struct%> type", name);
6322 *no_add_attrs = true;
6323 }
6324 return NULL_TREE;
6325}
6326
6327
6328/* Handle a "fallthrough" attribute; arguments as in struct
6329 attribute_spec.handler. */
6330
6331tree
6332handle_fallthrough_attribute (tree *, tree name, tree, int,
6333 bool *no_add_attrs)
6334{
6335 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name);
6336 *no_add_attrs = true;
6337 return NULL_TREE;
6338}
6339
6340/* Handle a "assume" attribute; arguments as in struct
6341 attribute_spec.handler. */
6342
6343tree
6344handle_assume_attribute (tree *, tree name, tree, int,
6345 bool *no_add_attrs)
6346{
6347 pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name);
6348 *no_add_attrs = true;
6349 return NULL_TREE;
6350}
6351
6352/* Handle a "patchable_function_entry" attributes; arguments as in
6353 struct attribute_spec.handler. */
6354
6355static tree
6356handle_patchable_function_entry_attribute (tree *, tree name, tree args,
6357 int, bool *no_add_attrs)
6358{
6359 for (; args; args = TREE_CHAIN (args))
6360 {
6361 tree val = TREE_VALUE (args);
6362 if (val && TREE_CODE (val) != IDENTIFIER_NODE
6363 && TREE_CODE (val) != FUNCTION_DECL)
6364 val = default_conversion (val);
6365
6366 if (!tree_fits_uhwi_p (val))
6367 {
6368 warning (OPT_Wattributes,
6369 "%qE attribute argument %qE is not an integer constant",
6370 name, val);
6371 *no_add_attrs = true;
6372 return NULL_TREE;
6373 }
6374
6375 if (tree_to_uhwi (val) > USHRT_MAX)
6376 {
6377 warning (OPT_Wattributes,
6378 "%qE attribute argument %qE exceeds %u",
6379 name, val, USHRT_MAX);
6380 *no_add_attrs = true;
6381 return NULL_TREE;
6382 }
6383 }
6384 return NULL_TREE;
6385}
6386
6387/* Handle a "NSObject" attributes; arguments as in
6388 struct attribute_spec.handler. */
6389
6390static tree
6391handle_nsobject_attribute (tree *node, tree name, tree args,
6392 int /*flags*/, bool *no_add_attrs)
6393{
6394 *no_add_attrs = true;
6395
6396 /* This attribute only applies to typedefs (or field decls for properties),
6397 we drop it otherwise - but warn about this if enabled. */
6398 if (TREE_CODE (*node) != TYPE_DECL && TREE_CODE (*node) != FIELD_DECL)
6399 {
6400 warning (OPT_WNSObject_attribute, "%qE attribute may be put on a"
6401 " typedef only; attribute is ignored", name);
6402 return NULL_TREE;
6403 }
6404
6405 /* The original implementation only allowed pointers to records, however
6406 recent implementations also allow void *. */
6407 tree type = TREE_TYPE (*node);
6408 if (!type || !POINTER_TYPE_P (type)
6409 || (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE
6410 && !VOID_TYPE_P (TREE_TYPE (type))))
6411 {
6412 error ("%qE attribute is for pointer types only", name);
6413 return NULL_TREE;
6414 }
6415
6416 tree t = tree_cons (name, args, TYPE_ATTRIBUTES (type));
6417 TREE_TYPE (*node) = build_type_attribute_variant (type, t);
6418
6419 return NULL_TREE;
6420}
6421
6422/* Handle a "objc_root_class" attributes; arguments as in
6423 struct attribute_spec.handler. */
6424
6425static tree
6426handle_objc_root_class_attribute (tree */*node*/, tree name, tree /*args*/,
6427 int /*flags*/, bool *no_add_attrs)
6428{
6429 /* This has no meaning outside Objective-C. */
6430 if (!c_dialect_objc())
6431 warning (OPT_Wattributes, "%qE is only applicable to Objective-C"
6432 " class interfaces, attribute ignored", name);
6433
6434 *no_add_attrs = true;
6435 return NULL_TREE;
6436}
6437
6438/* Handle an "objc_nullability" attribute; arguments as in
6439 struct attribute_spec.handler. */
6440
6441static tree
6442handle_objc_nullability_attribute (tree *node, tree name, tree args,
6443 int /*flags*/,
6444 bool *no_add_attrs)
6445{
6446 *no_add_attrs = true;
6447
6448 tree type = TREE_TYPE (*node);
6449 if (TREE_CODE (*node) == FUNCTION_DECL)
6450 type = TREE_TYPE (type);
6451
6452 if (type && !POINTER_TYPE_P (type))
6453 {
6454 error ("%qE cannot be applied to non-pointer type %qT", name, type);
6455 return NULL_TREE;
6456 }
6457
6458 /* We accept objc_nullability() with a single argument.
6459 string: "unspecified", "nullable", "nonnull" or "resettable"
6460 integer: 0 and 3 where the values have the same meaning as
6461 the strings. */
6462 tree val = TREE_VALUE (args);
6463 if (TREE_CODE (val) == INTEGER_CST)
6464 {
6465 val = default_conversion (val);
6466 if (!tree_fits_uhwi_p (val) || tree_to_uhwi (val) > 3)
6467 error ("%qE attribute argument %qE is not an integer constant"
6468 " between 0 and 3", name, val);
6469 else
6470 *no_add_attrs = false; /* OK */
6471 }
6472 else if (TREE_CODE (val) == STRING_CST
6473 && (strcmp (TREE_STRING_POINTER (val), s2: "nullable") == 0
6474 || strcmp (TREE_STRING_POINTER (val), s2: "nonnull") == 0
6475 || strcmp (TREE_STRING_POINTER (val), s2: "unspecified") == 0
6476 || strcmp (TREE_STRING_POINTER (val), s2: "resettable") == 0))
6477 *no_add_attrs = false; /* OK */
6478 else if (val != error_mark_node)
6479 error ("%qE attribute argument %qE is not recognized", name, val);
6480
6481 return NULL_TREE;
6482}
6483
6484/* Handle a "tainted_args" attribute; arguments as in
6485 struct attribute_spec.handler. */
6486
6487static tree
6488handle_tainted_args_attribute (tree *node, tree name, tree, int,
6489 bool *no_add_attrs)
6490{
6491 if (TREE_CODE (*node) != FUNCTION_DECL
6492 && TREE_CODE (*node) != FIELD_DECL)
6493 {
6494 warning (OPT_Wattributes, "%qE attribute ignored; valid only "
6495 "for functions and function pointer fields",
6496 name);
6497 *no_add_attrs = true;
6498 return NULL_TREE;
6499 }
6500
6501 if (TREE_CODE (*node) == FIELD_DECL
6502 && !(TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE
6503 && TREE_CODE (TREE_TYPE (TREE_TYPE (*node))) == FUNCTION_TYPE))
6504 {
6505 warning (OPT_Wattributes, "%qE attribute ignored;"
6506 " field must be a function pointer",
6507 name);
6508 *no_add_attrs = true;
6509 return NULL_TREE;
6510 }
6511
6512 *no_add_attrs = false; /* OK */
6513
6514 return NULL_TREE;
6515}
6516
6517/* Attempt to partially validate a single attribute ATTR as if
6518 it were to be applied to an entity OPER. */
6519
6520static bool
6521validate_attribute (location_t atloc, tree oper, tree attr)
6522{
6523 /* Determine whether the name of the attribute is valid
6524 and fail with an error if not. */
6525 tree atname = get_attribute_name (attr);
6526 if (!lookup_attribute_spec (atname))
6527 {
6528 if (atloc != UNKNOWN_LOCATION)
6529 error_at (atloc, "unknown attribute %qE", atname);
6530 return false;
6531 }
6532
6533 tree args = TREE_VALUE (attr);
6534 if (!args)
6535 return true;
6536
6537 /* FIXME: Do some validation. */
6538 const char *atstr = IDENTIFIER_POINTER (atname);
6539 if (!strcmp (s1: atstr, s2: "format"))
6540 return true;
6541
6542 /* Only when attribute arguments have been provided try to validate
6543 the whole thing. decl_attributes doesn't return an indication of
6544 success or failure so proceed regardless. */
6545 const char tmpname[] = "__builtin_has_attribute_tmp.";
6546 tree tmpid = get_identifier (tmpname);
6547 tree tmpdecl;
6548 if (!strcmp (s1: atstr, s2: "vector_size"))
6549 {
6550 tree type = TYPE_P (oper) ? oper : TREE_TYPE (oper);
6551 /* Check for function type here since type_for_vector_size
6552 strips it while looking for a function's return type. */
6553 if (FUNC_OR_METHOD_TYPE_P (type))
6554 {
6555 warning_at (atloc, OPT_Wattributes,
6556 "invalid operand type %qT for %qs", type, atstr);
6557 return false;
6558 }
6559
6560 type = type_for_vector_size (type);
6561 if (VECTOR_TYPE_P (type))
6562 type = TREE_TYPE (type);
6563 /* Avoid trying to apply attribute vector_size to OPER since
6564 it's overly restrictive. Simply make sure it has the right
6565 type. */
6566 return type_valid_for_vector_size (type, atname, args, NULL);
6567 }
6568
6569 if (TYPE_P (oper))
6570 tmpdecl = build_decl (atloc, TYPE_DECL, tmpid, oper);
6571 else if (DECL_P (oper))
6572 tmpdecl = build_decl (atloc, TREE_CODE (oper), tmpid, TREE_TYPE (oper));
6573 else if (EXPR_P (oper))
6574 tmpdecl = build_decl (atloc, TYPE_DECL, tmpid, TREE_TYPE (oper));
6575 else
6576 return false;
6577
6578 /* Temporarily clear CURRENT_FUNCTION_DECL to make decl_attributes
6579 believe the DECL declared above is at file scope. (See bug 87526.) */
6580 tree save_curfunc = current_function_decl;
6581 current_function_decl = NULL_TREE;
6582 if (DECL_P (tmpdecl))
6583 {
6584 if (DECL_P (oper))
6585 /* An alias cannot be a definition so declare the symbol extern. */
6586 DECL_EXTERNAL (tmpdecl) = true;
6587 /* Attribute visibility only applies to symbols visible from other
6588 translation units so make it "public." */
6589 TREE_PUBLIC (tmpdecl) = TREE_PUBLIC (oper);
6590 }
6591 decl_attributes (&tmpdecl, attr, 0);
6592 current_function_decl = save_curfunc;
6593
6594 /* FIXME: Change decl_attributes to indicate success or failure (and
6595 parameterize it to avoid failing with errors). */
6596 return true;
6597}
6598
6599/* Return true if the DECL, EXPR, or TYPE t has been declared with
6600 attribute ATTR. For DECL, consider also its type. For EXPR,
6601 consider just its type. */
6602
6603bool
6604has_attribute (location_t atloc, tree t, tree attr, tree (*convert)(tree))
6605{
6606 if (!attr || !t || t == error_mark_node)
6607 return false;
6608
6609 if (!validate_attribute (atloc, oper: t, attr))
6610 return false;
6611
6612 tree type = NULL_TREE;
6613 tree expr = NULL_TREE;
6614 if (TYPE_P (t))
6615 type = t;
6616 else
6617 {
6618 do
6619 {
6620 /* Determine the array element/member declaration from
6621 a COMPONENT_REF and an INDIRECT_REF involving a refeence. */
6622 STRIP_NOPS (t);
6623 tree_code code = TREE_CODE (t);
6624 if (code == INDIRECT_REF)
6625 {
6626 tree op0 = TREE_OPERAND (t, 0);
6627 if (TREE_CODE (TREE_TYPE (op0)) == REFERENCE_TYPE)
6628 t = op0;
6629 else
6630 break;
6631 }
6632 else if (code == COMPONENT_REF)
6633 t = TREE_OPERAND (t, 1);
6634 else
6635 break;
6636 } while (true);
6637 expr = t;
6638 }
6639
6640 /* Set to true when an attribute is found in the referenced entity
6641 that matches the specified attribute. */
6642 bool found_match = false;
6643
6644 tree atname = get_attribute_name (attr);
6645 const char *namestr = IDENTIFIER_POINTER (atname);
6646
6647 /* Iterate once for a type and twice for a function or variable
6648 declaration: once for the DECL and the second time for its
6649 TYPE. */
6650 for (bool done = false; !found_match && !done; )
6651 {
6652 tree atlist;
6653 if (type)
6654 {
6655 if (type == error_mark_node)
6656 {
6657 /* This could be a label. FIXME: add support for labels. */
6658 warning_at (atloc, OPT_Wattributes,
6659 (TYPE_P (t)
6660 ? G_("%qs attribute not supported for %qT "
6661 "in %<__builtin_has_attribute%>")
6662 : G_("%qs attribute not supported for %qE "
6663 "in %<__builtin_has_attribute%>")),
6664 namestr, t);
6665 return false;
6666 }
6667
6668 /* Clear EXPR to prevent considering it again below. */
6669 atlist = TYPE_ATTRIBUTES (type);
6670 expr = NULL_TREE;
6671 done = true;
6672 }
6673 else if (DECL_P (expr))
6674 {
6675 /* Set TYPE to the DECL's type to process it on the next
6676 iteration. */
6677 atlist = DECL_ATTRIBUTES (expr);
6678 type = TREE_TYPE (expr);
6679 }
6680 else
6681 {
6682 type = TREE_TYPE (expr);
6683 atlist = TYPE_ATTRIBUTES (type);
6684 done = true;
6685 }
6686
6687 /* True when an attribute with the sought name (though not necessarily
6688 with the sought attributes) has been found on the attribute chain. */
6689 bool found_attr = false;
6690
6691 /* When clear, the first mismatched attribute argument results
6692 in failure. Otherwise, the first matched attribute argument
6693 results in success. */
6694 bool attr_nonnull = !strcmp (s1: "nonnull", s2: namestr);
6695 bool ignore_mismatches = attr_nonnull;
6696
6697 /* Iterate over the instances of the sought attribute on the DECL or
6698 TYPE (there may be multiple instances with different arguments). */
6699 for (; (atlist = lookup_attribute (attr_name: namestr, list: atlist));
6700 found_attr = true, atlist = TREE_CHAIN (atlist))
6701 {
6702 /* If there are no arguments to match the result is true except
6703 for nonnull where the attribute with no arguments must match. */
6704 if (!TREE_VALUE (attr))
6705 return attr_nonnull ? !TREE_VALUE (atlist) : true;
6706
6707 /* Attribute nonnull with no arguments subsumes all values of
6708 the attribute. FIXME: This is overly broad since it only
6709 applies to pointer arguments, but querying non-pointer
6710 arguments is diagnosed. */
6711 if (!TREE_VALUE (atlist) && attr_nonnull)
6712 return true;
6713
6714 /* Iterate over the DECL or TYPE attribute argument's values. */
6715 for (tree val = TREE_VALUE (atlist); val; val = TREE_CHAIN (val))
6716 {
6717 /* Iterate over the arguments in the sought attribute comparing
6718 their values to those specified for the DECL or TYPE. */
6719 for (tree arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
6720 {
6721 tree v1 = TREE_VALUE (val);
6722 tree v2 = TREE_VALUE (arg);
6723 if (v1 == v2)
6724 return true;
6725
6726 if (!v1 || !v2)
6727 break;
6728
6729 if (TREE_CODE (v1) == IDENTIFIER_NODE
6730 || TREE_CODE (v2) == IDENTIFIER_NODE)
6731 /* Two identifiers are the same if their values are
6732 equal (that's handled above). Otherwise ther are
6733 either not the same or oneis not an identifier. */
6734 return false;
6735
6736 /* Convert to make them equality-comparable. */
6737 v1 = convert (v1);
6738 v2 = convert (v2);
6739
6740 /* A positive value indicates equality, negative means
6741 "don't know." */
6742 if (simple_cst_equal (v1, v2) == 1)
6743 return true;
6744
6745 if (!ignore_mismatches)
6746 break;
6747 }
6748 }
6749 }
6750
6751 if (!found_attr)
6752 {
6753 /* Some attributes are encoded directly in the tree node. */
6754 if (!strcmp (s1: "aligned", s2: namestr))
6755 {
6756 if (tree arg = TREE_VALUE (attr))
6757 {
6758 arg = convert (TREE_VALUE (arg));
6759 if (!tree_fits_uhwi_p (arg))
6760 /* Invalid argument. */;
6761 else if (expr && DECL_P (expr)
6762 && DECL_USER_ALIGN (expr))
6763 found_match = DECL_ALIGN_UNIT (expr) == tree_to_uhwi (arg);
6764 else if (type && TYPE_USER_ALIGN (type))
6765 found_match = TYPE_ALIGN_UNIT (type) == tree_to_uhwi (arg);
6766 }
6767 else if (expr && DECL_P (expr))
6768 found_match = DECL_USER_ALIGN (expr);
6769 else if (type)
6770 found_match = TYPE_USER_ALIGN (type);
6771 }
6772 else if (!strcmp (s1: "const", s2: namestr))
6773 {
6774 if (expr && DECL_P (expr))
6775 found_match = TREE_READONLY (expr);
6776 }
6777 else if (!strcmp (s1: "noreturn", s2: namestr))
6778 {
6779 /* C11 _Noreturn sets the volatile bit without attaching
6780 an attribute to the decl. */
6781 if (expr
6782 && DECL_P (expr)
6783 && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr)))
6784 found_match = TREE_THIS_VOLATILE (expr);
6785 }
6786 else if (!strcmp (s1: "pure", s2: namestr))
6787 {
6788 if (expr && DECL_P (expr))
6789 found_match = DECL_PURE_P (expr);
6790 }
6791 else if (!strcmp (s1: "deprecated", s2: namestr))
6792 {
6793 found_match = TREE_DEPRECATED (expr ? expr : type);
6794 if (found_match)
6795 return true;
6796 }
6797 else if (!strcmp (s1: "vector_size", s2: namestr))
6798 {
6799 if (!type || !VECTOR_TYPE_P (type))
6800 return false;
6801
6802 if (tree arg = TREE_VALUE (attr))
6803 {
6804 /* Compare the vector size argument for equality. */
6805 arg = convert (TREE_VALUE (arg));
6806 return tree_int_cst_equal (arg, TYPE_SIZE_UNIT (type)) == 1;
6807 }
6808 else
6809 return true;
6810 }
6811 else if (!strcmp (s1: "warn_if_not_aligned", s2: namestr))
6812 {
6813 if (tree arg = TREE_VALUE (attr))
6814 {
6815 arg = convert (TREE_VALUE (arg));
6816 if (expr && DECL_P (expr))
6817 found_match = (DECL_WARN_IF_NOT_ALIGN (expr)
6818 == tree_to_uhwi (arg) * BITS_PER_UNIT);
6819 else if (type)
6820 found_match = (TYPE_WARN_IF_NOT_ALIGN (type)
6821 == tree_to_uhwi (arg) * BITS_PER_UNIT);
6822 }
6823 else if (expr && DECL_P (expr))
6824 found_match = DECL_WARN_IF_NOT_ALIGN (expr);
6825 else if (type)
6826 found_match = TYPE_WARN_IF_NOT_ALIGN (type);
6827 }
6828 else if (!strcmp (s1: "transparent_union", s2: namestr))
6829 {
6830 if (type)
6831 found_match = TYPE_TRANSPARENT_AGGR (type) != 0;
6832 }
6833 else if (!strcmp (s1: "mode", s2: namestr))
6834 {
6835 /* Finally issue a warning for attributes that cannot
6836 be supported in this context. Attribute mode is not
6837 added to a symbol and cannot be determined from it. */
6838 warning_at (atloc, OPT_Wattributes,
6839 "%qs attribute not supported in "
6840 "%<__builtin_has_attribute%>", namestr);
6841 break;
6842 }
6843 }
6844 }
6845 return found_match;
6846}
6847

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of gcc/c-family/c-attribs.cc