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