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

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