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