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

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