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

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