Line data Source code
1 : /* C-family attributes handling.
2 : Copyright (C) 1992-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #define INCLUDE_STRING
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "target.h"
25 : #include "function.h"
26 : #include "tree.h"
27 : #include "memmodel.h"
28 : #include "c-common.h"
29 : #include "gimple-expr.h"
30 : #include "tm_p.h"
31 : #include "stringpool.h"
32 : #include "cgraph.h"
33 : #include "diagnostic.h"
34 : #include "intl.h"
35 : #include "stor-layout.h"
36 : #include "calls.h"
37 : #include "attribs.h"
38 : #include "varasm.h"
39 : #include "trans-mem.h"
40 : #include "c-objc.h"
41 : #include "common/common-target.h"
42 : #include "langhooks.h"
43 : #include "tree-inline.h"
44 : #include "ipa-strub.h"
45 : #include "toplev.h"
46 : #include "tree-iterator.h"
47 : #include "opts.h"
48 : #include "gimplify.h"
49 : #include "tree-pretty-print.h"
50 : #include "gcc-rich-location.h"
51 : #include "gcc-urlifier.h"
52 : #include "attr-callback.h"
53 :
54 : static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
55 : static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
56 : static tree handle_common_attribute (tree *, tree, tree, int, bool *);
57 : static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
58 : static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
59 : static tree handle_no_sanitize_attribute (tree *, tree, tree, int, bool *);
60 : static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
61 : int, bool *);
62 : static tree handle_no_sanitize_thread_attribute (tree *, tree, tree,
63 : int, bool *);
64 : static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
65 : int, bool *);
66 : static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
67 : bool *);
68 : static tree handle_no_sanitize_coverage_attribute (tree *, tree, tree, int,
69 : bool *);
70 : static tree handle_asan_odr_indicator_attribute (tree *, tree, tree, int,
71 : bool *);
72 : static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
73 : static tree handle_no_stack_protector_function_attribute (tree *, tree,
74 : tree, int, bool *);
75 : static tree handle_strub_attribute (tree *, tree, tree, int, bool *);
76 : static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
77 : static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
78 : static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *);
79 : static tree handle_symver_attribute (tree *, tree, tree, int, bool *);
80 : static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
81 : static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
82 : static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
83 : static tree handle_always_inline_attribute (tree *, tree, tree, int,
84 : bool *);
85 : static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
86 : static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
87 : static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
88 : static tree handle_error_attribute (tree *, tree, tree, int, bool *);
89 : static tree handle_used_attribute (tree *, tree, tree, int, bool *);
90 : static tree handle_uninitialized_attribute (tree *, tree, tree, int, bool *);
91 : static tree handle_externally_visible_attribute (tree *, tree, tree, int,
92 : bool *);
93 : static tree handle_no_reorder_attribute (tree *, tree, tree, int,
94 : bool *);
95 : static tree handle_const_attribute (tree *, tree, tree, int, bool *);
96 : static tree handle_transparent_union_attribute (tree *, tree, tree,
97 : int, bool *);
98 : static tree handle_scalar_storage_order_attribute (tree *, tree, tree,
99 : int, bool *);
100 : static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
101 : static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
102 : static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
103 : static tree handle_section_attribute (tree *, tree, tree, int, bool *);
104 : static tree handle_special_var_sec_attribute (tree *, tree, tree, int, bool *);
105 : static tree handle_warn_if_not_aligned_attribute (tree *, tree, tree,
106 : int, bool *);
107 : static tree handle_strict_flex_array_attribute (tree *, tree, tree,
108 : int, bool *);
109 : static tree handle_counted_by_attribute (tree *, tree, tree,
110 : int, bool *);
111 : static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
112 : static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
113 : static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
114 : static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *);
115 : static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
116 : static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
117 : static tree handle_visibility_attribute (tree *, tree, tree, int,
118 : bool *);
119 : static tree handle_tls_model_attribute (tree *, tree, tree, int,
120 : bool *);
121 : static tree handle_no_instrument_function_attribute (tree *, tree,
122 : tree, int, bool *);
123 : static tree handle_no_profile_instrument_function_attribute (tree *, tree,
124 : tree, int, bool *);
125 : static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
126 : static tree handle_dealloc_attribute (tree *, tree, tree, int, bool *);
127 : static tree handle_tainted_args_attribute (tree *, tree, tree, int, bool *);
128 : static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
129 : static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
130 : bool *);
131 : static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
132 : static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
133 : static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
134 : static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
135 : static tree handle_unavailable_attribute (tree *, tree, tree, int,
136 : bool *);
137 : static tree handle_vector_size_attribute (tree *, tree, tree, int,
138 : bool *) ATTRIBUTE_NONNULL(3);
139 : static tree handle_vector_mask_attribute (tree *, tree, tree, int,
140 : bool *) ATTRIBUTE_NONNULL(3);
141 : static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
142 : static tree handle_nonnull_if_nonzero_attribute (tree *, tree, tree, int,
143 : bool *);
144 : static tree handle_nonstring_attribute (tree *, tree, tree, int, bool *);
145 : static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
146 : static tree handle_expected_throw_attribute (tree *, tree, tree, int, bool *);
147 : static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
148 : static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
149 : bool *);
150 : static tree handle_access_attribute (tree *, tree, tree, int, bool *);
151 :
152 : static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
153 : static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
154 : static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
155 : static tree handle_alloc_align_attribute (tree *, tree, tree, int, bool *);
156 : static tree handle_assume_aligned_attribute (tree *, tree, tree, int, bool *);
157 : static tree handle_assume_attribute (tree *, tree, tree, int, bool *);
158 : static tree handle_target_attribute (tree *, tree, tree, int, bool *);
159 : static tree handle_target_version_attribute (tree *, tree, tree, int, bool *);
160 : static tree handle_target_clones_attribute (tree *, tree, tree, int, bool *);
161 : static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
162 : static tree ignore_attribute (tree *, tree, tree, int, bool *);
163 : static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
164 : static tree handle_zero_call_used_regs_attribute (tree *, tree, tree, int,
165 : bool *);
166 : static tree handle_argspec_attribute (tree *, tree, tree, int, bool *);
167 : static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
168 : static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
169 : static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
170 : static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
171 : bool *);
172 : static tree handle_omp_declare_variant_attribute (tree *, tree, tree, int,
173 : bool *);
174 : static tree handle_simd_attribute (tree *, tree, tree, int, bool *);
175 : static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
176 : bool *);
177 : static tree handle_non_overlapping_attribute (tree *, tree, tree, int, bool *);
178 : static tree handle_designated_init_attribute (tree *, tree, tree, int, bool *);
179 : static tree handle_patchable_function_entry_attribute (tree *, tree, tree,
180 : int, bool *);
181 : static tree handle_copy_attribute (tree *, tree, tree, int, bool *);
182 : static tree handle_nsobject_attribute (tree *, tree, tree, int, bool *);
183 : static tree handle_objc_root_class_attribute (tree *, tree, tree, int, bool *);
184 : static tree handle_objc_nullability_attribute (tree *, tree, tree, int, bool *);
185 : static tree handle_signed_bool_precision_attribute (tree *, tree, tree, int,
186 : bool *);
187 : static tree handle_hardbool_attribute (tree *, tree, tree, int, bool *);
188 : static tree handle_retain_attribute (tree *, tree, tree, int, bool *);
189 : static tree handle_fd_arg_attribute (tree *, tree, tree, int, bool *);
190 : static tree handle_flag_enum_attribute (tree *, tree, tree, int, bool *);
191 : static tree handle_null_terminated_string_arg_attribute (tree *, tree, tree, int, bool *);
192 :
193 : static tree handle_btf_decl_tag_attribute (tree *, tree, tree, int, bool *);
194 : static tree handle_btf_type_tag_attribute (tree *, tree, tree, int, bool *);
195 :
196 : /* Helper to define attribute exclusions. */
197 : #define ATTR_EXCL(name, function, type, variable) \
198 : { name, function, type, variable }
199 :
200 : /* Define attributes that are mutually exclusive with one another. */
201 : extern const struct attribute_spec::exclusions attr_aligned_exclusions[] =
202 : {
203 : /* Attribute name exclusion applies to:
204 : function, type, variable */
205 : ATTR_EXCL ("aligned", true, false, false),
206 : ATTR_EXCL ("packed", true, false, false),
207 : ATTR_EXCL (NULL, false, false, false)
208 : };
209 :
210 : extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
211 : {
212 : ATTR_EXCL ("cold", true, true, true),
213 : ATTR_EXCL ("hot", true, true, true),
214 : ATTR_EXCL (NULL, false, false, false)
215 : };
216 :
217 : static const struct attribute_spec::exclusions attr_common_exclusions[] =
218 : {
219 : ATTR_EXCL ("common", true, true, true),
220 : ATTR_EXCL ("nocommon", true, true, true),
221 : ATTR_EXCL (NULL, false, false, false),
222 : };
223 :
224 : static const struct attribute_spec::exclusions attr_inline_exclusions[] =
225 : {
226 : ATTR_EXCL ("noinline", true, true, true),
227 : ATTR_EXCL (NULL, false, false, false),
228 : };
229 :
230 : static const struct attribute_spec::exclusions attr_always_inline_exclusions[] =
231 : {
232 : ATTR_EXCL ("noinline", true, true, true),
233 : ATTR_EXCL ("target_clones", true, true, true),
234 : ATTR_EXCL (NULL, false, false, false),
235 : };
236 :
237 : static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
238 : {
239 : ATTR_EXCL ("always_inline", true, true, true),
240 : ATTR_EXCL ("gnu_inline", true, true, true),
241 : ATTR_EXCL (NULL, false, false, false),
242 : };
243 :
244 : static const struct attribute_spec::exclusions attr_target_exclusions[] =
245 : {
246 : ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
247 : TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
248 : ATTR_EXCL (NULL, false, false, false),
249 : };
250 :
251 : static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
252 : {
253 : ATTR_EXCL ("always_inline", true, true, true),
254 : ATTR_EXCL ("target", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
255 : TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
256 : ATTR_EXCL ("omp declare simd", true, true, true),
257 : ATTR_EXCL ("simd", true, true, true),
258 : ATTR_EXCL (NULL, false, false, false),
259 : };
260 :
261 : static const struct attribute_spec::exclusions attr_target_version_exclusions[] =
262 : {
263 : ATTR_EXCL ("omp declare simd", true, true, true),
264 : ATTR_EXCL ("simd", true, true, true),
265 : ATTR_EXCL (NULL, false, false, false),
266 : };
267 :
268 : static const struct attribute_spec::exclusions attr_omp_declare_simd_exclusions[] =
269 : {
270 : ATTR_EXCL ("target_version", true, true, true),
271 : ATTR_EXCL ("target_clones", true, true, true),
272 : ATTR_EXCL (NULL, false, false, false),
273 : };
274 :
275 : static const struct attribute_spec::exclusions attr_simd_exclusions[] =
276 : {
277 : ATTR_EXCL ("target_version", true, true, true),
278 : ATTR_EXCL ("target_clones", true, true, true),
279 : ATTR_EXCL (NULL, false, false, false),
280 : };
281 :
282 : extern const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
283 : {
284 : ATTR_EXCL ("alloc_align", true, true, true),
285 : ATTR_EXCL ("alloc_size", true, true, true),
286 : ATTR_EXCL ("const", true, true, true),
287 : ATTR_EXCL ("malloc", true, true, true),
288 : ATTR_EXCL ("pure", true, true, true),
289 : ATTR_EXCL ("returns_twice", true, true, true),
290 : ATTR_EXCL ("warn_unused_result", true, true, true),
291 : ATTR_EXCL (NULL, false, false, false),
292 : };
293 :
294 : static const struct attribute_spec::exclusions
295 : attr_warn_unused_result_exclusions[] =
296 : {
297 : ATTR_EXCL ("noreturn", true, true, true),
298 : ATTR_EXCL ("warn_unused_result", true, true, true),
299 : ATTR_EXCL (NULL, false, false, false),
300 : };
301 :
302 : static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
303 : {
304 : ATTR_EXCL ("noreturn", true, true, true),
305 : ATTR_EXCL (NULL, false, false, false),
306 : };
307 :
308 : /* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */
309 : static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
310 : {
311 : ATTR_EXCL ("const", true, true, true),
312 : ATTR_EXCL ("noreturn", true, true, true),
313 : ATTR_EXCL ("pure", true, true, true),
314 : ATTR_EXCL (NULL, false, false, false),
315 : };
316 :
317 : static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
318 : {
319 : ATTR_EXCL ("const", true, true, true),
320 : ATTR_EXCL ("alloc_align", true, true, true),
321 : ATTR_EXCL ("alloc_size", true, true, true),
322 : ATTR_EXCL ("malloc", true, true, true),
323 : ATTR_EXCL ("noreturn", true, true, true),
324 : ATTR_EXCL ("pure", true, true, true),
325 : ATTR_EXCL (NULL, false, false, false)
326 : };
327 :
328 : /* Exclusions that apply to attributes that put declarations in specific
329 : sections. */
330 : static const struct attribute_spec::exclusions attr_section_exclusions[] =
331 : {
332 : ATTR_EXCL ("noinit", true, true, true),
333 : ATTR_EXCL ("persistent", true, true, true),
334 : ATTR_EXCL ("section", true, true, true),
335 : ATTR_EXCL (NULL, false, false, false),
336 : };
337 :
338 : static const struct attribute_spec::exclusions attr_stack_protect_exclusions[] =
339 : {
340 : ATTR_EXCL ("stack_protect", true, false, false),
341 : ATTR_EXCL ("no_stack_protector", true, false, false),
342 : ATTR_EXCL (NULL, false, false, false),
343 : };
344 :
345 :
346 : /* Table of machine-independent attributes common to all C-like languages.
347 :
348 : Current list of processed common attributes: nonnull. */
349 : const struct attribute_spec c_common_gnu_attributes[] =
350 : {
351 : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
352 : affects_type_identity, handler, exclude } */
353 : { "signed_bool_precision", 1, 1, false, true, false, true,
354 : handle_signed_bool_precision_attribute, NULL },
355 : { "hardbool", 0, 2, false, true, false, true,
356 : handle_hardbool_attribute, NULL },
357 : { "packed", 0, 0, false, false, false, false,
358 : handle_packed_attribute,
359 : attr_aligned_exclusions },
360 : { "nocommon", 0, 0, true, false, false, false,
361 : handle_nocommon_attribute,
362 : attr_common_exclusions },
363 : { "common", 0, 0, true, false, false, false,
364 : handle_common_attribute,
365 : attr_common_exclusions },
366 : { "musttail", 0, 0, false, false, false,
367 : false, handle_musttail_attribute, NULL },
368 : /* FIXME: logically, noreturn attributes should be listed as
369 : "false, true, true" and apply to function types. But implementing this
370 : would require all the places in the compiler that use TREE_THIS_VOLATILE
371 : on a decl to identify non-returning functions to be located and fixed
372 : to check the function type instead. */
373 : { "noreturn", 0, 0, true, false, false, false,
374 : handle_noreturn_attribute,
375 : attr_noreturn_exclusions },
376 : { "volatile", 0, 0, true, false, false, false,
377 : handle_noreturn_attribute, NULL },
378 : { "stack_protect", 0, 0, true, false, false, false,
379 : handle_stack_protect_attribute,
380 : attr_stack_protect_exclusions },
381 : { "no_stack_protector", 0, 0, true, false, false, false,
382 : handle_no_stack_protector_function_attribute,
383 : attr_stack_protect_exclusions },
384 : { "strub", 0, 1, false, true, false, true,
385 : handle_strub_attribute, NULL },
386 : { "noinline", 0, 0, true, false, false, false,
387 : handle_noinline_attribute,
388 : attr_noinline_exclusions },
389 : { "noclone", 0, 0, true, false, false, false,
390 : handle_noclone_attribute, NULL },
391 : { "no_icf", 0, 0, true, false, false, false,
392 : handle_noicf_attribute, NULL },
393 : { "noipa", 0, 0, true, false, false, false,
394 : handle_noipa_attribute, NULL },
395 : { "leaf", 0, 0, true, false, false, false,
396 : handle_leaf_attribute, NULL },
397 : { "always_inline", 0, 0, true, false, false, false,
398 : handle_always_inline_attribute,
399 : attr_always_inline_exclusions },
400 : { "gnu_inline", 0, 0, true, false, false, false,
401 : handle_gnu_inline_attribute,
402 : attr_inline_exclusions },
403 : { "artificial", 0, 0, true, false, false, false,
404 : handle_artificial_attribute, NULL },
405 : { "flatten", 0, 0, true, false, false, false,
406 : handle_flatten_attribute, NULL },
407 : { "used", 0, 0, true, false, false, false,
408 : handle_used_attribute, NULL },
409 : { "unused", 0, 0, false, false, false, false,
410 : handle_unused_attribute, NULL },
411 : { "uninitialized", 0, 0, true, false, false, false,
412 : handle_uninitialized_attribute, NULL },
413 : { "retain", 0, 0, true, false, false, false,
414 : handle_retain_attribute, NULL },
415 : { "externally_visible", 0, 0, true, false, false, false,
416 : handle_externally_visible_attribute, NULL },
417 : { "no_reorder", 0, 0, true, false, false, false,
418 : handle_no_reorder_attribute, NULL },
419 : /* The same comments as for noreturn attributes apply to const ones. */
420 : { "const", 0, 0, true, false, false, false,
421 : handle_const_attribute,
422 : attr_const_pure_exclusions },
423 : { "scalar_storage_order", 1, 1, false, false, false, false,
424 : handle_scalar_storage_order_attribute, NULL },
425 : { "transparent_union", 0, 0, false, false, false, false,
426 : handle_transparent_union_attribute, NULL },
427 : { "constructor", 0, 1, true, false, false, false,
428 : handle_constructor_attribute, NULL },
429 : { "destructor", 0, 1, true, false, false, false,
430 : handle_destructor_attribute, NULL },
431 : { "mode", 1, 1, false, true, false, false,
432 : handle_mode_attribute, NULL },
433 : { "section", 1, 1, true, false, false, false,
434 : handle_section_attribute, attr_section_exclusions },
435 : { "aligned", 0, 1, false, false, false, false,
436 : handle_aligned_attribute,
437 : attr_aligned_exclusions },
438 : { "warn_if_not_aligned", 0, 1, false, false, false, false,
439 : handle_warn_if_not_aligned_attribute, NULL },
440 : { "strict_flex_array", 1, 1, true, false, false, false,
441 : handle_strict_flex_array_attribute, NULL },
442 : { "counted_by", 1, 1, true, false, false, false,
443 : handle_counted_by_attribute, NULL },
444 : { "weak", 0, 0, true, false, false, false,
445 : handle_weak_attribute, NULL },
446 : { "noplt", 0, 0, true, false, false, false,
447 : handle_noplt_attribute, NULL },
448 : { "ifunc", 1, 1, true, false, false, false,
449 : handle_ifunc_attribute, NULL },
450 : { "alias", 1, 1, true, false, false, false,
451 : handle_alias_attribute, NULL },
452 : { "weakref", 0, 1, true, false, false, false,
453 : handle_weakref_attribute, NULL },
454 : { "no_instrument_function", 0, 0, true, false, false, false,
455 : handle_no_instrument_function_attribute,
456 : NULL },
457 : { "no_profile_instrument_function", 0, 0, true, false, false, false,
458 : handle_no_profile_instrument_function_attribute,
459 : NULL },
460 : { "malloc", 0, 2, true, false, false, false,
461 : handle_malloc_attribute, attr_alloc_exclusions },
462 : { "returns_twice", 0, 0, true, false, false, false,
463 : handle_returns_twice_attribute,
464 : attr_returns_twice_exclusions },
465 : { "no_stack_limit", 0, 0, true, false, false, false,
466 : handle_no_limit_stack_attribute, NULL },
467 : { "pure", 0, 0, true, false, false, false,
468 : handle_pure_attribute,
469 : attr_const_pure_exclusions },
470 : { "reproducible", 0, 0, false, true, true, false,
471 : handle_reproducible_attribute, NULL },
472 : { "unsequenced", 0, 0, false, true, true, false,
473 : handle_unsequenced_attribute, NULL },
474 : { "reproducible noptr", 0, 0, false, true, true, false,
475 : handle_reproducible_attribute, NULL },
476 : { "unsequenced noptr", 0, 0, false, true, true, false,
477 : handle_unsequenced_attribute, NULL },
478 : { "transaction_callable", 0, 0, false, true, false, false,
479 : handle_tm_attribute, NULL },
480 : { "transaction_unsafe", 0, 0, false, true, false, true,
481 : handle_tm_attribute, NULL },
482 : { "transaction_safe", 0, 0, false, true, false, true,
483 : handle_tm_attribute, NULL },
484 : { "transaction_safe_dynamic", 0, 0, true, false, false, false,
485 : handle_tm_attribute, NULL },
486 : { "transaction_may_cancel_outer", 0, 0, false, true, false, false,
487 : handle_tm_attribute, NULL },
488 : { CALLBACK_ATTR_IDENT, 1, -1, true, false, false, false,
489 : handle_callback_attribute, NULL },
490 : /* ??? These two attributes didn't make the transition from the
491 : Intel language document to the multi-vendor language document. */
492 : { "transaction_pure", 0, 0, false, true, false, false,
493 : handle_tm_attribute, NULL },
494 : { "transaction_wrap", 1, 1, true, false, false, false,
495 : handle_tm_wrap_attribute, NULL },
496 : /* For internal use (marking of builtins) only. The name contains space
497 : to prevent its usage in source code. */
498 : { "no vops", 0, 0, true, false, false, false,
499 : handle_novops_attribute, NULL },
500 : { "deprecated", 0, 1, false, false, false, false,
501 : handle_deprecated_attribute, NULL },
502 : { "unavailable", 0, 1, false, false, false, false,
503 : handle_unavailable_attribute, NULL },
504 : { "vector_size", 1, 1, false, true, false, true,
505 : handle_vector_size_attribute, NULL },
506 : { "vector_mask", 0, 0, false, true, false, true,
507 : handle_vector_mask_attribute, NULL },
508 : { "visibility", 1, 1, false, false, false, false,
509 : handle_visibility_attribute, NULL },
510 : { "tls_model", 1, 1, true, false, false, false,
511 : handle_tls_model_attribute, NULL },
512 : { "nonnull", 0, -1, false, true, true, false,
513 : handle_nonnull_attribute, NULL },
514 : { "nonnull_if_nonzero", 2, 3, false, true, true, false,
515 : handle_nonnull_if_nonzero_attribute, NULL },
516 : { "nonstring", 0, 0, true, false, false, false,
517 : handle_nonstring_attribute, NULL },
518 : { "nothrow", 0, 0, true, false, false, false,
519 : handle_nothrow_attribute, NULL },
520 : { "expected_throw", 0, 0, true, false, false, false,
521 : handle_expected_throw_attribute, NULL },
522 : { "may_alias", 0, 0, false, true, false, false, NULL, NULL },
523 : { "cleanup", 1, 1, true, false, false, false,
524 : handle_cleanup_attribute, NULL },
525 : { "warn_unused_result", 0, 0, false, true, true, false,
526 : handle_warn_unused_result_attribute,
527 : attr_warn_unused_result_exclusions },
528 : { "sentinel", 0, 1, false, true, true, false,
529 : handle_sentinel_attribute, NULL },
530 : /* For internal use (marking of builtins) only. The name contains space
531 : to prevent its usage in source code. */
532 : { "type generic", 0, 0, false, true, true, false,
533 : handle_type_generic_attribute, NULL },
534 : { "alloc_size", 1, 2, false, true, true, false,
535 : handle_alloc_size_attribute,
536 : attr_alloc_exclusions },
537 : { "cold", 0, 0, false, false, false, false,
538 : handle_cold_attribute,
539 : attr_cold_hot_exclusions },
540 : { "hot", 0, 0, false, false, false, false,
541 : handle_hot_attribute,
542 : attr_cold_hot_exclusions },
543 : { "no_address_safety_analysis",
544 : 0, 0, true, false, false, false,
545 : handle_no_address_safety_analysis_attribute,
546 : NULL },
547 : { "no_sanitize", 1, -1, true, false, false, false,
548 : handle_no_sanitize_attribute, NULL },
549 : { "no_sanitize_address", 0, 0, true, false, false, false,
550 : handle_no_sanitize_address_attribute, NULL },
551 : { "no_sanitize_thread", 0, 0, true, false, false, false,
552 : handle_no_sanitize_thread_attribute, NULL },
553 : { "no_sanitize_undefined", 0, 0, true, false, false, false,
554 : handle_no_sanitize_undefined_attribute, NULL },
555 : { "no_sanitize_coverage", 0, 0, true, false, false, false,
556 : handle_no_sanitize_coverage_attribute, NULL },
557 : { "asan odr indicator", 0, 0, true, false, false, false,
558 : handle_asan_odr_indicator_attribute, NULL },
559 : { "warning", 1, 1, true, false, false, false,
560 : handle_error_attribute, NULL },
561 : { "error", 1, 1, true, false, false, false,
562 : handle_error_attribute, NULL },
563 : { "target", 1, -1, true, false, false, false,
564 : handle_target_attribute,
565 : attr_target_exclusions },
566 : { "target_version", 1, 1, true, false, false, false,
567 : handle_target_version_attribute,
568 : attr_target_version_exclusions},
569 : { "target_clones", 1, -1, true, false, false, false,
570 : handle_target_clones_attribute,
571 : attr_target_clones_exclusions },
572 : { "optimize", 1, -1, true, false, false, false,
573 : handle_optimize_attribute, NULL },
574 : /* For internal use only. The leading '*' both prevents its usage in
575 : source code and signals that it may be overridden by machine tables. */
576 : { "*tm regparm", 0, 0, false, true, true, false,
577 : ignore_attribute, NULL },
578 : { "no_split_stack", 0, 0, true, false, false, false,
579 : handle_no_split_stack_attribute, NULL },
580 : { "zero_call_used_regs", 1, 1, true, false, false, false,
581 : handle_zero_call_used_regs_attribute, NULL },
582 : /* For internal use only (marking of function arguments).
583 : The name contains a space to prevent its usage in source code. */
584 : { "arg spec", 1, -1, true, false, false, false,
585 : handle_argspec_attribute, NULL },
586 : /* For internal use (marking of builtins and runtime functions) only.
587 : The name contains space to prevent its usage in source code. */
588 : { "fn spec", 1, 1, false, true, true, false,
589 : handle_fnspec_attribute, NULL },
590 : { "warn_unused", 0, 0, false, false, false, false,
591 : handle_warn_unused_attribute, NULL },
592 : { "returns_nonnull", 0, 0, false, true, true, false,
593 : handle_returns_nonnull_attribute, NULL },
594 : { "omp declare simd", 0, -1, true, false, false, false,
595 : handle_omp_declare_simd_attribute,
596 : attr_omp_declare_simd_exclusions },
597 : { "omp declare variant base", 0, -1, true, false, false, false,
598 : handle_omp_declare_variant_attribute, NULL },
599 : { "omp declare variant variant", 0, -1, true, false, false, false,
600 : handle_omp_declare_variant_attribute, NULL },
601 : { "omp declare variant variant args", 0, -1, true, false,
602 : false, false,
603 : handle_omp_declare_variant_attribute, NULL },
604 : { "simd", 0, 1, true, false, false, false,
605 : handle_simd_attribute, attr_simd_exclusions },
606 : { "omp declare target", 0, -1, true, false, false, false,
607 : handle_omp_declare_target_attribute, NULL },
608 : { "omp declare target link", 0, 0, true, false, false, false,
609 : handle_omp_declare_target_attribute, NULL },
610 : { "omp declare target implicit", 0, 0, true, false, false, false,
611 : handle_omp_declare_target_attribute, NULL },
612 : { "omp declare target indirect", 0, 0, true, false, false, false,
613 : handle_omp_declare_target_attribute, NULL },
614 : { "omp declare target host", 0, 0, true, false, false, false,
615 : handle_omp_declare_target_attribute, NULL },
616 : { "omp declare target nohost", 0, 0, true, false, false, false,
617 : handle_omp_declare_target_attribute, NULL },
618 : { "non overlapping", 0, 0, true, false, false, false,
619 : handle_non_overlapping_attribute, NULL },
620 : { "alloc_align", 1, 1, false, true, true, false,
621 : handle_alloc_align_attribute,
622 : attr_alloc_exclusions },
623 : { "assume_aligned", 1, 2, false, true, true, false,
624 : handle_assume_aligned_attribute, NULL },
625 : { "designated_init", 0, 0, false, true, false, false,
626 : handle_designated_init_attribute, NULL },
627 : { "fallthrough", 0, 0, false, false, false, false,
628 : handle_fallthrough_attribute, NULL },
629 : { "assume", 1, 1, false, false, false, false,
630 : handle_assume_attribute, NULL },
631 : { "patchable_function_entry", 1, 2, true, false, false, false,
632 : handle_patchable_function_entry_attribute,
633 : NULL },
634 : { "nocf_check", 0, 0, false, true, true, true,
635 : handle_nocf_check_attribute, NULL },
636 : { "symver", 1, -1, true, false, false, false,
637 : handle_symver_attribute, NULL},
638 : { "copy", 1, 1, false, false, false, false,
639 : handle_copy_attribute, NULL },
640 : { "noinit", 0, 0, true, false, false, false,
641 : handle_special_var_sec_attribute, attr_section_exclusions },
642 : { "persistent", 0, 0, true, false, false, false,
643 : handle_special_var_sec_attribute, attr_section_exclusions },
644 : { "access", 1, 3, false, true, true, false,
645 : handle_access_attribute, NULL },
646 : /* Attributes used by Objective-C. */
647 : { "NSObject", 0, 0, true, false, false, false,
648 : handle_nsobject_attribute, NULL },
649 : { "objc_root_class", 0, 0, true, false, false, false,
650 : handle_objc_root_class_attribute, NULL },
651 : { "objc_nullability", 1, 1, true, false, false, false,
652 : handle_objc_nullability_attribute, NULL },
653 : { "*dealloc", 1, 2, true, false, false, false,
654 : handle_dealloc_attribute, NULL },
655 : { "tainted_args", 0, 0, true, false, false, false,
656 : handle_tainted_args_attribute, NULL },
657 : { "fd_arg", 1, 1, false, true, true, false,
658 : handle_fd_arg_attribute, NULL},
659 : { "fd_arg_read", 1, 1, false, true, true, false,
660 : handle_fd_arg_attribute, NULL},
661 : { "fd_arg_write", 1, 1, false, true, true, false,
662 : handle_fd_arg_attribute, NULL},
663 : { "flag_enum", 0, 0, false, true, false, false,
664 : handle_flag_enum_attribute, NULL },
665 : { "null_terminated_string_arg", 1, 1, false, true, true, false,
666 : handle_null_terminated_string_arg_attribute, NULL},
667 : { "btf_type_tag", 1, 1, false, true, false, false,
668 : handle_btf_type_tag_attribute, NULL},
669 : { "btf_decl_tag", 1, 1, true, false, false, false,
670 : handle_btf_decl_tag_attribute, NULL}
671 : };
672 :
673 : const struct scoped_attribute_specs c_common_gnu_attribute_table =
674 : {
675 : "gnu", { c_common_gnu_attributes }
676 : };
677 :
678 : /* Attributes also recognized in the clang:: namespace. */
679 : const struct attribute_spec c_common_clang_attributes[] = {
680 : { "flag_enum", 0, 0, false, true, false, false,
681 : handle_flag_enum_attribute, NULL },
682 : { "musttail", 0, 0, false, false, false,
683 : false, handle_musttail_attribute, NULL }
684 : };
685 :
686 : const struct scoped_attribute_specs c_common_clang_attribute_table =
687 : {
688 : "clang", { c_common_clang_attributes }
689 : };
690 :
691 : /* Give the specifications for the format attributes, used by C and all
692 : descendants.
693 :
694 : Current list of processed format attributes: format, format_arg. */
695 : const struct attribute_spec c_common_format_attributes[] =
696 : {
697 : /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
698 : affects_type_identity, handler, exclude } */
699 : { "format", 3, 3, false, true, true, false,
700 : handle_format_attribute, NULL },
701 : { "format_arg", 1, 1, false, true, true, false,
702 : handle_format_arg_attribute, NULL }
703 : };
704 :
705 : const struct scoped_attribute_specs c_common_format_attribute_table =
706 : {
707 : "gnu", { c_common_format_attributes }
708 : };
709 :
710 : /* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
711 : identifier as an argument, so the front end shouldn't look it up. */
712 :
713 : bool
714 16140039 : attribute_takes_identifier_p (const_tree attr_id)
715 : {
716 16140039 : const struct attribute_spec *spec = lookup_attribute_spec (attr_id);
717 16140039 : if (spec == NULL)
718 : {
719 : /* Unknown attribute that we'll end up ignoring, return true so we
720 : don't complain about an identifier argument. Except C++
721 : annotations. */
722 36 : if (c_dialect_cxx () && id_equal (attr_id, "annotation "))
723 : return false;
724 36 : return true;
725 : }
726 16140003 : else if (!strcmp ("mode", spec->name)
727 16086028 : || !strcmp ("format", spec->name)
728 15699018 : || !strcmp ("cleanup", spec->name)
729 15698688 : || !strcmp ("access", spec->name)
730 14936027 : || !strcmp ("counted_by", spec->name)
731 14935618 : || !strcmp ("old parm name", spec->name))
732 : return true;
733 : else
734 14935618 : return targetm.attribute_takes_identifier_p (attr_id);
735 : }
736 :
737 : /* Set a musttail attribute MUSTTAIL_P on return expression RETVAL
738 : at LOC. */
739 :
740 : void
741 134969277 : set_musttail_on_return (tree retval, location_t loc, bool musttail_p)
742 : {
743 134969277 : if (retval && musttail_p)
744 : {
745 840 : tree t = retval;
746 840 : if (TREE_CODE (t) == TARGET_EXPR)
747 20 : t = TARGET_EXPR_INITIAL (t);
748 840 : if (TREE_CODE (t) != CALL_EXPR)
749 12 : error_at (loc, "cannot tail-call: return value must be a call");
750 : else
751 828 : CALL_EXPR_MUST_TAIL_CALL (t) = 1;
752 : }
753 134968437 : else if (musttail_p && !retval)
754 8 : error_at (loc, "cannot tail-call: return value must be a call");
755 134969277 : }
756 :
757 : /* Verify that argument value POS at position ARGNO to attribute NAME
758 : applied to function FN (which is either a function declaration or function
759 : type) refers to a function parameter at position POS and the expected type
760 : CODE. Treat CODE == INTEGER_TYPE as matching all C integral types except
761 : bool. If successful, return POS after default conversions (and possibly
762 : adjusted by ADJUST_POS). Otherwise, issue appropriate warnings and return
763 : null. A non-zero 1-based ARGNO should be passed in by callers only for
764 : attributes with more than one argument.
765 :
766 : N.B. This function modifies POS. */
767 :
768 : tree
769 83034182 : positional_argument (const_tree fn, const_tree atname, tree &pos,
770 : tree_code code, int argno /* = 0 */,
771 : int flags /* = posargflags () */)
772 : {
773 83034182 : auto_urlify_attributes sentinel;
774 :
775 83034182 : const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn;
776 83034182 : const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn);
777 83034182 : if (pos && TREE_CODE (pos) != IDENTIFIER_NODE
778 83034182 : && TREE_CODE (pos) != FUNCTION_DECL)
779 83034158 : pos = default_conversion (pos);
780 :
781 83034182 : tree postype = TREE_TYPE (pos);
782 83034182 : if (pos == error_mark_node || !postype)
783 : {
784 : /* Only mention the positional argument number when it's non-zero. */
785 20 : if (argno < 1)
786 9 : warning (OPT_Wattributes,
787 : "%qE attribute argument is invalid", atname);
788 : else
789 11 : warning (OPT_Wattributes,
790 : "%qE attribute argument %i is invalid", atname, argno);
791 :
792 20 : return NULL_TREE;
793 : }
794 :
795 83034162 : if (!INTEGRAL_TYPE_P (postype))
796 : {
797 : /* Handle this case specially to avoid mentioning the value
798 : of pointer constants in diagnostics. Only mention
799 : the positional argument number when it's non-zero. */
800 41 : if (argno < 1)
801 31 : warning (OPT_Wattributes,
802 : "%qE attribute argument has type %qT",
803 : atname, postype);
804 : else
805 10 : warning (OPT_Wattributes,
806 : "%qE attribute argument %i has type %qT",
807 : atname, argno, postype);
808 :
809 41 : return NULL_TREE;
810 : }
811 :
812 83034121 : if (TREE_CODE (pos) != INTEGER_CST)
813 : {
814 : /* Only mention the argument number when it's non-zero. */
815 7 : if (argno < 1)
816 3 : warning (OPT_Wattributes,
817 : "%qE attribute argument value %qE is not an integer "
818 : "constant",
819 : atname, pos);
820 : else
821 4 : warning (OPT_Wattributes,
822 : "%qE attribute argument %i value %qE is not an integer "
823 : "constant",
824 : atname, argno, pos);
825 :
826 7 : return NULL_TREE;
827 : }
828 :
829 : /* Argument positions are 1-based. */
830 83034114 : if (integer_zerop (pos))
831 : {
832 4951529 : if (flags & POSARG_ZERO)
833 : /* Zero is explicitly allowed. */
834 4951516 : return pos;
835 :
836 13 : if (argno < 1)
837 12 : warning (OPT_Wattributes,
838 : "%qE attribute argument value %qE does not refer to "
839 : "a function parameter",
840 : atname, pos);
841 : else
842 1 : warning (OPT_Wattributes,
843 : "%qE attribute argument %i value %qE does not refer to "
844 : "a function parameter",
845 : atname, argno, pos);
846 :
847 13 : return NULL_TREE;
848 : }
849 :
850 78082585 : if (!prototype_p (fntype))
851 123 : return pos;
852 :
853 : /* ADJUST_POS is non-zero in C++ when the function type has invisible
854 : parameters generated by the compiler, such as the in-charge or VTT
855 : parameters. */
856 78082462 : const int adjust_pos = maybe_adjust_arg_pos_for_attribute (fndecl);
857 :
858 : /* Verify that the argument position does not exceed the number
859 : of formal arguments to the function. When POSARG_ELLIPSIS
860 : is set, ARGNO may be beyond the last argument of a vararg
861 : function. */
862 78082462 : unsigned nargs = type_num_arguments (fntype);
863 78082462 : if (!nargs
864 78082456 : || !tree_fits_uhwi_p (pos)
865 78082455 : || ((flags & POSARG_ELLIPSIS) == 0
866 72493651 : && !IN_RANGE (tree_to_uhwi (pos) + adjust_pos, 1, nargs)))
867 : {
868 :
869 30 : if (argno < 1)
870 16 : warning (OPT_Wattributes,
871 : "%qE attribute argument value %qE exceeds the number "
872 : "of function parameters %u",
873 : atname, pos, nargs);
874 : else
875 14 : warning (OPT_Wattributes,
876 : "%qE attribute argument %i value %qE exceeds the number "
877 : "of function parameters %u",
878 : atname, argno, pos, nargs);
879 30 : return NULL_TREE;
880 : }
881 :
882 : /* Verify that the type of the referenced formal argument matches
883 : the expected type. Invisible parameters may have been added by
884 : the compiler, so adjust the position accordingly. */
885 78082432 : unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos) + adjust_pos;
886 :
887 : /* Zero was handled above. */
888 78082432 : gcc_assert (ipos != 0);
889 :
890 78082432 : if (tree argtype = type_argument_type (fntype, ipos))
891 : {
892 72493630 : if (argtype == error_mark_node)
893 : return NULL_TREE;
894 :
895 72493627 : if (flags & POSARG_ELLIPSIS)
896 : {
897 2 : if (argno < 1)
898 0 : error ("%qE attribute argument value %qE does not refer to "
899 : "a variable argument list",
900 : atname, pos);
901 : else
902 2 : error ("%qE attribute argument %i value %qE does not refer to "
903 : "a variable argument list",
904 : atname, argno, pos);
905 2 : return NULL_TREE;
906 : }
907 :
908 : /* Where the expected code is STRING_CST accept any pointer
909 : expected by attribute format (this includes possibly qualified
910 : char pointers and, for targets like Darwin, also pointers to
911 : struct CFString). */
912 72493625 : bool type_match;
913 72493625 : if (code == STRING_CST)
914 11720764 : type_match = valid_format_string_type_p (argtype);
915 60772861 : else if (code == INTEGER_TYPE)
916 : /* For integers, accept enums, wide characters and other types
917 : that match INTEGRAL_TYPE_P except for bool. */
918 18767649 : type_match = (INTEGRAL_TYPE_P (argtype)
919 18767649 : && TREE_CODE (argtype) != BOOLEAN_TYPE);
920 : else
921 42005212 : type_match = TREE_CODE (argtype) == code;
922 :
923 53725976 : if (!type_match)
924 : {
925 73 : if (code == STRING_CST)
926 : {
927 : /* Reject invalid format strings with an error. */
928 24 : if (argno < 1)
929 6 : error ("%qE attribute argument value %qE refers to "
930 : "parameter type %qT",
931 : atname, pos, argtype);
932 : else
933 18 : error ("%qE attribute argument %i value %qE refers to "
934 : "parameter type %qT",
935 : atname, argno, pos, argtype);
936 :
937 24 : return NULL_TREE;
938 : }
939 :
940 49 : if (argno < 1)
941 42 : warning (OPT_Wattributes,
942 : "%qE attribute argument value %qE refers to "
943 : "parameter type %qT",
944 : atname, pos, argtype);
945 : else
946 7 : warning (OPT_Wattributes,
947 : "%qE attribute argument %i value %qE refers to "
948 : "parameter type %qT",
949 : atname, argno, pos, argtype);
950 49 : return NULL_TREE;
951 : }
952 : }
953 5588802 : else if (!(flags & POSARG_ELLIPSIS))
954 : {
955 0 : if (argno < 1)
956 0 : warning (OPT_Wattributes,
957 : "%qE attribute argument value %qE refers to "
958 : "a variadic function parameter of unknown type",
959 : atname, pos);
960 : else
961 0 : warning (OPT_Wattributes,
962 : "%qE attribute argument %i value %qE refers to "
963 : "a variadic function parameter of unknown type",
964 : atname, argno, pos);
965 0 : return NULL_TREE;
966 : }
967 :
968 78082354 : return build_int_cst (TREE_TYPE (pos), ipos);
969 83034182 : }
970 :
971 : /* Return the first of DECL or TYPE attributes installed in NODE if it's
972 : a DECL, or TYPE attributes if it's a TYPE, or null otherwise. */
973 :
974 : static tree
975 2537446 : decl_or_type_attrs (tree node)
976 : {
977 2537446 : if (DECL_P (node))
978 : {
979 130842 : if (tree attrs = DECL_ATTRIBUTES (node))
980 : return attrs;
981 :
982 51151 : tree type = TREE_TYPE (node);
983 51151 : if (type == error_mark_node)
984 : return NULL_TREE;
985 51150 : return TYPE_ATTRIBUTES (type);
986 : }
987 :
988 2406604 : if (TYPE_P (node))
989 2406604 : return TYPE_ATTRIBUTES (node);
990 :
991 : return NULL_TREE;
992 : }
993 :
994 : /* Given a pair of NODEs for arbitrary DECLs or TYPEs, validate one or
995 : two integral or string attribute arguments NEWARGS to be applied to
996 : NODE[0] for the absence of conflicts with the same attribute arguments
997 : already applied to NODE[1]. Issue a warning for conflicts and return
998 : false. Otherwise, when no conflicts are found, return true. */
999 :
1000 : static bool
1001 4814154 : validate_attr_args (tree node[2], tree name, tree newargs[2])
1002 : {
1003 : /* First validate the arguments against those already applied to
1004 : the same declaration (or type). */
1005 4814154 : tree self[2] = { node[0], node[0] };
1006 4814154 : if (node[0] != node[1] && !validate_attr_args (self, name, newargs))
1007 : return false;
1008 :
1009 4814118 : if (!node[1])
1010 : return true;
1011 :
1012 : /* Extract the same attribute from the previous declaration or type. */
1013 2537446 : tree prevattr = decl_or_type_attrs (node[1]);
1014 2537446 : const char* const namestr = IDENTIFIER_POINTER (name);
1015 2537446 : prevattr = lookup_attribute (namestr, prevattr);
1016 2537446 : if (!prevattr)
1017 : return true;
1018 :
1019 : /* Extract one or both attribute arguments. */
1020 25522 : tree prevargs[2];
1021 25522 : prevargs[0] = TREE_VALUE (TREE_VALUE (prevattr));
1022 25522 : prevargs[1] = TREE_CHAIN (TREE_VALUE (prevattr));
1023 25522 : if (prevargs[1])
1024 33 : prevargs[1] = TREE_VALUE (prevargs[1]);
1025 :
1026 : /* Both arguments must be equal or, for the second pair, neither must
1027 : be provided to succeed. */
1028 25522 : bool arg1eq, arg2eq;
1029 25522 : if (TREE_CODE (newargs[0]) == INTEGER_CST)
1030 : {
1031 25513 : arg1eq = tree_int_cst_equal (newargs[0], prevargs[0]);
1032 25513 : if (newargs[1] && prevargs[1])
1033 16 : arg2eq = tree_int_cst_equal (newargs[1], prevargs[1]);
1034 : else
1035 25497 : arg2eq = newargs[1] == prevargs[1];
1036 : }
1037 9 : else if (TREE_CODE (newargs[0]) == STRING_CST)
1038 : {
1039 9 : const char *s0 = TREE_STRING_POINTER (newargs[0]);
1040 9 : const char *s1 = TREE_STRING_POINTER (prevargs[0]);
1041 9 : arg1eq = strcmp (s0, s1) == 0;
1042 9 : if (newargs[1] && prevargs[1])
1043 : {
1044 0 : s0 = TREE_STRING_POINTER (newargs[1]);
1045 0 : s1 = TREE_STRING_POINTER (prevargs[1]);
1046 0 : arg2eq = strcmp (s0, s1) == 0;
1047 : }
1048 : else
1049 9 : arg2eq = newargs[1] == prevargs[1];
1050 : }
1051 : else
1052 0 : gcc_unreachable ();
1053 :
1054 25522 : if (arg1eq && arg2eq)
1055 : return true;
1056 :
1057 : /* If the two locations are different print a note pointing to
1058 : the previous one. */
1059 48 : const location_t curloc = input_location;
1060 48 : const location_t prevloc =
1061 48 : DECL_P (node[1]) ? DECL_SOURCE_LOCATION (node[1]) : curloc;
1062 :
1063 : /* Format the attribute specification for convenience. */
1064 48 : char newspec[80], prevspec[80];
1065 48 : if (newargs[1])
1066 2 : snprintf (newspec, sizeof newspec, "%s (%s, %s)", namestr,
1067 : print_generic_expr_to_str (newargs[0]),
1068 : print_generic_expr_to_str (newargs[1]));
1069 : else
1070 46 : snprintf (newspec, sizeof newspec, "%s (%s)", namestr,
1071 : print_generic_expr_to_str (newargs[0]));
1072 :
1073 48 : if (prevargs[1])
1074 17 : snprintf (prevspec, sizeof prevspec, "%s (%s, %s)", namestr,
1075 : print_generic_expr_to_str (prevargs[0]),
1076 : print_generic_expr_to_str (prevargs[1]));
1077 : else
1078 31 : snprintf (prevspec, sizeof prevspec, "%s (%s)", namestr,
1079 : print_generic_expr_to_str (prevargs[0]));
1080 :
1081 84 : if (warning_at (curloc, OPT_Wattributes,
1082 : "ignoring attribute %qs because it conflicts "
1083 : "with previous %qs",
1084 : newspec, prevspec)
1085 48 : && curloc != prevloc)
1086 12 : inform (prevloc, "previous declaration here");
1087 :
1088 : return false;
1089 : }
1090 :
1091 : /* Convenience wrapper for validate_attr_args to validate a single
1092 : attribute argument. Used by handlers for attributes that take
1093 : just a single argument. */
1094 :
1095 : static bool
1096 95730 : validate_attr_arg (tree node[2], tree name, tree newarg)
1097 : {
1098 95730 : tree argarray[2] = { newarg, NULL_TREE };
1099 0 : return validate_attr_args (node, name, argarray);
1100 : }
1101 :
1102 : /* Attribute handlers common to C front ends. */
1103 :
1104 : /* Handle a "signed_bool_precision" attribute; arguments as in
1105 : struct attribute_spec.handler. */
1106 :
1107 : static tree
1108 2 : handle_signed_bool_precision_attribute (tree *node, tree name, tree args,
1109 : int, bool *no_add_attrs)
1110 : {
1111 2 : *no_add_attrs = true;
1112 2 : if (!flag_gimple)
1113 : {
1114 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1115 0 : return NULL_TREE;
1116 : }
1117 :
1118 2 : if (!TYPE_P (*node) || TREE_CODE (*node) != BOOLEAN_TYPE)
1119 : {
1120 0 : warning (OPT_Wattributes, "%qE attribute only supported on "
1121 : "boolean types", name);
1122 0 : return NULL_TREE;
1123 : }
1124 :
1125 2 : unsigned HOST_WIDE_INT prec = HOST_WIDE_INT_M1U;
1126 2 : if (tree_fits_uhwi_p (TREE_VALUE (args)))
1127 2 : prec = tree_to_uhwi (TREE_VALUE (args));
1128 4 : if (prec > MAX_FIXED_MODE_SIZE)
1129 : {
1130 0 : warning (OPT_Wattributes, "%qE attribute with unsupported boolean "
1131 : "precision", name);
1132 0 : return NULL_TREE;
1133 : }
1134 :
1135 2 : tree new_type = build_nonstandard_boolean_type (prec);
1136 2 : *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
1137 :
1138 2 : return NULL_TREE;
1139 : }
1140 :
1141 : /* Handle a "hardbool" attribute; arguments as in struct
1142 : attribute_spec.handler. */
1143 :
1144 : static tree
1145 492 : handle_hardbool_attribute (tree *node, tree name, tree args,
1146 : int /* flags */, bool *no_add_attrs)
1147 : {
1148 492 : if (c_language != clk_c)
1149 : {
1150 0 : error ("%qE attribute only supported in C", name);
1151 0 : *no_add_attrs = TRUE;
1152 0 : return NULL_TREE;
1153 : }
1154 :
1155 492 : if (!TYPE_P (*node) || TREE_CODE (*node) != INTEGER_TYPE)
1156 : {
1157 5 : error ("%qE attribute only supported on "
1158 : "integral types", name);
1159 5 : *no_add_attrs = TRUE;
1160 5 : return NULL_TREE;
1161 : }
1162 :
1163 487 : tree orig = *node;
1164 : /* Drop qualifiers from the base type. Keep attributes, so that, in the odd
1165 : chance attributes are applicable and relevant to the base type, if they
1166 : are specified first, or through a typedef, they wouldn't be dropped on the
1167 : floor here. */
1168 487 : tree unqual = build_qualified_type (orig, TYPE_UNQUALIFIED);
1169 487 : *node = build_distinct_type_copy (unqual);
1170 :
1171 487 : TREE_SET_CODE (*node, ENUMERAL_TYPE);
1172 487 : ENUM_UNDERLYING_TYPE (*node) = unqual;
1173 487 : SET_TYPE_STRUCTURAL_EQUALITY (*node);
1174 :
1175 487 : tree false_value;
1176 487 : if (args)
1177 481 : false_value = fold_convert (*node, TREE_VALUE (args));
1178 : else
1179 6 : false_value = fold_convert (*node, integer_zero_node);
1180 :
1181 487 : if (TREE_OVERFLOW_P (false_value))
1182 : {
1183 114 : warning (OPT_Wattributes,
1184 : "overflows in conversion from %qT to %qT "
1185 : "changes value from %qE to %qE",
1186 57 : TREE_TYPE (TREE_VALUE (args)), *node,
1187 57 : TREE_VALUE (args), false_value);
1188 57 : TREE_OVERFLOW (false_value) = false;
1189 : }
1190 :
1191 487 : tree true_value;
1192 487 : if (args && TREE_CHAIN (args))
1193 480 : true_value = fold_convert (*node, TREE_VALUE (TREE_CHAIN (args)));
1194 : else
1195 7 : true_value = fold_build1 (BIT_NOT_EXPR, *node, false_value);
1196 :
1197 487 : if (TREE_OVERFLOW_P (true_value))
1198 : {
1199 57 : warning (OPT_Wattributes,
1200 : "overflows in conversion from %qT to %qT "
1201 : "changes value from %qE to %qE",
1202 57 : TREE_TYPE (TREE_VALUE (TREE_CHAIN (args))), *node,
1203 57 : TREE_VALUE (TREE_CHAIN (args)), true_value);
1204 57 : TREE_OVERFLOW (true_value) = false;
1205 : }
1206 :
1207 487 : if (tree_int_cst_compare (false_value, true_value) == 0)
1208 : {
1209 2 : error ("%qE attribute requires different values for"
1210 : " %<false%> and %<true%> for type %qT",
1211 : name, *node);
1212 2 : *no_add_attrs = TRUE;
1213 2 : return NULL_TREE;
1214 : }
1215 :
1216 485 : tree values = build_tree_list (get_identifier ("false"),
1217 : false_value);
1218 485 : TREE_CHAIN (values) = build_tree_list (get_identifier ("true"),
1219 : true_value);
1220 :
1221 : /* Do *not* set TYPE_MIN_VALUE, TYPE_MAX_VALUE, nor TYPE_PRECISION according
1222 : to the false and true values. That might cause the constants to be the
1223 : only acceptable values, which would drop the very hardening checks this
1224 : attribute is supposed to add. */
1225 :
1226 485 : TYPE_ATTRIBUTES (*node) = tree_cons (name, args,
1227 485 : TYPE_ATTRIBUTES (*node));
1228 485 : *no_add_attrs = TRUE;
1229 :
1230 485 : gcc_checking_assert (!TYPE_CACHED_VALUES_P (*node));
1231 485 : TYPE_VALUES (*node) = values;
1232 :
1233 485 : if (TYPE_QUALS (orig) != TYPE_QUALS (*node))
1234 14 : *node = build_qualified_type (*node, TYPE_QUALS (orig));
1235 :
1236 485 : if (TREE_CODE (orig) == TYPE_DECL)
1237 0 : TYPE_NAME (*node) = TYPE_NAME (orig);
1238 : else
1239 485 : TYPE_NAME (*node) = NULL_TREE;
1240 :
1241 : return NULL_TREE;
1242 : }
1243 :
1244 : /* Handle a "packed" attribute; arguments as in
1245 : struct attribute_spec.handler. */
1246 :
1247 : static tree
1248 5445 : handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1249 : int flags, bool *no_add_attrs)
1250 : {
1251 5445 : if (TYPE_P (*node))
1252 : {
1253 2529 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1254 : {
1255 68 : warning (OPT_Wattributes,
1256 : "%qE attribute ignored for type %qT", name, *node);
1257 68 : *no_add_attrs = true;
1258 : }
1259 : else
1260 2461 : TYPE_PACKED (*node) = 1;
1261 : }
1262 2916 : else if (TREE_CODE (*node) == FIELD_DECL)
1263 : {
1264 2904 : if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
1265 : /* Still pack bitfields. */
1266 2904 : && ! DECL_C_BIT_FIELD (*node))
1267 448 : warning (OPT_Wattributes,
1268 : "%qE attribute ignored for field of type %qT",
1269 448 : name, TREE_TYPE (*node));
1270 : else
1271 2456 : DECL_PACKED (*node) = 1;
1272 : }
1273 : /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
1274 : used for DECL_REGISTER. It wouldn't mean anything anyway.
1275 : We can't set DECL_PACKED on the type of a TYPE_DECL, because
1276 : that changes what the typedef is typing. */
1277 : else
1278 : {
1279 12 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1280 12 : *no_add_attrs = true;
1281 : }
1282 :
1283 5445 : return NULL_TREE;
1284 : }
1285 :
1286 : /* Handle a "nocommon" attribute; arguments as in
1287 : struct attribute_spec.handler. */
1288 :
1289 : static tree
1290 11 : handle_nocommon_attribute (tree *node, tree name,
1291 : tree ARG_UNUSED (args),
1292 : int ARG_UNUSED (flags), bool *no_add_attrs)
1293 : {
1294 11 : if (VAR_P (*node))
1295 11 : DECL_COMMON (*node) = 0;
1296 : else
1297 : {
1298 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1299 0 : *no_add_attrs = true;
1300 : }
1301 :
1302 11 : return NULL_TREE;
1303 : }
1304 :
1305 : /* Handle a "common" attribute; arguments as in
1306 : struct attribute_spec.handler. */
1307 :
1308 : static tree
1309 41 : handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1310 : int ARG_UNUSED (flags), bool *no_add_attrs)
1311 : {
1312 41 : if (VAR_P (*node))
1313 37 : DECL_COMMON (*node) = 1;
1314 : else
1315 : {
1316 4 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1317 4 : *no_add_attrs = true;
1318 : }
1319 :
1320 41 : return NULL_TREE;
1321 : }
1322 :
1323 : /* Handle a "musttail" attribute; arguments as in
1324 : struct attribute_spec.handler. */
1325 :
1326 : tree
1327 3 : handle_musttail_attribute (tree ARG_UNUSED (*node), tree name, tree ARG_UNUSED (args),
1328 : int ARG_UNUSED (flags), bool *no_add_attrs)
1329 : {
1330 : /* Currently only a statement attribute, handled directly in parser. */
1331 3 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1332 3 : *no_add_attrs = true;
1333 3 : return NULL_TREE;
1334 : }
1335 :
1336 : /* Handle a "noreturn" attribute; arguments as in
1337 : struct attribute_spec.handler. */
1338 :
1339 : tree
1340 3944578 : handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1341 : int ARG_UNUSED (flags), bool *no_add_attrs)
1342 : {
1343 3944578 : tree type = TREE_TYPE (*node);
1344 :
1345 : /* See FIXME comment in c_common_attribute_table. */
1346 3944578 : if (TREE_CODE (*node) == FUNCTION_DECL
1347 3944578 : || objc_method_decl (TREE_CODE (*node)))
1348 3944421 : TREE_THIS_VOLATILE (*node) = 1;
1349 157 : else if (TREE_CODE (type) == POINTER_TYPE
1350 157 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
1351 47 : TREE_TYPE (*node)
1352 47 : = (build_qualified_type
1353 47 : (build_pointer_type
1354 94 : (build_type_variant (TREE_TYPE (type),
1355 : TYPE_READONLY (TREE_TYPE (type)), 1)),
1356 47 : TYPE_QUALS (type)));
1357 : else
1358 : {
1359 110 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1360 110 : *no_add_attrs = true;
1361 : }
1362 :
1363 3944578 : return NULL_TREE;
1364 : }
1365 :
1366 : /* Handle a "hot" and attribute; arguments as in
1367 : struct attribute_spec.handler. */
1368 :
1369 : static tree
1370 162 : handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1371 : int ARG_UNUSED (flags), bool *no_add_attrs)
1372 : {
1373 162 : if (TREE_CODE (*node) == FUNCTION_DECL
1374 162 : || TREE_CODE (*node) == LABEL_DECL)
1375 : {
1376 : /* Attribute hot processing is done later with lookup_attribute. */
1377 : }
1378 9 : else if ((TREE_CODE (*node) == RECORD_TYPE
1379 9 : || TREE_CODE (*node) == UNION_TYPE)
1380 6 : && c_dialect_cxx ()
1381 6 : && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1382 : {
1383 : /* Check conflict here as decl_attributes will otherwise only catch
1384 : it late at the function when the attribute is used on a class. */
1385 6 : tree cold_attr = lookup_attribute ("cold", TYPE_ATTRIBUTES (*node));
1386 6 : if (cold_attr)
1387 : {
1388 0 : warning (OPT_Wattributes, "ignoring attribute %qE because it "
1389 : "conflicts with attribute %qs", name, "cold");
1390 0 : *no_add_attrs = true;
1391 : }
1392 : }
1393 3 : else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
1394 : | (int) ATTR_FLAG_DECL_NEXT))
1395 : {
1396 : /* Avoid applying the attribute to a function return type when
1397 : used as: void __attribute ((hot)) foo (void). It will be
1398 : passed to the function. */
1399 3 : *no_add_attrs = true;
1400 : }
1401 : else
1402 : {
1403 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1404 0 : *no_add_attrs = true;
1405 : }
1406 :
1407 162 : return NULL_TREE;
1408 : }
1409 :
1410 : /* Handle a "cold" and attribute; arguments as in
1411 : struct attribute_spec.handler. */
1412 :
1413 : static tree
1414 1824725 : handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1415 : int ARG_UNUSED (flags), bool *no_add_attrs)
1416 : {
1417 1824725 : if (TREE_CODE (*node) == FUNCTION_DECL
1418 1824725 : || TREE_CODE (*node) == LABEL_DECL)
1419 : {
1420 : /* Attribute cold processing is done later with lookup_attribute. */
1421 : }
1422 28 : else if ((TREE_CODE (*node) == RECORD_TYPE
1423 28 : || TREE_CODE (*node) == UNION_TYPE)
1424 6 : && c_dialect_cxx ()
1425 6 : && (flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1426 : {
1427 : /* Check conflict here as decl_attributes will otherwise only catch
1428 : it late at the function when the attribute is used on a class. */
1429 6 : tree hot_attr = lookup_attribute ("hot", TYPE_ATTRIBUTES (*node));
1430 6 : if (hot_attr)
1431 : {
1432 0 : warning (OPT_Wattributes, "ignoring attribute %qE because it "
1433 : "conflicts with attribute %qs", name, "hot");
1434 0 : *no_add_attrs = true;
1435 : }
1436 : }
1437 22 : else if (flags & ((int) ATTR_FLAG_FUNCTION_NEXT
1438 : | (int) ATTR_FLAG_DECL_NEXT))
1439 : {
1440 : /* Avoid applying the attribute to a function return type when
1441 : used as: void __attribute ((cold)) foo (void). It will be
1442 : passed to the function. */
1443 0 : *no_add_attrs = true;
1444 : }
1445 : else
1446 : {
1447 22 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1448 22 : *no_add_attrs = true;
1449 : }
1450 :
1451 1824725 : return NULL_TREE;
1452 : }
1453 :
1454 : /* Add FLAGS for a function NODE to no_sanitize_flags in DECL_ATTRIBUTES. */
1455 :
1456 : void
1457 582 : add_no_sanitize_value (tree node, sanitize_code_type flags)
1458 : {
1459 582 : tree attr = lookup_attribute ("no_sanitize", DECL_ATTRIBUTES (node));
1460 582 : if (attr)
1461 : {
1462 21 : sanitize_code_type old_value =
1463 21 : tree_to_sanitize_code_type (TREE_VALUE (attr));
1464 21 : flags |= old_value;
1465 :
1466 21 : if (flags == old_value)
1467 : return;
1468 :
1469 7 : TREE_VALUE (attr) = build_int_cst (uint64_type_node, flags);
1470 : }
1471 : else
1472 561 : DECL_ATTRIBUTES (node)
1473 1122 : = tree_cons (get_identifier ("no_sanitize"),
1474 561 : build_int_cst (uint64_type_node, flags),
1475 561 : DECL_ATTRIBUTES (node));
1476 : }
1477 :
1478 : /* Handle a "no_sanitize" attribute; arguments as in
1479 : struct attribute_spec.handler. */
1480 :
1481 : static tree
1482 220 : handle_no_sanitize_attribute (tree *node, tree name, tree args, int,
1483 : bool *no_add_attrs)
1484 : {
1485 220 : sanitize_code_type flags = 0;
1486 220 : *no_add_attrs = true;
1487 220 : if (TREE_CODE (*node) != FUNCTION_DECL)
1488 : {
1489 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1490 0 : return NULL_TREE;
1491 : }
1492 :
1493 500 : for (; args; args = TREE_CHAIN (args))
1494 : {
1495 280 : tree id = TREE_VALUE (args);
1496 280 : if (TREE_CODE (id) != STRING_CST)
1497 : {
1498 0 : error ("%qE argument not a string", name);
1499 0 : return NULL_TREE;
1500 : }
1501 :
1502 280 : char *string = ASTRDUP (TREE_STRING_POINTER (id));
1503 280 : flags |= parse_no_sanitize_attribute (string);
1504 : }
1505 :
1506 220 : add_no_sanitize_value (*node, flags);
1507 :
1508 220 : return NULL_TREE;
1509 : }
1510 :
1511 : /* Handle a "no_sanitize_address" attribute; arguments as in
1512 : struct attribute_spec.handler. */
1513 :
1514 : static tree
1515 156 : handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
1516 : bool *no_add_attrs)
1517 : {
1518 156 : *no_add_attrs = true;
1519 156 : if (TREE_CODE (*node) != FUNCTION_DECL)
1520 14 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1521 : else
1522 142 : add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_ADDRESS);
1523 :
1524 156 : return NULL_TREE;
1525 : }
1526 :
1527 : /* Handle a "no_sanitize_thread" attribute; arguments as in
1528 : struct attribute_spec.handler. */
1529 :
1530 : static tree
1531 24 : handle_no_sanitize_thread_attribute (tree *node, tree name, tree, int,
1532 : bool *no_add_attrs)
1533 : {
1534 24 : *no_add_attrs = true;
1535 24 : if (TREE_CODE (*node) != FUNCTION_DECL)
1536 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1537 : else
1538 24 : add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_THREAD);
1539 :
1540 24 : return NULL_TREE;
1541 : }
1542 :
1543 :
1544 : /* Handle a "no_address_safety_analysis" attribute; arguments as in
1545 : struct attribute_spec.handler. */
1546 :
1547 : static tree
1548 28 : handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
1549 : bool *no_add_attrs)
1550 : {
1551 28 : *no_add_attrs = true;
1552 28 : if (TREE_CODE (*node) != FUNCTION_DECL)
1553 14 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1554 : else
1555 14 : add_no_sanitize_value (*node, (sanitize_code_type) SANITIZE_ADDRESS);
1556 :
1557 28 : return NULL_TREE;
1558 : }
1559 :
1560 : /* Handle a "no_sanitize_undefined" attribute; arguments as in
1561 : struct attribute_spec.handler. */
1562 :
1563 : static tree
1564 145 : handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
1565 : bool *no_add_attrs)
1566 : {
1567 145 : *no_add_attrs = true;
1568 145 : if (TREE_CODE (*node) != FUNCTION_DECL)
1569 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1570 : else
1571 145 : add_no_sanitize_value (*node,
1572 : SANITIZE_UNDEFINED | SANITIZE_UNDEFINED_NONDEFAULT);
1573 :
1574 145 : return NULL_TREE;
1575 : }
1576 :
1577 : /* Handle a "no_sanitize_coverage" attribute; arguments as in
1578 : struct attribute_spec.handler. */
1579 :
1580 : static tree
1581 16 : handle_no_sanitize_coverage_attribute (tree *node, tree name, tree, int,
1582 : bool *no_add_attrs)
1583 : {
1584 16 : if (TREE_CODE (*node) != FUNCTION_DECL)
1585 : {
1586 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1587 0 : *no_add_attrs = true;
1588 : }
1589 :
1590 16 : return NULL_TREE;
1591 : }
1592 :
1593 : /* Handle an "asan odr indicator" attribute; arguments as in
1594 : struct attribute_spec.handler. */
1595 :
1596 : static tree
1597 0 : handle_asan_odr_indicator_attribute (tree *, tree, tree, int, bool *)
1598 : {
1599 0 : return NULL_TREE;
1600 : }
1601 :
1602 : /* Handle a "stack_protect" attribute; arguments as in
1603 : struct attribute_spec.handler. */
1604 :
1605 : static tree
1606 10 : handle_stack_protect_attribute (tree *node, tree name, tree, int,
1607 : bool *no_add_attrs)
1608 : {
1609 10 : if (TREE_CODE (*node) != FUNCTION_DECL)
1610 : {
1611 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1612 0 : *no_add_attrs = true;
1613 : }
1614 :
1615 10 : return NULL_TREE;
1616 : }
1617 :
1618 : /* Handle a "no_stack_protector" attribute; arguments as in
1619 : struct attribute_spec.handler. */
1620 :
1621 : static tree
1622 9 : handle_no_stack_protector_function_attribute (tree *node, tree name, tree,
1623 : int, bool *no_add_attrs)
1624 : {
1625 9 : if (TREE_CODE (*node) != FUNCTION_DECL)
1626 : {
1627 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1628 0 : *no_add_attrs = true;
1629 : }
1630 :
1631 9 : return NULL_TREE;
1632 : }
1633 :
1634 : /* Handle a "noipa" attribute; arguments as in
1635 : struct attribute_spec.handler. */
1636 :
1637 : static tree
1638 18797 : handle_noipa_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1639 : {
1640 18797 : if (TREE_CODE (*node) != FUNCTION_DECL)
1641 : {
1642 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1643 0 : *no_add_attrs = true;
1644 : }
1645 :
1646 18797 : return NULL_TREE;
1647 : }
1648 :
1649 : /* Handle a "strub" attribute; arguments as in
1650 : struct attribute_spec.handler. */
1651 :
1652 : static tree
1653 2839 : handle_strub_attribute (tree *node, tree name,
1654 : tree args,
1655 : int ARG_UNUSED (flags), bool *no_add_attrs)
1656 : {
1657 2839 : bool enable = true;
1658 :
1659 2839 : if (args && FUNCTION_POINTER_TYPE_P (*node))
1660 134 : *node = TREE_TYPE (*node);
1661 :
1662 2839 : if (args && FUNC_OR_METHOD_TYPE_P (*node))
1663 : {
1664 2174 : switch (strub_validate_fn_attr_parm (TREE_VALUE (args)))
1665 : {
1666 : case 1:
1667 : case 2:
1668 : enable = true;
1669 : break;
1670 :
1671 0 : case 0:
1672 0 : warning (OPT_Wattributes,
1673 : "%qE attribute ignored because of argument %qE",
1674 0 : name, TREE_VALUE (args));
1675 0 : *no_add_attrs = true;
1676 0 : enable = false;
1677 0 : break;
1678 :
1679 : case -1:
1680 : case -2:
1681 1034 : enable = false;
1682 : break;
1683 :
1684 0 : default:
1685 0 : gcc_unreachable ();
1686 : }
1687 :
1688 2174 : args = TREE_CHAIN (args);
1689 : }
1690 :
1691 2174 : if (args)
1692 : {
1693 0 : warning (OPT_Wattributes,
1694 : "ignoring attribute %qE because of excess arguments"
1695 : " starting at %qE",
1696 0 : name, TREE_VALUE (args));
1697 0 : *no_add_attrs = true;
1698 0 : enable = false;
1699 : }
1700 :
1701 : /* Warn about unmet expectations that the strub attribute works like a
1702 : qualifier. ??? Could/should we extend it to the element/field types
1703 : here? */
1704 2839 : if (TREE_CODE (*node) == ARRAY_TYPE
1705 : || VECTOR_TYPE_P (*node)
1706 2839 : || TREE_CODE (*node) == COMPLEX_TYPE)
1707 8 : warning (OPT_Wattributes,
1708 : "attribute %qE does not apply to elements"
1709 : " of non-scalar type %qT",
1710 : name, *node);
1711 2831 : else if (RECORD_OR_UNION_TYPE_P (*node))
1712 4 : warning (OPT_Wattributes,
1713 : "attribute %qE does not apply to fields"
1714 : " of aggregate type %qT",
1715 : name, *node);
1716 :
1717 : /* If we see a strub-enabling attribute, and we're at the default setting,
1718 : implicitly or explicitly, note that the attribute was seen, so that we can
1719 : reduce the compile-time overhead to nearly zero when the strub feature is
1720 : not used. */
1721 2839 : if (enable && flag_strub < -2)
1722 585 : flag_strub += 2;
1723 :
1724 2839 : return NULL_TREE;
1725 : }
1726 :
1727 : /* Handle a "noinline" attribute; arguments as in
1728 : struct attribute_spec.handler. */
1729 :
1730 : static tree
1731 861502 : handle_noinline_attribute (tree *node, tree name,
1732 : tree ARG_UNUSED (args),
1733 : int ARG_UNUSED (flags), bool *no_add_attrs)
1734 : {
1735 861502 : if (TREE_CODE (*node) == FUNCTION_DECL)
1736 861494 : DECL_UNINLINABLE (*node) = 1;
1737 : else
1738 : {
1739 8 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1740 8 : *no_add_attrs = true;
1741 : }
1742 :
1743 861502 : return NULL_TREE;
1744 : }
1745 :
1746 : /* Handle a "noclone" attribute; arguments as in
1747 : struct attribute_spec.handler. */
1748 :
1749 : static tree
1750 147256 : handle_noclone_attribute (tree *node, tree name,
1751 : tree ARG_UNUSED (args),
1752 : int ARG_UNUSED (flags), bool *no_add_attrs)
1753 : {
1754 147256 : if (TREE_CODE (*node) != FUNCTION_DECL)
1755 : {
1756 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1757 0 : *no_add_attrs = true;
1758 : }
1759 :
1760 147256 : return NULL_TREE;
1761 : }
1762 :
1763 : /* Handle a "nocf_check" attribute; arguments as in
1764 : struct attribute_spec.handler. */
1765 :
1766 : static tree
1767 99 : handle_nocf_check_attribute (tree *node, tree name,
1768 : tree ARG_UNUSED (args),
1769 : int ARG_UNUSED (flags), bool *no_add_attrs)
1770 : {
1771 99 : if (TREE_CODE (*node) != FUNCTION_TYPE
1772 99 : && TREE_CODE (*node) != METHOD_TYPE)
1773 : {
1774 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1775 0 : *no_add_attrs = true;
1776 : }
1777 99 : else if (!(flag_cf_protection & CF_BRANCH))
1778 : {
1779 34 : warning (OPT_Wattributes, "%qE attribute ignored. Use "
1780 : "%<-fcf-protection%> option to enable it",
1781 : name);
1782 34 : *no_add_attrs = true;
1783 : }
1784 :
1785 99 : return NULL_TREE;
1786 : }
1787 :
1788 : /* Handle a "no_icf" attribute; arguments as in
1789 : struct attribute_spec.handler. */
1790 :
1791 : static tree
1792 18812 : handle_noicf_attribute (tree *node, tree name,
1793 : tree ARG_UNUSED (args),
1794 : int ARG_UNUSED (flags), bool *no_add_attrs)
1795 : {
1796 18812 : if (TREE_CODE (*node) != FUNCTION_DECL
1797 18812 : && (TREE_CODE (*node) != VAR_DECL || !is_global_var (*node)))
1798 : {
1799 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1800 0 : *no_add_attrs = true;
1801 : }
1802 :
1803 18812 : return NULL_TREE;
1804 : }
1805 :
1806 :
1807 : /* Handle a "always_inline" attribute; arguments as in
1808 : struct attribute_spec.handler. */
1809 :
1810 : static tree
1811 41368134 : handle_always_inline_attribute (tree *node, tree name,
1812 : tree ARG_UNUSED (args),
1813 : int ARG_UNUSED (flags),
1814 : bool *no_add_attrs)
1815 : {
1816 41368134 : if (TREE_CODE (*node) == FUNCTION_DECL)
1817 : {
1818 : /* Set the attribute and mark it for disregarding inline
1819 : limits. */
1820 41368134 : DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
1821 : }
1822 : else
1823 : {
1824 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1825 0 : *no_add_attrs = true;
1826 : }
1827 :
1828 41368134 : return NULL_TREE;
1829 : }
1830 :
1831 : /* Handle a "gnu_inline" attribute; arguments as in
1832 : struct attribute_spec.handler. */
1833 :
1834 : static tree
1835 37296500 : handle_gnu_inline_attribute (tree *node, tree name,
1836 : tree ARG_UNUSED (args),
1837 : int ARG_UNUSED (flags),
1838 : bool *no_add_attrs)
1839 : {
1840 37296500 : if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
1841 : {
1842 : /* Do nothing else, just set the attribute. We'll get at
1843 : it later with lookup_attribute. */
1844 : }
1845 : else
1846 : {
1847 67046 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1848 67046 : *no_add_attrs = true;
1849 : }
1850 :
1851 37296500 : return NULL_TREE;
1852 : }
1853 :
1854 : /* Handle a "leaf" attribute; arguments as in
1855 : struct attribute_spec.handler. */
1856 :
1857 : static tree
1858 424774959 : handle_leaf_attribute (tree *node, tree name,
1859 : tree ARG_UNUSED (args),
1860 : int ARG_UNUSED (flags), bool *no_add_attrs)
1861 : {
1862 424774959 : if (TREE_CODE (*node) != FUNCTION_DECL)
1863 : {
1864 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1865 0 : *no_add_attrs = true;
1866 : }
1867 424774959 : if (!TREE_PUBLIC (*node))
1868 : {
1869 7 : warning (OPT_Wattributes, "%qE attribute has no effect on unit local "
1870 : "functions", name);
1871 7 : *no_add_attrs = true;
1872 : }
1873 :
1874 424774959 : return NULL_TREE;
1875 : }
1876 :
1877 : /* Handle an "artificial" attribute; arguments as in
1878 : struct attribute_spec.handler. */
1879 :
1880 : static tree
1881 36693181 : handle_artificial_attribute (tree *node, tree name,
1882 : tree ARG_UNUSED (args),
1883 : int ARG_UNUSED (flags),
1884 : bool *no_add_attrs)
1885 : {
1886 36693181 : if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
1887 : {
1888 : /* Do nothing else, just set the attribute. We'll get at
1889 : it later with lookup_attribute. */
1890 : }
1891 : else
1892 : {
1893 67046 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1894 67046 : *no_add_attrs = true;
1895 : }
1896 :
1897 36693181 : return NULL_TREE;
1898 : }
1899 :
1900 : /* Handle a "flatten" attribute; arguments as in
1901 : struct attribute_spec.handler. */
1902 :
1903 : static tree
1904 146 : handle_flatten_attribute (tree *node, tree name,
1905 : tree args ATTRIBUTE_UNUSED,
1906 : int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1907 : {
1908 146 : if (TREE_CODE (*node) == FUNCTION_DECL)
1909 : /* Do nothing else, just set the attribute. We'll get at
1910 : it later with lookup_attribute. */
1911 : ;
1912 : else
1913 : {
1914 4 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1915 4 : *no_add_attrs = true;
1916 : }
1917 :
1918 146 : return NULL_TREE;
1919 : }
1920 :
1921 : /* Handle a "warning" or "error" attribute; arguments as in
1922 : struct attribute_spec.handler. */
1923 :
1924 : static tree
1925 102 : handle_error_attribute (tree *node, tree name, tree args,
1926 : int ARG_UNUSED (flags), bool *no_add_attrs)
1927 : {
1928 102 : if (TREE_CODE (*node) == FUNCTION_DECL
1929 203 : && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1930 : /* Do nothing else, just set the attribute. We'll get at
1931 : it later with lookup_attribute. */
1932 : ;
1933 : else
1934 : {
1935 3 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1936 3 : *no_add_attrs = true;
1937 : }
1938 :
1939 102 : return NULL_TREE;
1940 : }
1941 :
1942 : /* Handle a "used" attribute; arguments as in
1943 : struct attribute_spec.handler. */
1944 :
1945 : static tree
1946 1783 : handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
1947 : int ARG_UNUSED (flags), bool *no_add_attrs)
1948 : {
1949 1783 : tree node = *pnode;
1950 :
1951 1783 : if (TREE_CODE (node) == FUNCTION_DECL
1952 958 : || (VAR_P (node) && TREE_STATIC (node))
1953 34 : || (TREE_CODE (node) == TYPE_DECL))
1954 : {
1955 1764 : TREE_USED (node) = 1;
1956 1764 : DECL_PRESERVE_P (node) = 1;
1957 1764 : if (VAR_P (node))
1958 924 : DECL_READ_P (node) = 1;
1959 : }
1960 : else
1961 : {
1962 19 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1963 19 : *no_add_attrs = true;
1964 : }
1965 :
1966 1783 : return NULL_TREE;
1967 : }
1968 :
1969 : /* Handle a "unused" attribute; arguments as in
1970 : struct attribute_spec.handler. */
1971 :
1972 : tree
1973 772566 : handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1974 : int flags, bool *no_add_attrs)
1975 : {
1976 772566 : if (DECL_P (*node))
1977 : {
1978 772412 : tree decl = *node;
1979 :
1980 772412 : if (TREE_CODE (decl) == PARM_DECL
1981 497016 : || VAR_OR_FUNCTION_DECL_P (decl)
1982 118377 : || TREE_CODE (decl) == LABEL_DECL
1983 118296 : || TREE_CODE (decl) == CONST_DECL
1984 278 : || TREE_CODE (decl) == FIELD_DECL
1985 258 : || TREE_CODE (decl) == TYPE_DECL)
1986 : {
1987 772411 : TREE_USED (decl) = 1;
1988 772411 : if (VAR_P (decl) || TREE_CODE (decl) == PARM_DECL)
1989 499033 : DECL_READ_P (decl) = 1;
1990 : }
1991 : else
1992 : {
1993 1 : warning (OPT_Wattributes, "%qE attribute ignored", name);
1994 1 : *no_add_attrs = true;
1995 : }
1996 : }
1997 : else
1998 : {
1999 154 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2000 85 : *node = build_variant_type_copy (*node);
2001 154 : TREE_USED (*node) = 1;
2002 : }
2003 :
2004 772566 : return NULL_TREE;
2005 : }
2006 :
2007 : /* Handle a "retain" attribute; arguments as in
2008 : struct attribute_spec.handler. */
2009 :
2010 : static tree
2011 262 : handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
2012 : int ARG_UNUSED (flags), bool *no_add_attrs)
2013 : {
2014 262 : tree node = *pnode;
2015 :
2016 262 : if (SUPPORTS_SHF_GNU_RETAIN
2017 262 : && (TREE_CODE (node) == FUNCTION_DECL
2018 186 : || (VAR_P (node) && TREE_STATIC (node))))
2019 : ;
2020 : else
2021 : {
2022 4 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2023 4 : *no_add_attrs = true;
2024 : }
2025 :
2026 262 : return NULL_TREE;
2027 : }
2028 :
2029 : /* Handle an "uninitialized" attribute; arguments as in
2030 : struct attribute_spec.handler. */
2031 :
2032 : static tree
2033 7358 : handle_uninitialized_attribute (tree *node, tree name, tree ARG_UNUSED (args),
2034 : int ARG_UNUSED (flags), bool *no_add_attrs)
2035 : {
2036 7358 : tree decl = *node;
2037 7358 : if (!VAR_P (decl))
2038 : {
2039 8 : warning (OPT_Wattributes, "%qE attribute ignored because %qD "
2040 : "is not a variable", name, decl);
2041 8 : *no_add_attrs = true;
2042 : }
2043 7350 : else if (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
2044 : {
2045 24 : warning (OPT_Wattributes, "%qE attribute ignored because %qD "
2046 : "is not a local variable", name, decl);
2047 24 : *no_add_attrs = true;
2048 : }
2049 :
2050 7358 : return NULL_TREE;
2051 : }
2052 :
2053 : /* Handle a "externally_visible" attribute; arguments as in
2054 : struct attribute_spec.handler. */
2055 :
2056 : static tree
2057 259878 : handle_externally_visible_attribute (tree *pnode, tree name,
2058 : tree ARG_UNUSED (args),
2059 : int ARG_UNUSED (flags),
2060 : bool *no_add_attrs)
2061 : {
2062 259878 : tree node = *pnode;
2063 :
2064 259878 : if (VAR_OR_FUNCTION_DECL_P (node))
2065 : {
2066 259836 : if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
2067 519710 : && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
2068 : {
2069 17 : warning (OPT_Wattributes,
2070 : "%qE attribute have effect only on public objects", name);
2071 17 : *no_add_attrs = true;
2072 : }
2073 : }
2074 : else
2075 : {
2076 4 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2077 4 : *no_add_attrs = true;
2078 : }
2079 :
2080 259878 : return NULL_TREE;
2081 : }
2082 :
2083 : /* Handle the "no_reorder" attribute. Arguments as in
2084 : struct attribute_spec.handler. */
2085 :
2086 : static tree
2087 17 : handle_no_reorder_attribute (tree *pnode,
2088 : tree name,
2089 : tree,
2090 : int,
2091 : bool *no_add_attrs)
2092 : {
2093 17 : tree node = *pnode;
2094 :
2095 15 : if (!VAR_OR_FUNCTION_DECL_P (node)
2096 17 : && !(TREE_STATIC (node) || DECL_EXTERNAL (node)))
2097 : {
2098 0 : warning (OPT_Wattributes,
2099 : "%qE attribute only affects top level objects",
2100 : name);
2101 0 : *no_add_attrs = true;
2102 : }
2103 :
2104 17 : return NULL_TREE;
2105 : }
2106 :
2107 : /* Handle a "const" attribute; arguments as in
2108 : struct attribute_spec.handler. */
2109 :
2110 : static tree
2111 181210579 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
2112 : int flags, bool *no_add_attrs)
2113 : {
2114 181210579 : tree type = TREE_TYPE (*node);
2115 :
2116 : /* See FIXME comment on noreturn in c_common_attribute_table. */
2117 181210579 : if (TREE_CODE (*node) == FUNCTION_DECL)
2118 181210543 : TREE_READONLY (*node) = 1;
2119 36 : else if (TREE_CODE (type) == POINTER_TYPE
2120 36 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
2121 31 : TREE_TYPE (*node)
2122 31 : = (build_qualified_type
2123 31 : (build_pointer_type
2124 62 : (build_type_variant (TREE_TYPE (type), 1,
2125 : TREE_THIS_VOLATILE (TREE_TYPE (type)))),
2126 31 : TYPE_QUALS (type)));
2127 : else
2128 : {
2129 5 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2130 5 : *no_add_attrs = true;
2131 : }
2132 :
2133 : /* void __builtin_unreachable(void) is const. Accept other such
2134 : built-ins but warn on user-defined functions that return void. */
2135 181210579 : if (!(flags & ATTR_FLAG_BUILT_IN)
2136 3045952 : && TREE_CODE (*node) == FUNCTION_DECL
2137 184256495 : && VOID_TYPE_P (TREE_TYPE (type)))
2138 14 : warning (OPT_Wattributes, "%qE attribute on function "
2139 : "returning %<void%>", name);
2140 :
2141 181210579 : return NULL_TREE;
2142 : }
2143 :
2144 : /* Handle a "scalar_storage_order" attribute; arguments as in
2145 : struct attribute_spec.handler. */
2146 :
2147 : static tree
2148 896 : handle_scalar_storage_order_attribute (tree *node, tree name, tree args,
2149 : int flags, bool *no_add_attrs)
2150 : {
2151 896 : tree id = TREE_VALUE (args);
2152 896 : tree type;
2153 :
2154 896 : if (TREE_CODE (*node) == TYPE_DECL
2155 3 : && ! (flags & ATTR_FLAG_CXX11))
2156 3 : node = &TREE_TYPE (*node);
2157 896 : type = *node;
2158 :
2159 896 : if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
2160 : {
2161 : error ("%qE attribute is not supported because endianness is not uniform",
2162 : name);
2163 : return NULL_TREE;
2164 : }
2165 :
2166 896 : if (RECORD_OR_UNION_TYPE_P (type) && !c_dialect_cxx ())
2167 : {
2168 893 : bool reverse = false;
2169 :
2170 893 : if (TREE_CODE (id) == STRING_CST
2171 893 : && strcmp (TREE_STRING_POINTER (id), "big-endian") == 0)
2172 : reverse = !BYTES_BIG_ENDIAN;
2173 426 : else if (TREE_CODE (id) == STRING_CST
2174 426 : && strcmp (TREE_STRING_POINTER (id), "little-endian") == 0)
2175 : reverse = BYTES_BIG_ENDIAN;
2176 : else
2177 : {
2178 3 : error ("attribute %qE argument must be one of %qs or %qs",
2179 : name, "big-endian", "little-endian");
2180 3 : return NULL_TREE;
2181 : }
2182 :
2183 890 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2184 : {
2185 2 : if (reverse)
2186 : /* A type variant isn't good enough, since we don't want a cast
2187 : to such a type to be removed as a no-op. */
2188 1 : *node = type = build_duplicate_type (type);
2189 : }
2190 :
2191 890 : TYPE_REVERSE_STORAGE_ORDER (type) = reverse;
2192 890 : return NULL_TREE;
2193 : }
2194 :
2195 3 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2196 3 : *no_add_attrs = true;
2197 3 : return NULL_TREE;
2198 : }
2199 :
2200 : /* Handle a "transparent_union" attribute; arguments as in
2201 : struct attribute_spec.handler. */
2202 :
2203 : static tree
2204 148 : handle_transparent_union_attribute (tree *node, tree name,
2205 : tree ARG_UNUSED (args), int flags,
2206 : bool *no_add_attrs)
2207 : {
2208 148 : tree type;
2209 :
2210 148 : *no_add_attrs = true;
2211 :
2212 148 : if (TREE_CODE (*node) == TYPE_DECL
2213 89 : && ! (flags & ATTR_FLAG_CXX11))
2214 83 : node = &TREE_TYPE (*node);
2215 148 : type = *node;
2216 :
2217 148 : if (TREE_CODE (type) == UNION_TYPE)
2218 : {
2219 : /* Make sure that the first field will work for a transparent union.
2220 : If the type isn't complete yet, leave the check to the code in
2221 : finish_struct. */
2222 142 : if (TYPE_SIZE (type))
2223 : {
2224 83 : tree first = first_field (type);
2225 83 : if (first == NULL_TREE
2226 71 : || DECL_ARTIFICIAL (first)
2227 154 : || TYPE_MODE (type) != DECL_MODE (first))
2228 12 : goto ignored;
2229 : }
2230 :
2231 130 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
2232 : {
2233 : /* If the type isn't complete yet, setting the flag
2234 : on a variant wouldn't ever be checked. */
2235 65 : if (!TYPE_SIZE (type))
2236 0 : goto ignored;
2237 :
2238 : /* build_duplicate_type doesn't work for C++. */
2239 65 : if (c_dialect_cxx ())
2240 3 : goto ignored;
2241 :
2242 : /* A type variant isn't good enough, since we don't want a cast
2243 : to such a type to be removed as a no-op. */
2244 62 : *node = type = build_duplicate_type (type);
2245 : }
2246 :
2247 271 : for (tree t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
2248 144 : TYPE_TRANSPARENT_AGGR (t) = 1;
2249 : return NULL_TREE;
2250 : }
2251 :
2252 6 : ignored:
2253 21 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2254 21 : return NULL_TREE;
2255 : }
2256 :
2257 : /* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to
2258 : get the requested priority for a constructor or destructor,
2259 : possibly issuing diagnostics for invalid or reserved
2260 : priorities. */
2261 :
2262 : static priority_type
2263 691 : get_priority (tree args, bool is_destructor)
2264 : {
2265 691 : HOST_WIDE_INT pri;
2266 691 : tree arg;
2267 :
2268 691 : if (!args)
2269 : return DEFAULT_INIT_PRIORITY;
2270 :
2271 273 : if (!SUPPORTS_INIT_PRIORITY)
2272 : {
2273 : if (is_destructor)
2274 : error ("destructor priorities are not supported");
2275 : else
2276 : error ("constructor priorities are not supported");
2277 : return DEFAULT_INIT_PRIORITY;
2278 : }
2279 :
2280 273 : arg = TREE_VALUE (args);
2281 273 : if (TREE_CODE (arg) == IDENTIFIER_NODE || TREE_CODE (arg) == FUNCTION_DECL)
2282 8 : goto invalid;
2283 265 : if (arg == error_mark_node)
2284 : return DEFAULT_INIT_PRIORITY;
2285 261 : arg = default_conversion (arg);
2286 261 : if (!tree_fits_shwi_p (arg)
2287 261 : || !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
2288 11 : goto invalid;
2289 :
2290 250 : pri = tree_to_shwi (arg);
2291 250 : if (pri < 0 || pri > MAX_INIT_PRIORITY)
2292 8 : goto invalid;
2293 :
2294 242 : if (pri <= MAX_RESERVED_INIT_PRIORITY)
2295 : {
2296 24 : if (is_destructor)
2297 8 : warning (OPT_Wprio_ctor_dtor,
2298 : "destructor priorities from 0 to %d are reserved "
2299 : "for the implementation",
2300 : MAX_RESERVED_INIT_PRIORITY);
2301 : else
2302 16 : warning (OPT_Wprio_ctor_dtor,
2303 : "constructor priorities from 0 to %d are reserved "
2304 : "for the implementation",
2305 : MAX_RESERVED_INIT_PRIORITY);
2306 : }
2307 242 : return pri;
2308 :
2309 27 : invalid:
2310 27 : if (is_destructor)
2311 12 : error ("destructor priorities must be integers from 0 to %d inclusive",
2312 : MAX_INIT_PRIORITY);
2313 : else
2314 15 : error ("constructor priorities must be integers from 0 to %d inclusive",
2315 : MAX_INIT_PRIORITY);
2316 : return DEFAULT_INIT_PRIORITY;
2317 : }
2318 :
2319 : /* Handle a "constructor" attribute; arguments as in
2320 : struct attribute_spec.handler. */
2321 :
2322 : static tree
2323 504 : handle_constructor_attribute (tree *node, tree name, tree args,
2324 : int ARG_UNUSED (flags),
2325 : bool *no_add_attrs)
2326 : {
2327 504 : tree decl = *node;
2328 504 : tree type = TREE_TYPE (decl);
2329 :
2330 504 : if (TREE_CODE (decl) == FUNCTION_DECL
2331 504 : && TREE_CODE (type) == FUNCTION_TYPE
2332 1008 : && decl_function_context (decl) == 0)
2333 : {
2334 504 : priority_type priority;
2335 504 : DECL_STATIC_CONSTRUCTOR (decl) = 1;
2336 504 : priority = get_priority (args, /*is_destructor=*/false);
2337 504 : SET_DECL_INIT_PRIORITY (decl, priority);
2338 504 : TREE_USED (decl) = 1;
2339 : }
2340 : else
2341 : {
2342 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2343 0 : *no_add_attrs = true;
2344 : }
2345 :
2346 504 : return NULL_TREE;
2347 : }
2348 :
2349 : /* Handle a "destructor" attribute; arguments as in
2350 : struct attribute_spec.handler. */
2351 :
2352 : static tree
2353 187 : handle_destructor_attribute (tree *node, tree name, tree args,
2354 : int ARG_UNUSED (flags),
2355 : bool *no_add_attrs)
2356 : {
2357 187 : tree decl = *node;
2358 187 : tree type = TREE_TYPE (decl);
2359 :
2360 187 : if (TREE_CODE (decl) == FUNCTION_DECL
2361 187 : && TREE_CODE (type) == FUNCTION_TYPE
2362 374 : && decl_function_context (decl) == 0)
2363 : {
2364 187 : priority_type priority;
2365 187 : DECL_STATIC_DESTRUCTOR (decl) = 1;
2366 187 : priority = get_priority (args, /*is_destructor=*/true);
2367 187 : SET_DECL_FINI_PRIORITY (decl, priority);
2368 187 : TREE_USED (decl) = 1;
2369 : }
2370 : else
2371 : {
2372 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2373 0 : *no_add_attrs = true;
2374 : }
2375 :
2376 187 : return NULL_TREE;
2377 : }
2378 :
2379 : /* Nonzero if the mode is a valid vector mode for this architecture.
2380 : This returns nonzero even if there is no hardware support for the
2381 : vector mode, but we can emulate with narrower modes. */
2382 :
2383 : static bool
2384 0 : vector_mode_valid_p (machine_mode mode)
2385 : {
2386 0 : enum mode_class mclass = GET_MODE_CLASS (mode);
2387 :
2388 : /* Doh! What's going on? */
2389 0 : if (mclass != MODE_VECTOR_INT
2390 0 : && mclass != MODE_VECTOR_FLOAT
2391 : && mclass != MODE_VECTOR_FRACT
2392 0 : && mclass != MODE_VECTOR_UFRACT
2393 : && mclass != MODE_VECTOR_ACCUM
2394 0 : && mclass != MODE_VECTOR_UACCUM)
2395 : return false;
2396 :
2397 : /* Hardware support. Woo hoo! */
2398 0 : if (targetm.vector_mode_supported_p (mode))
2399 : return true;
2400 :
2401 : /* We should probably return 1 if requesting V4DI and we have no DI,
2402 : but we have V2DI, but this is probably very unlikely. */
2403 :
2404 : /* If we have support for the inner mode, we can safely emulate it.
2405 : We may not have V2DI, but me can emulate with a pair of DIs. */
2406 0 : return targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
2407 : }
2408 :
2409 :
2410 : /* Handle a "mode" attribute; arguments as in
2411 : struct attribute_spec.handler. */
2412 :
2413 : static tree
2414 53947 : handle_mode_attribute (tree *node, tree name, tree args,
2415 : int ARG_UNUSED (flags), bool *no_add_attrs)
2416 : {
2417 53947 : tree type = *node;
2418 53947 : tree ident = TREE_VALUE (args);
2419 :
2420 53947 : *no_add_attrs = true;
2421 :
2422 53947 : if (TREE_CODE (ident) != IDENTIFIER_NODE)
2423 2 : warning (OPT_Wattributes, "%qE attribute ignored", name);
2424 : else
2425 : {
2426 53945 : int j;
2427 53945 : const char *p = IDENTIFIER_POINTER (ident);
2428 53945 : int len = strlen (p);
2429 53945 : machine_mode mode = VOIDmode;
2430 53945 : tree typefm;
2431 53945 : bool valid_mode;
2432 :
2433 53945 : if (len > 4 && p[0] == '_' && p[1] == '_'
2434 34384 : && p[len - 1] == '_' && p[len - 2] == '_')
2435 : {
2436 34384 : char *newp = (char *) alloca (len - 1);
2437 :
2438 34384 : strcpy (newp, &p[2]);
2439 34384 : newp[len - 4] = '\0';
2440 34384 : p = newp;
2441 : }
2442 :
2443 : /* Change this type to have a type with the specified mode.
2444 : First check for the special modes. */
2445 53945 : if (!strcmp (p, "byte"))
2446 82 : mode = byte_mode;
2447 53863 : else if (!strcmp (p, "word"))
2448 32132 : mode = word_mode;
2449 21731 : else if (!strcmp (p, "pointer"))
2450 767 : mode = ptr_mode;
2451 20964 : else if (!strcmp (p, "libgcc_cmp_return"))
2452 814 : mode = targetm.libgcc_cmp_return_mode ();
2453 20150 : else if (!strcmp (p, "libgcc_shift_count"))
2454 308 : mode = targetm.libgcc_shift_count_mode ();
2455 19842 : else if (!strcmp (p, "unwind_word"))
2456 410 : mode = targetm.unwind_word_mode ();
2457 : else
2458 594550 : for (j = 0; j < NUM_MACHINE_MODES; j++)
2459 594548 : if (!strcmp (p, GET_MODE_NAME (j)))
2460 : {
2461 19430 : mode = (machine_mode) j;
2462 19430 : break;
2463 : }
2464 :
2465 53945 : if (mode == VOIDmode)
2466 : {
2467 2 : error ("unknown machine mode %qE", ident);
2468 2 : return NULL_TREE;
2469 : }
2470 :
2471 : /* Allow the target a chance to translate MODE into something supported.
2472 : See PR86324. */
2473 53943 : mode = targetm.translate_mode_attribute (mode);
2474 :
2475 53943 : valid_mode = false;
2476 53943 : switch (GET_MODE_CLASS (mode))
2477 : {
2478 51933 : case MODE_INT:
2479 51933 : case MODE_PARTIAL_INT:
2480 51933 : case MODE_FLOAT:
2481 51933 : case MODE_DECIMAL_FLOAT:
2482 51933 : case MODE_FRACT:
2483 51933 : case MODE_UFRACT:
2484 51933 : case MODE_ACCUM:
2485 51933 : case MODE_UACCUM:
2486 51933 : valid_mode
2487 51933 : = targetm.scalar_mode_supported_p (as_a <scalar_mode> (mode));
2488 51933 : 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 53943 : if (!valid_mode)
2512 : {
2513 7 : error ("unable to emulate %qs", p);
2514 7 : return NULL_TREE;
2515 : }
2516 :
2517 53936 : 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 53936 : if (ALL_FIXED_POINT_MODE_P (mode)
2541 53936 : && 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 107872 : typefm = lang_hooks.types.type_for_mode (mode,
2548 53936 : ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type)
2549 53936 : : TYPE_UNSIGNED (type));
2550 : }
2551 :
2552 53936 : if (typefm == NULL_TREE)
2553 : {
2554 0 : error ("no data type for mode %qs", p);
2555 0 : return NULL_TREE;
2556 : }
2557 53936 : 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 107656 : else if (VECTOR_MODE_P (mode)
2589 53828 : ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
2590 53828 : : 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 53935 : *node = build_type_attribute_qual_variant (typefm, TYPE_ATTRIBUTES (type),
2598 53935 : TYPE_QUALS (type));
2599 53935 : 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 475 : handle_section_attribute (tree *node, tree name, tree args,
2611 : int flags, bool *no_add_attrs)
2612 : {
2613 475 : tree decl = *node;
2614 475 : tree res = NULL_TREE;
2615 475 : tree argval = TREE_VALUE (args);
2616 475 : const char* new_section_name;
2617 :
2618 475 : 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 475 : 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 475 : if (TREE_CODE (argval) != STRING_CST)
2632 : {
2633 0 : error ("section attribute argument not a string constant");
2634 0 : goto fail;
2635 : }
2636 :
2637 475 : if (VAR_P (decl)
2638 362 : && 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 475 : 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 475 : 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 473 : if (VAR_P (decl)
2659 362 : && !targetm.have_tls && targetm.emutls.tmpl_section
2660 473 : && DECL_THREAD_LOCAL_P (decl))
2661 : {
2662 0 : error ("section of %q+D cannot be overridden", *node);
2663 0 : goto fail;
2664 : }
2665 :
2666 473 : if (!validate_attr_arg (node, name, argval))
2667 1 : goto fail;
2668 :
2669 472 : 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 472 : if (!(*no_add_attrs))
2675 : {
2676 472 : set_decl_section_name (decl, new_section_name);
2677 472 : 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 638153 : 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 638153 : tree decl = NULL_TREE;
2694 638153 : tree *type = NULL;
2695 638153 : bool is_type = false;
2696 638153 : 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 638153 : tree last_decl = node[1] ? node[1] : *node;
2702 :
2703 638153 : if (args)
2704 : {
2705 599730 : align_expr = TREE_VALUE (args);
2706 599730 : if (align_expr && TREE_CODE (align_expr) != IDENTIFIER_NODE
2707 599730 : && TREE_CODE (align_expr) != FUNCTION_DECL)
2708 599722 : align_expr = default_conversion (align_expr);
2709 : }
2710 : else
2711 76846 : align_expr = size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT);
2712 :
2713 638153 : if (DECL_P (*node))
2714 : {
2715 610700 : decl = *node;
2716 610700 : type = &TREE_TYPE (decl);
2717 610700 : is_type = TREE_CODE (*node) == TYPE_DECL;
2718 : }
2719 27453 : else if (TYPE_P (*node))
2720 27453 : type = node, is_type = true;
2721 :
2722 : /* True to consider invalid alignments greater than MAX_OFILE_ALIGNMENT. */
2723 1276306 : bool objfile = (TREE_CODE (*node) == FUNCTION_DECL
2724 638153 : || (VAR_P (*node) && TREE_STATIC (*node)));
2725 : /* Log2 of specified alignment. */
2726 638153 : int pow2align = check_user_alignment (align_expr, objfile,
2727 : /* warn_zero = */ true);
2728 638153 : 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 637995 : 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 637995 : unsigned curalign = 0;
2740 637995 : unsigned lastalign = 0;
2741 :
2742 : /* True when SET_DECL_ALIGN() should be called for the decl when
2743 : *NO_ADD_ATTRS is false. */
2744 637995 : bool set_align = true;
2745 637995 : if (is_type)
2746 : {
2747 271522 : 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 232794 : else if (decl && TREE_TYPE (decl) != error_mark_node
2752 466075 : && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
2753 : {
2754 232695 : tree tt = TREE_TYPE (decl);
2755 232695 : *type = build_variant_type_copy (*type);
2756 232695 : DECL_ORIGINAL_TYPE (decl) = tt;
2757 232695 : TYPE_NAME (*type) = decl;
2758 232695 : TREE_USED (*type) = TREE_USED (decl);
2759 232695 : TREE_TYPE (decl) = *type;
2760 : }
2761 : else
2762 586 : *type = build_variant_type_copy (*type);
2763 :
2764 271522 : 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 271450 : SET_TYPE_ALIGN (*type, bitalign);
2772 271450 : TYPE_USER_ALIGN (*type) = 1;
2773 : }
2774 : }
2775 366473 : else if (! VAR_OR_FUNCTION_DECL_P (decl)
2776 330472 : && 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 366418 : else if (TREE_CODE (decl) == FUNCTION_DECL
2782 366418 : && (((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 366368 : else if (DECL_USER_ALIGN (decl)
2827 366368 : && 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 366365 : else if (warn_if_not_aligned_p
2838 52 : && TREE_CODE (decl) == FIELD_DECL
2839 366409 : && !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 637995 : 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 637983 : else if (!is_type && !*no_add_attrs && set_align)
2853 : {
2854 366313 : SET_DECL_ALIGN (decl, bitalign);
2855 366313 : 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 638029 : handle_aligned_attribute (tree *node, tree name, tree args,
2866 : int flags, bool *no_add_attrs)
2867 : {
2868 638029 : return common_handle_aligned_attribute (node, name, args, flags,
2869 638029 : 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 409 : handle_counted_by_attribute (tree *node, tree name,
2932 : tree args, int ARG_UNUSED (flags),
2933 : bool *no_add_attrs)
2934 : {
2935 409 : tree decl = *node;
2936 409 : tree argval = TREE_VALUE (args);
2937 409 : tree old_counted_by = lookup_attribute ("counted_by", DECL_ATTRIBUTES (decl));
2938 :
2939 : /* This attribute is not supported in C++. */
2940 409 : 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 397 : 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 395 : else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE
2957 395 : && 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 393 : else if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
2966 393 : && !c_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 392 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
2976 392 : && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == VOID_TYPE)
2977 : {
2978 4 : 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 388 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
2986 388 : && 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 387 : else if (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE
2996 249 : && RECORD_OR_UNION_TYPE_P (TREE_TYPE (TREE_TYPE (decl)))
2997 432 : && 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 386 : 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 384 : 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 409 : return NULL_TREE;
3028 : }
3029 :
3030 : /* Handle a "weak" attribute; arguments as in
3031 : struct attribute_spec.handler. */
3032 :
3033 : static tree
3034 9069 : 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 9069 : if (TREE_CODE (*node) == FUNCTION_DECL
3040 9069 : && 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 9068 : 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 9067 : else if (VAR_OR_FUNCTION_DECL_P (*node))
3052 9062 : 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 5696 : handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
3246 : bool *no_add_attrs)
3247 : {
3248 5696 : tree decl = *node;
3249 :
3250 5696 : 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 5494 : else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
3257 5695 : || (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 11390 : || (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 5695 : else if (!is_alias
3269 5695 : && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
3270 117 : || 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 5694 : else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
3283 : {
3284 5687 : tree id;
3285 :
3286 5687 : id = TREE_VALUE (args);
3287 5687 : 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 5687 : id = get_identifier (TREE_STRING_POINTER (id));
3294 : /* This counts as a use of the object pointed to. */
3295 5687 : TREE_USED (id) = 1;
3296 :
3297 5687 : if (TREE_CODE (decl) == FUNCTION_DECL)
3298 5486 : DECL_INITIAL (decl) = error_mark_node;
3299 : else
3300 201 : TREE_STATIC (decl) = 1;
3301 :
3302 5687 : if (!is_alias)
3303 : {
3304 : /* ifuncs are also aliases, so set that attribute too. */
3305 117 : DECL_ATTRIBUTES (decl)
3306 117 : = tree_cons (get_identifier ("alias"), args,
3307 117 : DECL_ATTRIBUTES (decl));
3308 117 : DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
3309 117 : 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 5695 : if (decl_in_symtab_p (*node))
3319 : {
3320 5694 : struct symtab_node *n = symtab_node::get (decl);
3321 5694 : 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 118 : handle_ifunc_attribute (tree *node, tree name, tree args,
3335 : int ARG_UNUSED (flags), bool *no_add_attrs)
3336 : {
3337 118 : 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 5578 : handle_alias_attribute (tree *node, tree name, tree args,
3345 : int ARG_UNUSED (flags), bool *no_add_attrs)
3346 : {
3347 5578 : 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 1099 : 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 1099 : *no_add_attrs = true;
3360 :
3361 1099 : tree decl = *node;
3362 :
3363 1099 : tree ref = TREE_VALUE (args);
3364 1099 : if (ref == error_mark_node)
3365 : return NULL_TREE;
3366 :
3367 1098 : location_t loc = input_location;
3368 1098 : if (DECL_P (decl))
3369 1095 : loc = DECL_SOURCE_LOCATION (decl);
3370 1098 : 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 1096 : if (CONSTANT_CLASS_P (ref)
3379 1096 : && (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 1095 : 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 9 : return NULL_TREE;
3400 : }
3401 :
3402 : /* Consider address-of expressions in the attribute argument
3403 : as requests to copy from the referenced entity. */
3404 1086 : if (TREE_CODE (ref) == ADDR_EXPR)
3405 18 : ref = TREE_OPERAND (ref, 0);
3406 :
3407 1129 : do
3408 : {
3409 : /* Drill down into references to find the referenced decl. */
3410 1129 : tree_code refcode = TREE_CODE (ref);
3411 1129 : if (refcode == ARRAY_REF
3412 1129 : || refcode == INDIRECT_REF)
3413 51 : ref = TREE_OPERAND (ref, 0);
3414 1078 : 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 1063 : if ((CONSTANT_CLASS_P (ref) || EXPR_P (ref))
3427 72 : && POINTER_TYPE_P (TREE_TYPE (ref))
3428 1141 : && !FUNCTION_POINTER_TYPE_P (TREE_TYPE (ref)))
3429 44 : ref = TREE_TYPE (ref);
3430 :
3431 1086 : tree reftype = TYPE_P (ref) ? ref : TREE_TYPE (ref);
3432 :
3433 1086 : if (DECL_P (decl))
3434 : {
3435 1084 : 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 1103 : || (TREE_CODE (decl) == FUNCTION_DECL
3441 926 : && (VAR_P (ref)
3442 925 : || (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 4 : return NULL_TREE;
3456 : }
3457 :
3458 1080 : tree attrs = NULL_TREE;
3459 1080 : if (DECL_P (ref))
3460 1012 : 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 1850 : 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 1082 : if (TREE_NOTHROW (ref))
3508 555 : 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 1082 : if (DECL_P (ref)
3513 1012 : && TREE_THIS_VOLATILE (ref)
3514 33 : && FUNC_OR_METHOD_TYPE_P (reftype))
3515 32 : TREE_THIS_VOLATILE (decl) = true;
3516 :
3517 1082 : if (POINTER_TYPE_P (reftype))
3518 96 : reftype = TREE_TYPE (reftype);
3519 :
3520 1082 : if (!TYPE_P (reftype))
3521 : return NULL_TREE;
3522 :
3523 1082 : 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 1421 : 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 911 : handle_weakref_attribute (tree *node, tree name, tree args,
3540 : int flags, bool *no_add_attrs)
3541 : {
3542 911 : 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 911 : if (decl_function_context (*node)
3548 911 : || current_function_decl
3549 1822 : || !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 909 : 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 909 : if (args)
3569 : {
3570 452 : attr = tree_cons (get_identifier ("alias"), args, attr);
3571 452 : attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
3572 :
3573 452 : *no_add_attrs = true;
3574 :
3575 452 : decl_attributes (node, attr, flags);
3576 : }
3577 : else
3578 : {
3579 457 : 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 457 : DECL_WEAK (*node) = 1;
3588 : }
3589 :
3590 909 : if (decl_in_symtab_p (*node))
3591 : {
3592 909 : struct symtab_node *n = symtab_node::get (*node);
3593 909 : 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 694134 : handle_visibility_attribute (tree *node, tree name, tree args,
3605 : int ARG_UNUSED (flags),
3606 : bool *ARG_UNUSED (no_add_attrs))
3607 : {
3608 694134 : tree decl = *node;
3609 694134 : tree id = TREE_VALUE (args);
3610 694134 : enum symbol_visibility vis;
3611 :
3612 694134 : 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 694004 : 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 694132 : 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 694132 : 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 694131 : if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
3656 : vis = VISIBILITY_DEFAULT;
3657 637968 : else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
3658 : vis = VISIBILITY_INTERNAL;
3659 637908 : 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 694131 : if (DECL_VISIBILITY_SPECIFIED (decl)
3671 694131 : && 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 694131 : DECL_VISIBILITY (decl) = vis;
3689 694131 : 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 694131 : return NULL_TREE;
3697 : }
3698 :
3699 : /* Handle an "tls_model" attribute; arguments as in
3700 : struct attribute_spec.handler. */
3701 :
3702 : static tree
3703 339 : handle_tls_model_attribute (tree *node, tree name, tree args,
3704 : int ARG_UNUSED (flags),
3705 : bool *ARG_UNUSED (no_add_attrs))
3706 : {
3707 339 : tree id;
3708 339 : tree decl = *node;
3709 339 : enum tls_model kind;
3710 :
3711 339 : 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 337 : 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 335 : kind = DECL_TLS_MODEL (decl);
3727 335 : id = TREE_VALUE (args);
3728 335 : if (TREE_CODE (id) != STRING_CST)
3729 : {
3730 1 : error ("%qE argument not a string", name);
3731 1 : return NULL_TREE;
3732 : }
3733 :
3734 334 : if (!strcmp (TREE_STRING_POINTER (id), "local-exec"))
3735 : kind = TLS_MODEL_LOCAL_EXEC;
3736 303 : else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec"))
3737 : kind = TLS_MODEL_INITIAL_EXEC;
3738 204 : else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic"))
3739 203 : kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
3740 150 : 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 334 : set_decl_tls_model (decl, kind);
3748 334 : 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 342504 : maybe_add_noinline (tree name, tree alloc_decl, tree dealloc_decl,
3797 : bool *no_add_attrs)
3798 : {
3799 342504 : 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 221847 : if ((optimize && DECL_DECLARED_INLINE_P (alloc_decl))
3808 476727 : || 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 221843 : if ((optimize && DECL_DECLARED_INLINE_P (dealloc_decl))
3818 476715 : || 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 254868 : tree attr = tree_cons (get_identifier ("noinline"), NULL_TREE, NULL_TREE);
3834 254868 : decl_attributes (&alloc_decl, attr, 0);
3835 254868 : return attr;
3836 : }
3837 :
3838 : /* Handle the "malloc" attribute. */
3839 :
3840 : static tree
3841 3239215 : handle_malloc_attribute (tree *node, tree name, tree args, int flags,
3842 : bool *no_add_attrs)
3843 : {
3844 3239215 : if (flags & ATTR_FLAG_INTERNAL)
3845 : /* Recursive call. */
3846 : return NULL_TREE;
3847 :
3848 3239215 : tree fndecl = *node;
3849 :
3850 3239215 : 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 3239211 : tree rettype = TREE_TYPE (TREE_TYPE (*node));
3860 3239211 : 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 3239203 : if (!args)
3870 : {
3871 : /* Only the form of the attribute with no arguments declares
3872 : a function malloc-like. */
3873 2896662 : DECL_IS_MALLOC (*node) = 1;
3874 2896662 : return NULL_TREE;
3875 : }
3876 :
3877 342541 : tree dealloc = TREE_VALUE (args);
3878 342541 : 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 342540 : STRIP_NOPS (dealloc);
3887 342540 : 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 342524 : 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 342517 : TREE_USED (dealloc) = 1;
3925 :
3926 342517 : tree fntype = TREE_TYPE (dealloc);
3927 342517 : tree argpos = TREE_CHAIN (args) ? TREE_VALUE (TREE_CHAIN (args)) : NULL_TREE;
3928 342517 : if (!argpos)
3929 : {
3930 4910 : tree argtypes = TYPE_ARG_TYPES (fntype);
3931 4910 : 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 4910 : tree argtype = TREE_VALUE (argtypes);
3943 4910 : 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 4897 : tree at_noinline =
3958 4897 : maybe_add_noinline (name, fndecl, dealloc, no_add_attrs);
3959 4897 : 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 4889 : tree attrs = build_tree_list (NULL_TREE, DECL_NAME (fndecl));
3968 4889 : attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
3969 4889 : decl_attributes (&dealloc, attrs, 0);
3970 4889 : return NULL_TREE;
3971 : }
3972 :
3973 : /* Validate the positional argument. */
3974 337607 : argpos = positional_argument (fntype, name, argpos, POINTER_TYPE);
3975 337607 : 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 337607 : tree at_noinline =
3984 337607 : maybe_add_noinline (name, fndecl, dealloc, no_add_attrs);
3985 337607 : 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 337599 : tree attrs = tree_cons (NULL_TREE, argpos, NULL_TREE);
3993 337599 : attrs = tree_cons (NULL_TREE, DECL_NAME (fndecl), attrs);
3994 337599 : attrs = tree_cons (get_identifier ("*dealloc"), attrs, at_noinline);
3995 337599 : decl_attributes (&dealloc, attrs, 0);
3996 337599 : 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 342512 : handle_dealloc_attribute (tree *node, tree name, tree args, int,
4005 : bool *no_add_attrs)
4006 : {
4007 342512 : tree fndecl = *node;
4008 :
4009 342512 : tree attrs = DECL_ATTRIBUTES (fndecl);
4010 342512 : if (!attrs)
4011 : return NULL_TREE;
4012 :
4013 292778 : tree arg = TREE_VALUE (args);
4014 292778 : args = TREE_CHAIN (args);
4015 581009 : tree arg_pos = args ? TREE_VALUE (args) : integer_zero_node;
4016 :
4017 292778 : gcc_checking_assert ((DECL_P (arg)
4018 : && fndecl_built_in_p (arg, BUILT_IN_NORMAL))
4019 : || TREE_CODE (arg) == IDENTIFIER_NODE);
4020 :
4021 292778 : const char* const namestr = IDENTIFIER_POINTER (name);
4022 1082322 : for (tree at = attrs; (at = lookup_attribute (namestr, at));
4023 789544 : at = TREE_CHAIN (at))
4024 : {
4025 789882 : tree alloc = TREE_VALUE (at);
4026 789882 : if (!alloc)
4027 0 : continue;
4028 :
4029 789882 : tree pos = TREE_CHAIN (alloc);
4030 789882 : alloc = TREE_VALUE (alloc);
4031 1570092 : pos = pos ? TREE_VALUE (pos) : integer_zero_node;
4032 789882 : gcc_checking_assert ((DECL_P (alloc)
4033 : && fndecl_built_in_p (alloc, BUILT_IN_NORMAL))
4034 : || TREE_CODE (alloc) == IDENTIFIER_NODE);
4035 :
4036 789882 : 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 338 : *no_add_attrs = true;
4042 338 : 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 2311422 : handle_alloc_size_attribute (tree *node, tree name, tree args,
4054 : int ARG_UNUSED (flags), bool *no_add_attrs)
4055 : {
4056 2311422 : tree fntype = *node;
4057 2311422 : tree rettype = TREE_TYPE (fntype);
4058 2311422 : 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 2311383 : tree newargs[2] = { NULL_TREE, NULL_TREE };
4068 5102083 : for (int i = 1; args; ++i)
4069 : {
4070 2790736 : 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 2790736 : tree next = TREE_CHAIN (args);
4076 2790736 : if (tree val = positional_argument (fntype, name, pos, INTEGER_TYPE,
4077 2790736 : next || i > 1 ? i : 0))
4078 : {
4079 2790700 : TREE_VALUE (args) = val;
4080 2790700 : newargs[i - 1] = val;
4081 : }
4082 : else
4083 : {
4084 36 : *no_add_attrs = true;
4085 36 : return NULL_TREE;
4086 : }
4087 :
4088 2790700 : args = next;
4089 : }
4090 :
4091 2311347 : 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 95300 : handle_alloc_align_attribute (tree *node, tree name, tree args, int,
4102 : bool *no_add_attrs)
4103 : {
4104 95300 : tree fntype = *node;
4105 95300 : tree rettype = TREE_TYPE (fntype);
4106 95300 : 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 95289 : if (tree val = positional_argument (*node, name, TREE_VALUE (args),
4116 : INTEGER_TYPE))
4117 95257 : 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 436584 : handle_argspec_attribute (tree *, tree, tree args, int, bool *)
4200 : {
4201 : /* Verify the attribute has one or two arguments and their kind. */
4202 873168 : gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST);
4203 436584 : if (TREE_CHAIN (args))
4204 : {
4205 436584 : tree val = TREE_VALUE (TREE_CHAIN (args));
4206 436584 : gcc_assert (!TREE_CHAIN (TREE_CHAIN (args)));
4207 436584 : gcc_assert (TYPE_P (val));
4208 : }
4209 436584 : return NULL_TREE;
4210 : }
4211 :
4212 : /* Handle the internal-only "fn spec" attribute. */
4213 :
4214 : static tree
4215 129696477 : 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 259392954 : gcc_assert (args
4220 : && TREE_CODE (TREE_VALUE (args)) == STRING_CST
4221 : && !TREE_CHAIN (args));
4222 129696477 : 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 1519 : handle_omp_declare_variant_attribute (tree *, tree, tree, int, bool *)
4260 : {
4261 1519 : return NULL_TREE;
4262 : }
4263 :
4264 : /* Handle a "simd" attribute. */
4265 :
4266 : static tree
4267 8910 : handle_simd_attribute (tree *node, tree name, tree args, int, bool *no_add_attrs)
4268 : {
4269 8910 : if (TREE_CODE (*node) == FUNCTION_DECL)
4270 : {
4271 8910 : tree t = get_identifier ("omp declare simd");
4272 8910 : tree attr = NULL_TREE;
4273 8910 : if (args)
4274 : {
4275 8785 : tree id = TREE_VALUE (args);
4276 :
4277 8785 : 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 8785 : if (strcmp (TREE_STRING_POINTER (id), "notinbranch") == 0)
4285 8777 : 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 8906 : DECL_ATTRIBUTES (*node)
4300 17812 : = tree_cons (t, build_tree_list (NULL_TREE, attr),
4301 8906 : 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 2874 : handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
4317 : {
4318 2874 : 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 221018 : handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4335 : int ARG_UNUSED (flags), bool *no_add_attrs)
4336 : {
4337 221018 : if (TREE_CODE (*node) == FUNCTION_DECL)
4338 221018 : 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 221018 : 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 19787189 : handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4382 : int ARG_UNUSED (flags), bool *no_add_attrs)
4383 : {
4384 19787189 : if (TREE_CODE (*node) == FUNCTION_DECL)
4385 : {
4386 19787189 : tree type = TREE_TYPE (*node);
4387 19787189 : if (VOID_TYPE_P (TREE_TYPE (type)))
4388 3 : warning (OPT_Wattributes, "%qE attribute on function "
4389 : "returning %<void%>", name);
4390 :
4391 19787189 : 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 19787189 : 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 16377426 : tm_attr_to_mask (tree attr)
4496 : {
4497 16377426 : if (attr == NULL)
4498 : return 0;
4499 16377146 : if (is_attribute_p ("transaction_safe", attr))
4500 : return TM_ATTR_SAFE;
4501 16377019 : if (is_attribute_p ("transaction_callable", attr))
4502 : return TM_ATTR_CALLABLE;
4503 16376918 : if (is_attribute_p ("transaction_pure", attr))
4504 : return TM_ATTR_PURE;
4505 16376900 : if (is_attribute_p ("transaction_unsafe", attr))
4506 : return TM_ATTR_IRREVOCABLE;
4507 16376891 : 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 1366245 : find_tm_attribute (tree list)
4543 : {
4544 1370726 : for (; list ; list = TREE_CHAIN (list))
4545 : {
4546 4629 : tree name = get_attribute_name (list);
4547 4629 : 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 1359574 : 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 1359574 : *no_add_attrs = true;
4566 :
4567 1359574 : 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 1359475 : case FUNCTION_TYPE:
4577 1359475 : case METHOD_TYPE:
4578 1359475 : {
4579 1359475 : tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node));
4580 1359475 : if (old_name == name)
4581 : ;
4582 1359475 : else if (old_name != NULL_TREE)
4583 12 : error ("type was previously declared %qE", old_name);
4584 : else
4585 1359463 : *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 : /* Ignore the given attribute. Used when this attribute may be usefully
4676 : overridden by the target, but is not used generically. */
4677 :
4678 : static tree
4679 0 : ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
4680 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4681 : bool *no_add_attrs)
4682 : {
4683 0 : *no_add_attrs = true;
4684 0 : return NULL_TREE;
4685 : }
4686 :
4687 : /* Handle a "no vops" attribute; arguments as in
4688 : struct attribute_spec.handler. */
4689 :
4690 : static tree
4691 1659912 : handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
4692 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4693 : bool *ARG_UNUSED (no_add_attrs))
4694 : {
4695 1659912 : gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
4696 1659912 : DECL_IS_NOVOPS (*node) = 1;
4697 1659912 : return NULL_TREE;
4698 : }
4699 :
4700 : /* Handle a "deprecated" attribute; arguments as in
4701 : struct attribute_spec.handler. */
4702 :
4703 : tree
4704 1162203 : handle_deprecated_attribute (tree *node, tree name,
4705 : tree args, int flags,
4706 : bool *no_add_attrs)
4707 : {
4708 1162203 : tree type = NULL_TREE;
4709 1162203 : int warn = 0;
4710 1162203 : tree what = NULL_TREE;
4711 :
4712 1162203 : if (!args)
4713 444608 : *no_add_attrs = true;
4714 717595 : else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
4715 : {
4716 7 : error ("deprecated message is not a string");
4717 7 : *no_add_attrs = true;
4718 : }
4719 :
4720 1162203 : if (DECL_P (*node))
4721 : {
4722 813193 : tree decl = *node;
4723 813193 : type = TREE_TYPE (decl);
4724 :
4725 813193 : if (TREE_CODE (decl) == TYPE_DECL
4726 813193 : || TREE_CODE (decl) == PARM_DECL
4727 : || VAR_OR_FUNCTION_DECL_P (decl)
4728 : || TREE_CODE (decl) == FIELD_DECL
4729 : || TREE_CODE (decl) == CONST_DECL
4730 29 : || objc_method_decl (TREE_CODE (decl))
4731 29 : || TREE_CODE (decl) == CONCEPT_DECL)
4732 813178 : TREE_DEPRECATED (decl) = 1;
4733 15 : else if (TREE_CODE (decl) == LABEL_DECL)
4734 : {
4735 15 : pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
4736 : name);
4737 15 : *no_add_attrs = true;
4738 15 : return NULL_TREE;
4739 : }
4740 : else
4741 : warn = 1;
4742 : }
4743 349010 : else if (TYPE_P (*node))
4744 : {
4745 349010 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
4746 10094 : *node = build_variant_type_copy (*node);
4747 349010 : TREE_DEPRECATED (*node) = 1;
4748 349010 : type = *node;
4749 : }
4750 : else
4751 : warn = 1;
4752 :
4753 1162188 : if (warn)
4754 : {
4755 0 : *no_add_attrs = true;
4756 0 : if (type && TYPE_NAME (type))
4757 : {
4758 0 : if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4759 0 : what = TYPE_NAME (type);
4760 0 : else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4761 0 : && DECL_NAME (TYPE_NAME (type)))
4762 0 : what = DECL_NAME (TYPE_NAME (type));
4763 : }
4764 0 : if (what)
4765 0 : warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
4766 : else
4767 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
4768 : }
4769 :
4770 : return NULL_TREE;
4771 : }
4772 :
4773 : /* Handle a "unavailable" attribute; arguments as in
4774 : struct attribute_spec.handler. */
4775 :
4776 : static tree
4777 256 : handle_unavailable_attribute (tree *node, tree name,
4778 : tree args, int flags,
4779 : bool *no_add_attrs)
4780 : {
4781 256 : tree type = NULL_TREE;
4782 256 : int warn = 0;
4783 256 : tree what = NULL_TREE;
4784 :
4785 256 : if (!args)
4786 161 : *no_add_attrs = true;
4787 95 : else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
4788 : {
4789 0 : error ("the message attached to %<unavailable%> is not a string");
4790 0 : *no_add_attrs = true;
4791 : }
4792 :
4793 256 : if (DECL_P (*node))
4794 : {
4795 217 : tree decl = *node;
4796 217 : type = TREE_TYPE (decl);
4797 :
4798 217 : if (TREE_CODE (decl) == TYPE_DECL
4799 217 : || TREE_CODE (decl) == PARM_DECL
4800 : || VAR_OR_FUNCTION_DECL_P (decl)
4801 : || TREE_CODE (decl) == FIELD_DECL
4802 : || TREE_CODE (decl) == CONST_DECL
4803 0 : || objc_method_decl (TREE_CODE (decl)))
4804 217 : TREE_UNAVAILABLE (decl) = 1;
4805 : else
4806 : warn = 1;
4807 : }
4808 39 : else if (TYPE_P (*node))
4809 : {
4810 39 : if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
4811 0 : *node = build_variant_type_copy (*node);
4812 39 : TREE_UNAVAILABLE (*node) = 1;
4813 39 : type = *node;
4814 : }
4815 : else
4816 : warn = 1;
4817 :
4818 256 : if (warn)
4819 : {
4820 0 : *no_add_attrs = true;
4821 0 : if (type && TYPE_NAME (type))
4822 : {
4823 0 : if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
4824 0 : what = TYPE_NAME (*node);
4825 0 : else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
4826 0 : && DECL_NAME (TYPE_NAME (type)))
4827 0 : what = DECL_NAME (TYPE_NAME (type));
4828 : }
4829 0 : if (what)
4830 0 : warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
4831 : else
4832 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
4833 : }
4834 :
4835 256 : return NULL_TREE;
4836 : }
4837 :
4838 : /* Return the "base" type from TYPE that is suitable to apply attribute
4839 : vector_size to by stripping arrays, function types, etc. */
4840 : static tree
4841 525346 : type_for_vector_size (tree type)
4842 : {
4843 : /* We need to provide for vector pointers, vector arrays, and
4844 : functions returning vectors. For example:
4845 :
4846 : __attribute__((vector_size(16))) short *foo;
4847 :
4848 : In this case, the mode is SI, but the type being modified is
4849 : HI, so we need to look further. */
4850 :
4851 525346 : while (POINTER_TYPE_P (type)
4852 : || TREE_CODE (type) == FUNCTION_TYPE
4853 : || TREE_CODE (type) == METHOD_TYPE
4854 : || TREE_CODE (type) == ARRAY_TYPE
4855 525807 : || TREE_CODE (type) == OFFSET_TYPE)
4856 461 : type = TREE_TYPE (type);
4857 :
4858 525346 : return type;
4859 : }
4860 :
4861 : /* Given TYPE, return the base type to which the vector_size attribute
4862 : ATNAME with ARGS, when non-null, can be applied, if one exists.
4863 : On success and when both ARGS and PTRNUNITS are non-null, set
4864 : *PTRNUNINTS to the number of vector units. When PTRNUNITS is not
4865 : null, issue a warning when the attribute argument is not constant
4866 : and an error if there is no such type. Otherwise issue a warning
4867 : in the latter case and return null. */
4868 :
4869 : static tree
4870 525344 : type_valid_for_vector_size (tree type, tree atname, tree args,
4871 : unsigned HOST_WIDE_INT *ptrnunits)
4872 : {
4873 525344 : bool hardbool_p = c_hardbool_type_attr (type);
4874 525344 : bool error_p = ptrnunits != NULL || hardbool_p;
4875 :
4876 : /* Get the mode of the type being modified. */
4877 525344 : machine_mode orig_mode = TYPE_MODE (type);
4878 :
4879 525344 : if ((!INTEGRAL_TYPE_P (type)
4880 525344 : && !SCALAR_FLOAT_TYPE_P (type)
4881 1 : && !FIXED_POINT_TYPE_P (type))
4882 525343 : || (!SCALAR_FLOAT_MODE_P (orig_mode)
4883 337395 : && GET_MODE_CLASS (orig_mode) != MODE_INT
4884 2 : && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
4885 525341 : || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
4886 525341 : || TREE_CODE (type) == BOOLEAN_TYPE
4887 525334 : || hardbool_p
4888 1050677 : || TREE_CODE (type) == BITINT_TYPE)
4889 : {
4890 13 : if (error_p)
4891 13 : error ("invalid vector type for attribute %qE", atname);
4892 : else
4893 0 : warning (OPT_Wattributes, "invalid vector type for attribute %qE",
4894 : atname);
4895 13 : return NULL_TREE;
4896 : }
4897 :
4898 : /* When no argument has been provided this is just a request to validate
4899 : the type above. Return TYPE to indicate success. */
4900 525331 : if (!args)
4901 : return type;
4902 :
4903 525331 : tree size = TREE_VALUE (args);
4904 : /* Erroneous arguments have already been diagnosed. */
4905 525331 : if (size == error_mark_node)
4906 : return NULL_TREE;
4907 :
4908 525327 : if (size && TREE_CODE (size) != IDENTIFIER_NODE
4909 525327 : && TREE_CODE (size) != FUNCTION_DECL)
4910 525319 : size = default_conversion (size);
4911 :
4912 525327 : if (TREE_CODE (size) != INTEGER_CST)
4913 : {
4914 8 : if (error_p)
4915 8 : error ("%qE attribute argument value %qE is not an integer constant",
4916 : atname, size);
4917 : else
4918 0 : warning (OPT_Wattributes,
4919 : "%qE attribute argument value %qE is not an integer constant",
4920 : atname, size);
4921 8 : return NULL_TREE;
4922 : }
4923 :
4924 525319 : if (!TYPE_UNSIGNED (TREE_TYPE (size))
4925 525319 : && tree_int_cst_sgn (size) < 0)
4926 : {
4927 1 : if (error_p)
4928 1 : error ("%qE attribute argument value %qE is negative",
4929 : atname, size);
4930 : else
4931 0 : warning (OPT_Wattributes,
4932 : "%qE attribute argument value %qE is negative",
4933 : atname, size);
4934 1 : return NULL_TREE;
4935 : }
4936 :
4937 : /* The attribute argument value is constrained by the maximum bit
4938 : alignment representable in unsigned int on the host. */
4939 525318 : unsigned HOST_WIDE_INT vecsize;
4940 525318 : unsigned HOST_WIDE_INT maxsize = tree_to_uhwi (max_object_size ());
4941 525318 : if (!tree_fits_uhwi_p (size)
4942 525318 : || (vecsize = tree_to_uhwi (size)) > maxsize)
4943 : {
4944 2 : if (error_p)
4945 2 : error ("%qE attribute argument value %qE exceeds %wu",
4946 : atname, size, maxsize);
4947 : else
4948 0 : warning (OPT_Wattributes,
4949 : "%qE attribute argument value %qE exceeds %wu",
4950 : atname, size, maxsize);
4951 2 : return NULL_TREE;
4952 : }
4953 :
4954 525316 : if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
4955 : {
4956 54 : if (error_p)
4957 2 : error ("vector size not an integral multiple of component size");
4958 54 : return NULL_TREE;
4959 : }
4960 :
4961 525262 : if (vecsize == 0)
4962 : {
4963 1 : error ("zero vector size");
4964 1 : return NULL;
4965 : }
4966 :
4967 : /* Calculate how many units fit in the vector. */
4968 525261 : unsigned HOST_WIDE_INT nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
4969 525261 : if (nunits & (nunits - 1))
4970 : {
4971 0 : if (error_p)
4972 0 : error ("number of vector components %wu not a power of two", nunits);
4973 : else
4974 0 : warning (OPT_Wattributes,
4975 : "number of vector components %wu not a power of two", nunits);
4976 0 : return NULL_TREE;
4977 : }
4978 :
4979 525261 : if (nunits >= (unsigned HOST_WIDE_INT)INT_MAX)
4980 : {
4981 1 : if (error_p)
4982 1 : error ("number of vector components %wu exceeds %d",
4983 : nunits, INT_MAX - 1);
4984 : else
4985 0 : warning (OPT_Wattributes,
4986 : "number of vector components %wu exceeds %d",
4987 : nunits, INT_MAX - 1);
4988 1 : return NULL_TREE;
4989 : }
4990 :
4991 525260 : if (ptrnunits)
4992 525136 : *ptrnunits = nunits;
4993 :
4994 : return type;
4995 : }
4996 :
4997 : /* Handle a "vector_size" attribute; arguments as in
4998 : struct attribute_spec.handler. */
4999 :
5000 : static tree
5001 525168 : handle_vector_size_attribute (tree *node, tree name, tree args,
5002 : int ARG_UNUSED (flags),
5003 : bool *no_add_attrs)
5004 : {
5005 525168 : *no_add_attrs = true;
5006 :
5007 : /* Determine the "base" type to apply the attribute to. */
5008 525168 : tree type = type_for_vector_size (*node);
5009 :
5010 : /* Get the vector size (in bytes) and let the function compute
5011 : the number of vector units. */
5012 525168 : unsigned HOST_WIDE_INT nunits;
5013 525168 : type = type_valid_for_vector_size (type, name, args, &nunits);
5014 525168 : if (!type)
5015 : return NULL_TREE;
5016 :
5017 525136 : gcc_checking_assert (args != NULL);
5018 :
5019 525136 : tree new_type = build_vector_type (type, nunits);
5020 :
5021 : /* Build back pointers if needed. */
5022 525136 : *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
5023 :
5024 525136 : return NULL_TREE;
5025 : }
5026 :
5027 : /* Handle a "vector_mask" attribute; arguments as in
5028 : struct attribute_spec.handler. */
5029 :
5030 : static tree
5031 2 : handle_vector_mask_attribute (tree *node, tree name, tree,
5032 : int ARG_UNUSED (flags),
5033 : bool *no_add_attrs)
5034 : {
5035 2 : *no_add_attrs = true;
5036 2 : if (!flag_gimple)
5037 : {
5038 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
5039 0 : return NULL_TREE;
5040 : }
5041 :
5042 : /* Determine the "base" type to apply the attribute to. */
5043 2 : tree type = type_for_vector_size (*node);
5044 2 : if (!VECTOR_TYPE_P (type) || VECTOR_BOOLEAN_TYPE_P (type))
5045 : {
5046 0 : warning (OPT_Wattributes, "%qE attribute only supported on "
5047 : "non-mask vector types", name);
5048 0 : return NULL_TREE;
5049 : }
5050 :
5051 2 : tree new_type = truth_type_for (type);
5052 :
5053 : /* Build back pointers if needed. */
5054 2 : *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
5055 :
5056 2 : return NULL_TREE;
5057 : }
5058 :
5059 : /* Handle the "nonnull" attribute. */
5060 :
5061 : static tree
5062 45033381 : handle_nonnull_attribute (tree *node, tree name,
5063 : tree args, int ARG_UNUSED (flags),
5064 : bool *no_add_attrs)
5065 : {
5066 45033381 : tree type = *node;
5067 :
5068 : /* If no arguments are specified, all pointer arguments should be
5069 : non-null. Verify a full prototype is given so that the arguments
5070 : will have the correct types when we actually check them later.
5071 : Avoid diagnosing type-generic built-ins since those have no
5072 : prototype. */
5073 45033381 : if (!args)
5074 : {
5075 24666237 : if (!prototype_p (type)
5076 24666237 : && (!TYPE_ATTRIBUTES (type)
5077 832644 : || !lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))))
5078 : {
5079 1 : error ("%qE attribute without arguments on a non-prototype",
5080 : name);
5081 1 : *no_add_attrs = true;
5082 : }
5083 24666237 : return NULL_TREE;
5084 : }
5085 :
5086 46925969 : for (int i = 1; args; ++i)
5087 : {
5088 26558851 : tree pos = TREE_VALUE (args);
5089 : /* NEXT is null when the attribute includes just one argument.
5090 : That's used to tell positional_argument to avoid mentioning
5091 : the argument number in diagnostics (since there's just one
5092 : mentioning it is unnecessary and could be confusing). */
5093 26558851 : tree next = TREE_CHAIN (args);
5094 26558851 : if (tree val = positional_argument (type, name, pos, POINTER_TYPE,
5095 26558851 : next || i > 1 ? i : 0))
5096 26558825 : TREE_VALUE (args) = val;
5097 : else
5098 : {
5099 26 : *no_add_attrs = true;
5100 26 : break;
5101 : }
5102 26558825 : args = next;
5103 : }
5104 :
5105 : return NULL_TREE;
5106 : }
5107 :
5108 : /* Handle the "nonnull_if_nonzero" attribute. */
5109 :
5110 : static tree
5111 15108729 : handle_nonnull_if_nonzero_attribute (tree *node, tree name,
5112 : tree args, int ARG_UNUSED (flags),
5113 : bool *no_add_attrs)
5114 : {
5115 15108729 : tree type = *node;
5116 15108729 : tree pos = TREE_VALUE (args);
5117 15108729 : tree pos2 = TREE_VALUE (TREE_CHAIN (args));
5118 15108729 : tree chain2 = TREE_CHAIN (TREE_CHAIN (args));
5119 15108729 : tree pos3 = NULL_TREE;
5120 15108729 : if (chain2)
5121 772927 : pos3 = TREE_VALUE (chain2);
5122 15108729 : tree val = positional_argument (type, name, pos, POINTER_TYPE, 1);
5123 15108729 : tree val2 = positional_argument (type, name, pos2, INTEGER_TYPE, 2);
5124 15108729 : tree val3 = NULL_TREE;
5125 15108729 : if (chain2)
5126 772927 : val3 = positional_argument (type, name, pos3, INTEGER_TYPE, 3);
5127 15108729 : if (val && val2 && (!chain2 || val3))
5128 : {
5129 15108716 : TREE_VALUE (args) = val;
5130 15108716 : TREE_VALUE (TREE_CHAIN (args)) = val2;
5131 15108716 : if (chain2)
5132 772922 : TREE_VALUE (chain2) = val3;
5133 : }
5134 : else
5135 13 : *no_add_attrs = true;
5136 :
5137 15108729 : return NULL_TREE;
5138 : }
5139 :
5140 : /* Handle the "fd_arg", "fd_arg_read" and "fd_arg_write" attributes */
5141 :
5142 : static tree
5143 32 : handle_fd_arg_attribute (tree *node, tree name, tree args,
5144 : int ARG_UNUSED (flags), bool *no_add_attrs)
5145 : {
5146 32 : tree type = *node;
5147 32 : if (!args)
5148 : {
5149 0 : if (!prototype_p (type))
5150 : {
5151 0 : error ("%qE attribute without arguments on a non-prototype", name);
5152 0 : *no_add_attrs = true;
5153 : }
5154 0 : return NULL_TREE;
5155 : }
5156 :
5157 32 : if (positional_argument (*node, name, TREE_VALUE (args), INTEGER_TYPE))
5158 : return NULL_TREE;
5159 :
5160 20 : *no_add_attrs = true;
5161 20 : return NULL_TREE;
5162 : }
5163 :
5164 : /* Handle the "flag_enum" attribute. */
5165 :
5166 : static tree
5167 41386 : handle_flag_enum_attribute (tree *node, tree ARG_UNUSED (name),
5168 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
5169 : bool *no_add_attrs)
5170 : {
5171 41386 : if (TREE_CODE (*node) != ENUMERAL_TYPE)
5172 : {
5173 0 : warning (OPT_Wattributes, "%qE attribute ignored on non-enum", name);
5174 0 : *no_add_attrs = true;
5175 : }
5176 :
5177 41386 : return NULL_TREE;
5178 : }
5179 :
5180 : /* Handle the "null_terminated_string_arg" attribute. */
5181 :
5182 : static tree
5183 64 : handle_null_terminated_string_arg_attribute (tree *node, tree name, tree args,
5184 : int ARG_UNUSED (flags),
5185 : bool *no_add_attrs)
5186 : {
5187 64 : if (positional_argument (*node, name, TREE_VALUE (args), POINTER_TYPE))
5188 : return NULL_TREE;
5189 :
5190 20 : *no_add_attrs = true;
5191 20 : return NULL_TREE;
5192 : }
5193 :
5194 : /* Common argument checking for btf_type_tag and btf_decl_tag.
5195 : Return true if the ARGS are valid, otherwise emit an error and
5196 : return false. */
5197 :
5198 : static bool
5199 112 : btf_tag_args_ok (tree name, tree args)
5200 : {
5201 112 : if (!args) /* Correct number of args (1) is checked for us. */
5202 : return false;
5203 112 : else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
5204 : {
5205 2 : error ("%qE attribute requires a string argument", name);
5206 2 : return false;
5207 : }
5208 :
5209 : /* Only narrow character strings are accepted. */
5210 110 : tree argtype = TREE_TYPE (TREE_TYPE (TREE_VALUE (args)));
5211 110 : if (!(argtype == char_type_node
5212 6 : || argtype == char8_type_node
5213 6 : || argtype == signed_char_type_node
5214 6 : || argtype == unsigned_char_type_node))
5215 : {
5216 6 : error ("unsupported wide string type argument in %qE attribute", name);
5217 6 : return false;
5218 : }
5219 :
5220 : return true;
5221 : }
5222 :
5223 : /* Handle the "btf_decl_tag" attribute. */
5224 :
5225 : static tree
5226 52 : handle_btf_decl_tag_attribute (tree * ARG_UNUSED (node), tree name, tree args,
5227 : int ARG_UNUSED (flags), bool *no_add_attrs)
5228 : {
5229 52 : if (!btf_tag_args_ok (name, args))
5230 4 : *no_add_attrs = true;
5231 :
5232 52 : return NULL_TREE;
5233 : }
5234 :
5235 : /* Handle the "btf_type_tag" attribute. */
5236 :
5237 : static tree
5238 60 : handle_btf_type_tag_attribute (tree *node, tree name, tree args,
5239 : int flags, bool *no_add_attrs)
5240 : {
5241 60 : if (!btf_tag_args_ok (name, args))
5242 : {
5243 4 : *no_add_attrs = true;
5244 4 : return NULL_TREE;
5245 : }
5246 :
5247 56 : if (TREE_CODE (*node) == FUNCTION_TYPE || TREE_CODE (*node) == METHOD_TYPE)
5248 : {
5249 3 : warning (OPT_Wattributes,
5250 : "%qE attribute does not apply to functions", name);
5251 3 : *no_add_attrs = true;
5252 3 : return NULL_TREE;
5253 : }
5254 :
5255 : /* Ensure a variant type is always created to hold the type_tag,
5256 : unless ATTR_FLAG_IN_PLACE is set. Same logic as in
5257 : common_handle_aligned_attribute. */
5258 53 : tree decl = NULL_TREE;
5259 53 : tree *type = NULL;
5260 53 : bool is_type = false;
5261 :
5262 53 : if (DECL_P (*node))
5263 : {
5264 0 : decl = *node;
5265 0 : type = &TREE_TYPE (decl);
5266 0 : is_type = TREE_CODE (*node) == TYPE_DECL;
5267 : }
5268 53 : else if (TYPE_P (*node))
5269 : type = node, is_type = true;
5270 :
5271 0 : if (is_type)
5272 : {
5273 53 : if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
5274 : /* OK, modify the type in place. */;
5275 :
5276 : /* If we have a TYPE_DECL, then copy the type, so that we
5277 : don't accidentally modify a builtin type. See pushdecl. */
5278 0 : else if (decl && TREE_TYPE (decl) != error_mark_node
5279 49 : && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
5280 : {
5281 0 : tree tt = TREE_TYPE (decl);
5282 0 : *type = build_variant_type_copy (*type);
5283 0 : DECL_ORIGINAL_TYPE (decl) = tt;
5284 0 : TYPE_NAME (*type) = decl;
5285 0 : TREE_USED (*type) = TREE_USED (decl);
5286 0 : TREE_TYPE (decl) = *type;
5287 : }
5288 : else
5289 49 : *type = build_variant_type_copy (*type);
5290 : }
5291 :
5292 : return NULL_TREE;
5293 : }
5294 :
5295 : /* Handle the "nonstring" variable attribute. */
5296 :
5297 : static tree
5298 894 : handle_nonstring_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5299 : int ARG_UNUSED (flags), bool *no_add_attrs)
5300 : {
5301 894 : gcc_assert (!args);
5302 894 : tree_code code = TREE_CODE (*node);
5303 :
5304 894 : if (VAR_P (*node)
5305 409 : || code == FIELD_DECL
5306 409 : || code == PARM_DECL)
5307 : {
5308 886 : tree type = TREE_TYPE (*node);
5309 :
5310 886 : if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
5311 : {
5312 : /* Accept the attribute on arrays and pointers to all three
5313 : narrow character types, including multi-dimensional arrays
5314 : or pointers to them. */
5315 878 : tree eltype = strip_array_types (TREE_TYPE (type));
5316 878 : eltype = TYPE_MAIN_VARIANT (eltype);
5317 878 : if (eltype == char_type_node
5318 136 : || eltype == signed_char_type_node
5319 72 : || eltype == unsigned_char_type_node)
5320 : return NULL_TREE;
5321 : }
5322 :
5323 16 : warning (OPT_Wattributes,
5324 : "%qE attribute ignored on objects of type %qT",
5325 : name, type);
5326 16 : *no_add_attrs = true;
5327 16 : return NULL_TREE;
5328 : }
5329 :
5330 8 : if (code == FUNCTION_DECL)
5331 4 : warning (OPT_Wattributes,
5332 : "%qE attribute does not apply to functions", name);
5333 4 : else if (code == TYPE_DECL)
5334 4 : warning (OPT_Wattributes,
5335 : "%qE attribute does not apply to types", name);
5336 : else
5337 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
5338 :
5339 8 : *no_add_attrs = true;
5340 8 : return NULL_TREE;
5341 : }
5342 :
5343 : /* Given a function type FUNCTYPE, returns the type of the parameter
5344 : ARGNO or null if ARGNO exceeds the number of parameters. On failure
5345 : set *NARGS to the number of function parameters. */
5346 :
5347 : static tree
5348 1240209 : get_argument_type (tree functype, unsigned argno, unsigned *nargs)
5349 : {
5350 1240209 : function_args_iterator iter;
5351 1240209 : function_args_iter_init (&iter, functype);
5352 :
5353 1240209 : unsigned count = 0;
5354 :
5355 2537165 : for ( ; iter.next; ++count, function_args_iter_next (&iter))
5356 : {
5357 2537159 : if (count + 1 == argno)
5358 : {
5359 1240203 : tree argtype = function_args_iter_cond (&iter);
5360 1240203 : if (VOID_TYPE_P (argtype))
5361 : break;
5362 1240200 : if (argtype != error_mark_node)
5363 : return argtype;
5364 : }
5365 : }
5366 :
5367 9 : *nargs = count;
5368 9 : return NULL_TREE;
5369 : }
5370 :
5371 : /* Given a function FNDECL return the function argument at the zero-
5372 : based position ARGNO or null if it can't be found. */
5373 :
5374 : static tree
5375 6 : get_argument (tree fndecl, unsigned argno)
5376 : {
5377 6 : if (!DECL_P (fndecl))
5378 : return NULL_TREE;
5379 :
5380 6 : unsigned i = 0;
5381 10 : for (tree arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
5382 8 : if (i++ == argno)
5383 : return arg;
5384 :
5385 : return NULL_TREE;
5386 : }
5387 :
5388 : /* Attempt to append attribute access specification ATTRSPEC, optionally
5389 : described by the human-readable string ATTRSTR, for type T, to one in
5390 : ATTRS. VBLIST is an optional list of bounds of variable length array
5391 : parameters described by ATTRSTR.
5392 : Issue warning for conflicts and return null if any are found.
5393 : Return the concatenated access string on success. */
5394 :
5395 : static tree
5396 1091566 : append_access_attr (tree node[3], tree attrs, const char *attrstr,
5397 : const char *attrspec, tree vblist = NULL_TREE)
5398 : {
5399 1091566 : tree argstr = build_string (strlen (attrspec) + 1, attrspec);
5400 1091566 : tree ataccess = tree_cons (NULL_TREE, argstr, vblist);
5401 1091566 : ataccess = tree_cons (get_identifier ("access"), ataccess, NULL_TREE);
5402 :
5403 : /* The access specification being applied. This may be an implicit
5404 : access spec synthesized for array (or VLA) parameters even for
5405 : a declaration with an explicit access spec already applied, if
5406 : this call corresponds to the first declaration of the function. */
5407 1091566 : rdwr_map new_idxs;
5408 1091566 : init_attr_rdwr_indices (&new_idxs, ataccess);
5409 :
5410 : /* The current access specification alrady applied. */
5411 1091566 : rdwr_map cur_idxs;
5412 1091566 : init_attr_rdwr_indices (&cur_idxs, attrs);
5413 :
5414 1091566 : tree args = TYPE_ARG_TYPES (node[0]);
5415 1091566 : int argpos = 0;
5416 1091566 : std::string spec;
5417 5066635 : for (tree arg = args; arg; arg = TREE_CHAIN (arg), argpos++)
5418 : {
5419 3975069 : const attr_access* const newa = new_idxs.get (argpos);
5420 :
5421 3975069 : if (!newa)
5422 6272972 : continue;
5423 :
5424 : /* The map has two equal entries for each pointer argument that
5425 : has an associated size argument. Process just the entry for
5426 : the former. */
5427 1677083 : if ((unsigned)argpos != newa->ptrarg)
5428 551213 : continue;
5429 :
5430 1125870 : const attr_access* const cura = cur_idxs.get (argpos);
5431 1125870 : if (!cura)
5432 : {
5433 : /* The new attribute needs to be added. */
5434 1119314 : tree str = newa->to_internal_string ();
5435 1119314 : spec += TREE_STRING_POINTER (str);
5436 1119314 : continue;
5437 1119314 : }
5438 :
5439 : /* The new access spec refers to an array/pointer argument for
5440 : which an access spec already exists. Check and diagnose any
5441 : conflicts. If no conflicts are found, merge the two. */
5442 :
5443 6556 : if (!attrstr)
5444 : {
5445 6367 : tree str = NULL_TREE;
5446 6367 : if (newa->mode != access_deferred)
5447 0 : str = newa->to_external_string ();
5448 6367 : else if (cura->mode != access_deferred)
5449 2159 : str = cura->to_external_string ();
5450 2159 : if (str)
5451 2159 : attrstr = TREE_STRING_POINTER (str);
5452 : }
5453 :
5454 6556 : location_t curloc = input_location;
5455 6556 : if (node[2] && DECL_P (node[2]))
5456 6556 : curloc = DECL_SOURCE_LOCATION (node[2]);
5457 :
5458 6556 : location_t prevloc = UNKNOWN_LOCATION;
5459 6556 : if (node[1] && DECL_P (node[1]))
5460 3707 : prevloc = DECL_SOURCE_LOCATION (node[1]);
5461 :
5462 6556 : if (newa->mode != cura->mode
5463 2181 : && newa->mode != access_deferred
5464 22 : && cura->mode != access_deferred
5465 10 : && newa->internal_p == cura->internal_p)
5466 : {
5467 : /* Mismatch in access mode. */
5468 10 : auto_diagnostic_group d;
5469 0 : if (warning_at (curloc, OPT_Wattributes,
5470 : "attribute %qs mismatch with mode %qs",
5471 10 : attrstr, cura->mode_names[cura->mode])
5472 10 : && prevloc != UNKNOWN_LOCATION)
5473 10 : inform (prevloc, "previous declaration here");
5474 10 : continue;
5475 10 : }
5476 :
5477 : /* Set if PTRARG refers to a VLA with an unspecified bound (T[*]).
5478 : Be prepared for either CURA or NEWA to refer to it, depending
5479 : on which happens to come first in the declaration. */
5480 13092 : const bool cur_vla_ub = (cura->internal_p
5481 4243 : && cura->sizarg == UINT_MAX
5482 10683 : && cura->minsize == HOST_WIDE_INT_M1U);
5483 13092 : const bool new_vla_ub = (newa->internal_p
5484 6367 : && newa->sizarg == UINT_MAX
5485 12804 : && newa->minsize == HOST_WIDE_INT_M1U);
5486 :
5487 6546 : if (newa->sizarg != cura->sizarg
5488 2109 : && attrstr
5489 2106 : && (!(cur_vla_ub ^ new_vla_ub)
5490 19 : || (!cura->internal_p && !newa->internal_p)))
5491 : {
5492 : /* Avoid diagnosing redeclarations of functions with no explicit
5493 : attribute access that add one. */
5494 2087 : if (newa->mode == access_deferred
5495 2077 : && cura->mode != access_deferred
5496 2077 : && newa->sizarg == UINT_MAX
5497 2073 : && cura->sizarg != UINT_MAX)
5498 2073 : continue;
5499 :
5500 14 : if (cura->mode == access_deferred
5501 4 : && newa->mode != access_deferred
5502 4 : && cura->sizarg == UINT_MAX
5503 3 : && newa->sizarg != UINT_MAX)
5504 3 : continue;
5505 :
5506 : /* The two specs designate different size arguments. It's okay
5507 : for the explicit spec to specify a size where none is provided
5508 : by the implicit (VLA) one, as in:
5509 : __attribute__ ((access (read_write, 1, 2)))
5510 : void f (int*, int);
5511 : but not for two explicit access attributes to do that. */
5512 11 : bool warned = false;
5513 :
5514 11 : auto_diagnostic_group d;
5515 :
5516 11 : if (newa->sizarg == UINT_MAX)
5517 : /* Mismatch in the presence of the size argument. */
5518 2 : warned = warning_at (curloc, OPT_Wattributes,
5519 : "attribute %qs missing positional argument 2 "
5520 : "provided in previous designation by argument "
5521 2 : "%u", attrstr, cura->sizarg + 1);
5522 9 : else if (cura->sizarg == UINT_MAX)
5523 : /* Mismatch in the presence of the size argument. */
5524 3 : warned = warning_at (curloc, OPT_Wattributes,
5525 : "attribute %qs positional argument 2 "
5526 : "missing in previous designation",
5527 : attrstr);
5528 6 : else if (newa->internal_p || cura->internal_p)
5529 : /* Mismatch in the value of the size argument and a VLA bound. */
5530 4 : warned = warning_at (curloc, OPT_Wattributes,
5531 : "attribute %qs positional argument 2 "
5532 : "conflicts with previous designation "
5533 : "by argument %u",
5534 : attrstr, cura->sizarg + 1);
5535 : else
5536 : /* Mismatch in the value of the size argument between two
5537 : explicit access attributes. */
5538 2 : warned = warning_at (curloc, OPT_Wattributes,
5539 : "attribute %qs mismatched positional argument "
5540 : "values %i and %i",
5541 : attrstr, newa->sizarg + 1, cura->sizarg + 1);
5542 :
5543 11 : if (warned)
5544 : {
5545 : /* If the previous declaration is a function (as opposed
5546 : to a typedef of one), find the location of the array
5547 : or pointer argument that uses the conflicting VLA bound
5548 : and point to it in the note. */
5549 11 : const attr_access* const pa = cura->size ? cura : newa;
5550 11 : tree size = pa->size ? TREE_VALUE (pa->size) : NULL_TREE;
5551 6 : if (size && DECL_P (size))
5552 : {
5553 6 : location_t argloc = UNKNOWN_LOCATION;
5554 6 : if (tree arg = get_argument (node[2], pa->ptrarg))
5555 4 : argloc = DECL_SOURCE_LOCATION (arg);
5556 :
5557 6 : gcc_rich_location richloc (DECL_SOURCE_LOCATION (size));
5558 6 : if (argloc != UNKNOWN_LOCATION)
5559 4 : richloc.add_range (argloc);
5560 :
5561 6 : inform (&richloc, "designating the bound of variable "
5562 : "length array argument %u",
5563 6 : pa->ptrarg + 1);
5564 6 : }
5565 5 : else if (prevloc != UNKNOWN_LOCATION)
5566 3 : inform (prevloc, "previous declaration here");
5567 : }
5568 :
5569 11 : continue;
5570 11 : }
5571 :
5572 4459 : if (newa->internal_p == cura->internal_p)
5573 4376 : continue;
5574 :
5575 : /* Merge the CURA and NEWA. */
5576 83 : attr_access merged = *newa;
5577 :
5578 : /* VLA seen in a declaration takes precedence. */
5579 83 : if (cura->minsize == HOST_WIDE_INT_M1U)
5580 17 : merged.minsize = HOST_WIDE_INT_M1U;
5581 :
5582 : /* Use the explicitly specified size positional argument. */
5583 83 : if (cura->sizarg != UINT_MAX)
5584 25 : merged.sizarg = cura->sizarg;
5585 :
5586 : /* Use the explicitly specified mode. */
5587 83 : if (merged.mode == access_deferred)
5588 68 : merged.mode = cura->mode;
5589 :
5590 83 : tree str = merged.to_internal_string ();
5591 83 : spec += TREE_STRING_POINTER (str);
5592 : }
5593 :
5594 1091566 : if (!spec.length ())
5595 : return NULL_TREE;
5596 :
5597 1087411 : return build_string (spec.length (), spec.c_str ());
5598 1091566 : }
5599 :
5600 : /* Convenience wrapper for the above. */
5601 :
5602 : static tree
5603 689449 : append_access_attr_idxs (tree node[3], tree attrs, const char *attrstr,
5604 : char code, HOST_WIDE_INT idxs[2])
5605 : {
5606 689449 : char attrspec[80];
5607 689449 : int n = sprintf (attrspec, "%c%u", code, (unsigned) idxs[0] - 1);
5608 689449 : if (idxs[1])
5609 550977 : n += sprintf (attrspec + n, ",%u", (unsigned) idxs[1] - 1);
5610 :
5611 689449 : return append_access_attr (node, attrs, attrstr, attrspec);
5612 : }
5613 :
5614 : /* Handle the access attribute for function type NODE[0], with the function
5615 : DECL optionally in NODE[1]. The handler is called both in response to
5616 : an explict attribute access on a declaration with a mode and one or two
5617 : positional arguments, and for internally synthesized access specifications
5618 : with a string argument optionally followd by a DECL or expression
5619 : representing a VLA bound. To speed up parsing, the handler transforms
5620 : the attribute and its arguments into a string. */
5621 :
5622 : static tree
5623 2178587 : handle_access_attribute (tree node[3], tree name, tree args, int flags,
5624 : bool *no_add_attrs)
5625 : {
5626 2178587 : tree attrs = TYPE_ATTRIBUTES (*node);
5627 2178587 : tree type = *node;
5628 2178587 : if (POINTER_TYPE_P (type))
5629 : {
5630 0 : tree ptype = TREE_TYPE (type);
5631 0 : if (FUNC_OR_METHOD_TYPE_P (ptype))
5632 2178587 : type = ptype;
5633 : }
5634 :
5635 2178587 : *no_add_attrs = true;
5636 :
5637 : /* Verify a full prototype is provided so that the argument types
5638 : can be validated. Avoid diagnosing type-generic built-ins since
5639 : those have no prototype. */
5640 2178587 : if (!args
5641 0 : && !prototype_p (type)
5642 2178587 : && (!attrs || !lookup_attribute ("type generic", attrs)))
5643 : {
5644 0 : error ("attribute %qE without arguments on a non-prototype", name);
5645 0 : return NULL_TREE;
5646 : }
5647 :
5648 2178587 : tree access_mode = TREE_VALUE (args);
5649 2178587 : if (TREE_CODE (access_mode) == STRING_CST)
5650 : {
5651 1489308 : const char* const str = TREE_STRING_POINTER (access_mode);
5652 1489308 : if (*str == '+')
5653 : {
5654 : /* This is a request to merge an internal specification for
5655 : a function declaration involving arrays but no explicit
5656 : attribute access. */
5657 402117 : tree vblist = TREE_CHAIN (args);
5658 402117 : tree axstr = append_access_attr (node, attrs, NULL, str + 1,
5659 : vblist);
5660 402117 : if (!axstr)
5661 : return NULL_TREE;
5662 :
5663 : /* Replace any existing access attribute specification with
5664 : the concatenation above. */
5665 398136 : tree axsat = tree_cons (NULL_TREE, axstr, vblist);
5666 398136 : axsat = tree_cons (name, axsat, NULL_TREE);
5667 :
5668 : /* Recursively call self to "replace" the documented/external
5669 : form of the attribute with the condensend internal form. */
5670 398136 : decl_attributes (node, axsat, flags | ATTR_FLAG_INTERNAL);
5671 398136 : return NULL_TREE;
5672 : }
5673 :
5674 1087191 : if (flags & ATTR_FLAG_INTERNAL)
5675 : {
5676 : /* This is a recursive call to handle the condensed internal
5677 : form of the attribute (see below). Since all validation
5678 : has been done simply return here, accepting the attribute
5679 : as is. */
5680 1087189 : *no_add_attrs = false;
5681 1087189 : return NULL_TREE;
5682 : }
5683 : }
5684 :
5685 : /* Set to true when the access mode has the form of a function call
5686 : as in 'attribute (read_only (1, 2))'. That's an easy mistake to
5687 : make and so worth a special diagnostic. */
5688 689281 : bool funcall = false;
5689 689281 : if (TREE_CODE (access_mode) == CALL_EXPR)
5690 : {
5691 6 : access_mode = CALL_EXPR_FN (access_mode);
5692 6 : if (TREE_CODE (access_mode) != ADDR_EXPR)
5693 : {
5694 0 : error ("attribute %qE invalid mode", name);
5695 0 : return NULL_TREE;
5696 : }
5697 6 : access_mode = TREE_OPERAND (access_mode, 0);
5698 6 : access_mode = DECL_NAME (access_mode);
5699 6 : funcall = true;
5700 : }
5701 689275 : else if (TREE_CODE (access_mode) != IDENTIFIER_NODE)
5702 : {
5703 5 : error ("attribute %qE mode %qE is not an identifier; expected one of "
5704 : "%qs, %qs, %qs, or %qs", name, access_mode,
5705 : "read_only", "read_write", "write_only", "none");
5706 5 : return NULL_TREE;
5707 : }
5708 :
5709 689276 : const char* const access_str = IDENTIFIER_POINTER (access_mode);
5710 689276 : const char *ps = access_str;
5711 689276 : if (ps[0] == '_' && ps[1] == '_')
5712 : {
5713 688734 : size_t len = strlen (ps);
5714 688734 : if (ps[len - 1] == '_' && ps[len - 2] == '_')
5715 688734 : ps += 2;
5716 : }
5717 :
5718 689276 : int imode;
5719 :
5720 689276 : {
5721 689276 : const int nmodes = ARRAY_SIZE (attr_access::mode_names);
5722 :
5723 1847809 : for (imode = 0; imode != nmodes; ++imode)
5724 1847791 : if (!strncmp (ps, attr_access::mode_names[imode],
5725 1847791 : strlen (attr_access::mode_names[imode])))
5726 : break;
5727 :
5728 689276 : if (imode == nmodes)
5729 : {
5730 18 : error ("attribute %qE invalid mode %qs; expected one of "
5731 : "%qs, %qs, %qs, or %qs", name, access_str,
5732 : "read_only", "read_write", "write_only", "none");
5733 18 : return NULL_TREE;
5734 : }
5735 : }
5736 :
5737 689258 : const ::access_mode mode = static_cast<::access_mode>(imode);
5738 :
5739 689258 : if (funcall)
5740 : {
5741 3 : error ("attribute %qE unexpected %<(%> after mode %qs; expected "
5742 : "a positional argument or %<)%>",
5743 : name, access_str);
5744 3 : return NULL_TREE;
5745 : }
5746 :
5747 689255 : args = TREE_CHAIN (args);
5748 689255 : if (!args)
5749 : {
5750 : /* The first positional argument is required. It may be worth
5751 : dropping the requirement at some point and having read_only
5752 : apply to all const-qualified pointers and read_write or
5753 : write_only to the rest. */
5754 4 : error ("attribute %<%E(%s)%> missing an argument",
5755 : name, access_str);
5756 4 : return NULL_TREE;
5757 : }
5758 :
5759 : /* One or more positional arguments have been specified. Validate
5760 : them. */
5761 689251 : tree idxnodes[2] = { NULL_TREE, NULL_TREE };
5762 689251 : tree argtypes[2] = { NULL_TREE, NULL_TREE };
5763 : /* 1-based attribute positional arguments or zero if not specified.
5764 : Invalid negative or excessive values are also stored but used
5765 : only in diagnostics. */
5766 689251 : HOST_WIDE_INT idxs[2] = { 0, 0 };
5767 :
5768 : /* Number of function formal arguments (used in diagnostics). */
5769 689251 : unsigned nfuncargs = 0;
5770 : /* Number of (optional) attribute positional arguments. */
5771 689251 : unsigned nattrargs = 0;
5772 :
5773 1929466 : for (unsigned i = 0; i != 2; ++i, args = TREE_CHAIN (args), ++nattrargs)
5774 : {
5775 1378502 : if (!args)
5776 : break;
5777 :
5778 1240215 : idxnodes[i] = TREE_VALUE (args);
5779 :
5780 1240215 : if (TREE_CODE (idxnodes[i]) != IDENTIFIER_NODE
5781 1240215 : && TREE_CODE (idxnodes[i]) != FUNCTION_DECL)
5782 1240215 : idxnodes[i] = default_conversion (idxnodes[i]);
5783 :
5784 1240215 : if (tree_fits_shwi_p (idxnodes[i]))
5785 : {
5786 1240209 : idxs[i] = tree_to_shwi (idxnodes[i]);
5787 1240209 : argtypes[i] = get_argument_type (type, idxs[i], &nfuncargs);
5788 : }
5789 : }
5790 :
5791 689251 : if ((nattrargs == 1 && !idxs[0])
5792 689248 : || (nattrargs == 2 && (!idxs[0] || !idxs[1])))
5793 : {
5794 6 : if (idxnodes[1])
5795 3 : error ("attribute %<%E(%s, %E, %E)%> invalid positional argument %i",
5796 3 : name, access_str, idxnodes[0], idxnodes[1], idxs[0] ? 2 : 1);
5797 : else
5798 3 : error ("attribute %<%E(%s, %E)%> invalid positional argument %i",
5799 3 : name, access_str, idxnodes[0], idxs[0] ? 2 : 1);
5800 6 : return NULL_TREE;
5801 : }
5802 :
5803 : /* Format the attribute specification to include in diagnostics. */
5804 689245 : char attrstr[80];
5805 689245 : if (idxnodes[1])
5806 1101922 : snprintf (attrstr, sizeof attrstr, "%s(%s, %lli, %lli)",
5807 550961 : IDENTIFIER_POINTER (name), access_str,
5808 550961 : (long long) idxs[0], (long long) idxs[1]);
5809 138284 : else if (idxnodes[0])
5810 276568 : snprintf (attrstr, sizeof attrstr, "%s(%s, %lli)",
5811 138284 : IDENTIFIER_POINTER (name), access_str,
5812 138284 : (long long) idxs[0]);
5813 : else
5814 0 : snprintf (attrstr, sizeof attrstr, "%s(%s)",
5815 0 : IDENTIFIER_POINTER (name), access_str);
5816 :
5817 : /* Verify the positional argument values are in range. */
5818 689245 : if (!argtypes[0] || (idxnodes[1] && !argtypes[1]))
5819 : {
5820 9 : if (idxnodes[0])
5821 : {
5822 9 : if (idxs[0] < 0 || idxs[1] < 0)
5823 9 : error ("attribute %qs positional argument %i invalid value %wi",
5824 : attrstr, idxs[0] < 0 ? 1 : 2,
5825 : idxs[0] < 0 ? idxs[0] : idxs[1]);
5826 : else
5827 3 : error ("attribute %qs positional argument %i value %wi exceeds "
5828 : "number of function arguments %u",
5829 : attrstr, idxs[0] ? 1 : 2,
5830 : idxs[0] ? idxs[0] : idxs[1],
5831 : nfuncargs);
5832 : }
5833 : else
5834 0 : error ("attribute %qs invalid positional argument", attrstr);
5835 :
5836 9 : return NULL_TREE;
5837 : }
5838 :
5839 689236 : if (!POINTER_TYPE_P (argtypes[0]))
5840 : {
5841 : /* The first argument must have a pointer or reference type. */
5842 4 : error ("attribute %qs positional argument 1 references "
5843 : "non-pointer argument type %qT",
5844 : attrstr, argtypes[0]);
5845 4 : return NULL_TREE;
5846 : }
5847 :
5848 689232 : {
5849 : /* Pointers to functions are not allowed. */
5850 689232 : tree ptrtype = TREE_TYPE (argtypes[0]);
5851 689232 : if (FUNC_OR_METHOD_TYPE_P (ptrtype))
5852 : {
5853 3 : error ("attribute %qs positional argument 1 references "
5854 : "argument of function type %qT",
5855 : attrstr, ptrtype);
5856 3 : return NULL_TREE;
5857 : }
5858 : }
5859 :
5860 689229 : if (mode == access_read_write || mode == access_write_only)
5861 : {
5862 : /* Read_write and write_only modes must reference non-const
5863 : arguments. */
5864 451554 : if (TYPE_READONLY (TREE_TYPE (argtypes[0])))
5865 : {
5866 3 : error ("attribute %qs positional argument 1 references "
5867 : "%qs-qualified argument type %qT",
5868 : attrstr, "const", argtypes[0]);
5869 3 : return NULL_TREE;
5870 : }
5871 : }
5872 237675 : else if (!TYPE_READONLY (TREE_TYPE (argtypes[0])))
5873 : {
5874 : /* A read_only mode should ideally reference const-qualified
5875 : arguments but it's not diagnosed error if one doesn't.
5876 : This makes it possible to annotate legacy, const-incorrect
5877 : APIs. It might be worth a diagnostic along the lines of
5878 : -Wsuggest-const. */
5879 237675 : ;
5880 : }
5881 :
5882 689226 : if (argtypes[1] && !INTEGRAL_TYPE_P (argtypes[1]))
5883 : {
5884 12 : error ("attribute %qs positional argument 2 references "
5885 : "non-integer argument type %qT",
5886 : attrstr, argtypes[1]);
5887 12 : return NULL_TREE;
5888 : }
5889 :
5890 : /* Verify that the new attribute doesn't conflict with any existing
5891 : attributes specified on previous declarations of the same type
5892 : and if not, concatenate the two. */
5893 689214 : const char code = attr_access::mode_chars[mode];
5894 689214 : tree new_attrs = append_access_attr_idxs (node, attrs, attrstr, code, idxs);
5895 689214 : if (!new_attrs)
5896 : return NULL_TREE;
5897 :
5898 : /* Replace any existing access attribute specification with
5899 : the concatenation above. */
5900 689199 : new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
5901 689199 : new_attrs = tree_cons (name, new_attrs, NULL_TREE);
5902 :
5903 689199 : if (node[1])
5904 : {
5905 : /* Repeat for the previously declared type. */
5906 235 : attrs = TYPE_ATTRIBUTES (TREE_TYPE (node[1]));
5907 235 : new_attrs = append_access_attr_idxs (node, attrs, attrstr, code, idxs);
5908 235 : if (!new_attrs)
5909 : return NULL_TREE;
5910 :
5911 76 : new_attrs = tree_cons (NULL_TREE, new_attrs, NULL_TREE);
5912 76 : new_attrs = tree_cons (name, new_attrs, NULL_TREE);
5913 : }
5914 :
5915 : /* Recursively call self to "replace" the documented/external form
5916 : of the attribute with the condensed internal form. */
5917 689040 : decl_attributes (node, new_attrs, flags | ATTR_FLAG_INTERNAL);
5918 689040 : return NULL_TREE;
5919 : }
5920 :
5921 :
5922 : /* This function builds a string which is concatenated to SPEC and returns
5923 : list of variably bounds corresponding to an array/VLA parameter with
5924 : type TYPE. The string consists of one dollar symbol for each specified
5925 : variable bound, one asterisk for each unspecified variable bound,
5926 : a space for an array of unknown size (only possibly for the outermost),
5927 : and a zero for a zero-sized array.
5928 :
5929 : The chainof variable bounds starts with the most significant bound.
5930 : For example, the TYPE T[2][m][3][n] will produce "$$" and (m, (n, nil)). */
5931 :
5932 : static tree
5933 973310 : build_arg_spec (tree type, std::string *spec)
5934 : {
5935 992071 : while (POINTER_TYPE_P (type))
5936 18761 : type = TREE_TYPE (type);
5937 :
5938 973310 : if (TREE_CODE (type) != ARRAY_TYPE)
5939 : return NULL_TREE;
5940 :
5941 495750 : tree list = build_arg_spec (TREE_TYPE (type), spec);
5942 :
5943 495750 : if (!COMPLETE_TYPE_P (type))
5944 : {
5945 65008 : (*spec) += ' ';
5946 65008 : return list;
5947 : }
5948 :
5949 430742 : tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5950 :
5951 430742 : if (!mval)
5952 : {
5953 56 : (*spec) += '0';
5954 56 : return list;
5955 : }
5956 :
5957 430686 : if (TREE_CODE (mval) == COMPOUND_EXPR
5958 155 : && integer_zerop (TREE_OPERAND (mval, 0))
5959 430841 : && integer_zerop (TREE_OPERAND (mval, 1)))
5960 : {
5961 145 : (*spec) += '*';
5962 145 : return list;
5963 : }
5964 :
5965 430541 : if (TREE_CODE (mval) == INTEGER_CST)
5966 : return list;
5967 :
5968 : /* A variable bound. */
5969 13975 : (*spec) += '$';
5970 :
5971 13975 : mval = array_type_nelts_top (type);
5972 :
5973 : /* Remove NOP_EXPR and SAVE_EXPR to uncover possible PARM_DECLS. */
5974 13975 : if (TREE_CODE (mval) == NOP_EXPR)
5975 13965 : mval = TREE_OPERAND (mval, 0);
5976 13975 : if (TREE_CODE (mval) == SAVE_EXPR)
5977 : {
5978 13940 : mval = TREE_OPERAND (mval, 0);
5979 13940 : if (TREE_CODE (mval) == NOP_EXPR)
5980 0 : mval = TREE_OPERAND (mval, 0);
5981 : }
5982 :
5983 13975 : return tree_cons (NULL_TREE, mval, list);
5984 : }
5985 :
5986 : /* Extract attribute "arg spec" from each FNDECL argument that has it,
5987 : build a single attribute access corresponding to all the arguments,
5988 : and return the result. SKIP_VOIDPTR set to ignore void* parameters
5989 : (used for user-defined functions for which, unlike in for built-ins,
5990 : void* cannot be relied on to determine anything about the access
5991 : through it or whether it even takes place).
5992 :
5993 : For example, the parameters in the declaration:
5994 :
5995 : void f (int x, int y, char [x][1][y][3], char [y][2][y][5]);
5996 :
5997 : result in the following attribute access:
5998 :
5999 : value: "+^2[*],$0$1^3[*],$1$1"
6000 : list: < <0, x> <1, y> >
6001 :
6002 : where the list has a single value which itself is a list, each
6003 : of whose <node>s corresponds to one VLA bound for each of the two
6004 : parameters. */
6005 :
6006 : tree
6007 51633399 : build_attr_access_from_parms (tree parms, bool skip_voidptr)
6008 : {
6009 : /* Maps each named integral argument DECL seen so far to its position
6010 : in the argument list; used to associate VLA sizes with arguments. */
6011 51633399 : hash_map<tree, unsigned> arg2pos;
6012 :
6013 : /* The string representation of the access specification for all
6014 : arguments. */
6015 51633399 : std::string spec;
6016 51633399 : unsigned argpos = 0;
6017 :
6018 : /* A TREE_LIST of VLA bounds. */
6019 51633399 : tree vblist = NULL_TREE;
6020 :
6021 177382772 : for (tree arg = parms; arg; arg = TREE_CHAIN (arg), ++argpos)
6022 : {
6023 125749373 : if (!DECL_P (arg))
6024 34275 : continue;
6025 :
6026 125715098 : tree argtype = TREE_TYPE (arg);
6027 125715098 : if (DECL_NAME (arg) && INTEGRAL_TYPE_P (argtype))
6028 37410458 : arg2pos.put (arg, argpos);
6029 : }
6030 :
6031 51633399 : tree nnlist = NULL_TREE;
6032 51633399 : argpos = 0;
6033 177382772 : for (tree arg = parms; arg; arg = TREE_CHAIN (arg), ++argpos)
6034 : {
6035 125749373 : if (!DECL_P (arg))
6036 34275 : continue;
6037 :
6038 125715098 : tree argtype = TREE_TYPE (arg);
6039 :
6040 125715098 : tree argspec = DECL_ATTRIBUTES (arg);
6041 125715098 : if (!argspec)
6042 125218574 : continue;
6043 :
6044 496524 : if (POINTER_TYPE_P (argtype))
6045 : {
6046 : /* void* arguments in user-defined functions could point to
6047 : anything; skip them. */
6048 479456 : tree reftype = TREE_TYPE (argtype);
6049 479456 : if (skip_voidptr && VOID_TYPE_P (reftype))
6050 8 : continue;
6051 : }
6052 :
6053 : /* Each parameter should have at most one "arg spec" attribute. */
6054 496516 : argspec = lookup_attribute ("arg spec", argspec);
6055 496516 : if (!argspec)
6056 18956 : continue;
6057 :
6058 : /* Attribute arg spec should have one or two arguments. */
6059 477560 : argspec = TREE_VALUE (argspec);
6060 :
6061 : /* The attribute arg spec string. */
6062 477560 : const char *s = TREE_STRING_POINTER (TREE_VALUE (argspec));
6063 477560 : bool static_p = s && (0 == strcmp("static", s));
6064 :
6065 : /* Collect the list of nonnull arguments which use "[static ..]". */
6066 138 : if (static_p)
6067 138 : nnlist = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
6068 138 : argpos + 1), nnlist);
6069 :
6070 477560 : tree argvbs;
6071 : /* Create the attribute access string from the arg spec data,
6072 : optionally followed by position of the VLA bound argument if
6073 : it is one. */
6074 477560 : {
6075 477560 : size_t specend = spec.length ();
6076 477560 : if (!specend)
6077 : {
6078 440934 : spec = '+';
6079 440934 : specend = 1;
6080 : }
6081 :
6082 477560 : spec += attr_access::mode_chars[access_deferred];
6083 955120 : spec += std::to_string (argpos);
6084 477560 : spec += '[';
6085 477560 : tree type = TREE_VALUE (TREE_CHAIN (argspec));
6086 477560 : argvbs = build_arg_spec (type, &spec);
6087 :
6088 : /* Postprocess the string to bring it in the format expected
6089 : by the code handling the access attribute. First, we
6090 : add 's' if the array was declared as [static ...]. */
6091 477560 : if (static_p)
6092 : {
6093 138 : size_t send = spec.length();
6094 :
6095 138 : if (spec[send - 1] == '[')
6096 : {
6097 111 : spec += 's';
6098 : }
6099 : else
6100 : {
6101 : /* If there is a symbol, we need to swap the order. */
6102 27 : spec += spec[send - 1];
6103 27 : spec[send - 1] = 's';
6104 : }
6105 : }
6106 :
6107 : /* If the outermost bound is an integer constant, we need to write
6108 : the size if it is constant. */
6109 955120 : if (type && TYPE_DOMAIN (type))
6110 : {
6111 412552 : tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
6112 412552 : if (mval && TREE_CODE (mval) == INTEGER_CST)
6113 : {
6114 411186 : char buf[40];
6115 411186 : unsigned HOST_WIDE_INT n = tree_to_uhwi (mval) + 1;
6116 411186 : sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n);
6117 411186 : spec += buf;
6118 : }
6119 : }
6120 477560 : spec += ']';
6121 :
6122 : /* Trim the trailing NUL. */
6123 477560 : spec.resize (spec.length ());
6124 : }
6125 :
6126 : /* The (optional) list of expressions denoting the VLA bounds
6127 : N in ARGTYPE <arg>[Ni]...[Nj]...[Nk]. */
6128 477560 : if (argvbs)
6129 : {
6130 1483 : spec += ',';
6131 : /* Add ARGVBS to the list. Their presence is indicated by
6132 : appending a comma followed by the dollar sign and, when
6133 : it corresponds to a function parameter, the position of
6134 : each bound Ni, so it can be distinguished from
6135 : an unspecified bound (as in T[*]). The list is in reverse
6136 : order of arguments and needs to be reversed to access in
6137 : order. */
6138 1483 : vblist = tree_cons (NULL_TREE, argvbs, vblist);
6139 :
6140 15458 : for (tree vb = argvbs; vb; vb = TREE_CHAIN (vb))
6141 : {
6142 13975 : tree bound = TREE_VALUE (vb);
6143 13975 : if (const unsigned *psizpos = arg2pos.get (bound))
6144 : {
6145 : /* BOUND previously seen in the parameter list. */
6146 411 : TREE_PURPOSE (vb) = size_int (*psizpos);
6147 : /* Format the position string in place. */
6148 411 : int len = snprintf (NULL, 0, "$%u", *psizpos);
6149 411 : size_t specend = spec.length ();
6150 411 : spec.resize (specend + len + 1);
6151 411 : sprintf (&spec[specend], "$%u", *psizpos);
6152 : /* Trim the trailing NUL. */
6153 411 : spec.resize (specend + len);
6154 : }
6155 : else
6156 : {
6157 : /* BOUND doesn't name a parameter (it could be a global
6158 : variable or an expression such as a function call). */
6159 13564 : spec += '$';
6160 : }
6161 : }
6162 : }
6163 : }
6164 :
6165 51633399 : if (!spec.length ())
6166 : return NULL_TREE;
6167 :
6168 : /* If we have nonnull arguments, synthesize an attribute. */
6169 440934 : if (nnlist != NULL_TREE)
6170 130 : nnlist = build_tree_list (get_identifier ("nonnull"), nnlist);
6171 :
6172 : /* Attribute access takes a two or three arguments. Wrap VBLIST in
6173 : another list in case it has more nodes than would otherwise fit. */
6174 440934 : vblist = build_tree_list (NULL_TREE, vblist);
6175 :
6176 : /* Build a single attribute access with the string describing all
6177 : array arguments and an optional list of any non-parameter VLA
6178 : bounds in order. */
6179 440934 : tree str = build_string (spec.length (), spec.c_str ());
6180 440934 : tree attrargs = tree_cons (NULL_TREE, str, vblist);
6181 440934 : tree name = get_identifier ("access");
6182 440934 : return tree_cons (name, attrargs, nnlist);
6183 51633399 : }
6184 :
6185 : /* Handle a "nothrow" attribute; arguments as in
6186 : struct attribute_spec.handler. */
6187 :
6188 : static tree
6189 436444962 : handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6190 : int ARG_UNUSED (flags), bool *no_add_attrs)
6191 : {
6192 436444962 : if (TREE_CODE (*node) == FUNCTION_DECL)
6193 436444962 : TREE_NOTHROW (*node) = 1;
6194 : /* ??? TODO: Support types. */
6195 : else
6196 : {
6197 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6198 0 : *no_add_attrs = true;
6199 : }
6200 :
6201 436444962 : return NULL_TREE;
6202 : }
6203 :
6204 : /* Handle a "nothrow" attribute; arguments as in
6205 : struct attribute_spec.handler. */
6206 :
6207 : static tree
6208 14 : handle_expected_throw_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6209 : int ARG_UNUSED (flags), bool *no_add_attrs)
6210 : {
6211 14 : if (TREE_CODE (*node) == FUNCTION_DECL)
6212 : /* No flag to set here. */;
6213 : /* ??? TODO: Support types. */
6214 : else
6215 : {
6216 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6217 0 : *no_add_attrs = true;
6218 : }
6219 :
6220 14 : return NULL_TREE;
6221 : }
6222 :
6223 : /* Handle a "cleanup" attribute; arguments as in
6224 : struct attribute_spec.handler. */
6225 :
6226 : static tree
6227 322 : handle_cleanup_attribute (tree *node, tree name, tree args,
6228 : int ARG_UNUSED (flags), bool *no_add_attrs)
6229 : {
6230 322 : tree decl = *node;
6231 322 : tree cleanup_id, cleanup_decl;
6232 :
6233 : /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
6234 : for global destructors in C++. This requires infrastructure that
6235 : we don't have generically at the moment. It's also not a feature
6236 : we'd be missing too much, since we do have attribute constructor. */
6237 322 : if (!VAR_P (decl) || TREE_STATIC (decl))
6238 : {
6239 12 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6240 12 : *no_add_attrs = true;
6241 12 : return NULL_TREE;
6242 : }
6243 :
6244 : /* Verify that the argument is a function in scope. */
6245 : /* ??? We could support pointers to functions here as well, if
6246 : that was considered desirable. */
6247 310 : cleanup_id = TREE_VALUE (args);
6248 310 : if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
6249 : {
6250 4 : error ("cleanup argument not an identifier");
6251 4 : *no_add_attrs = true;
6252 4 : return NULL_TREE;
6253 : }
6254 306 : cleanup_decl = lookup_name (cleanup_id);
6255 306 : if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
6256 : {
6257 8 : error ("cleanup argument not a function");
6258 8 : *no_add_attrs = true;
6259 8 : return NULL_TREE;
6260 : }
6261 :
6262 : /* That the function has proper type is checked with the
6263 : eventual call to build_function_call. */
6264 :
6265 : return NULL_TREE;
6266 : }
6267 :
6268 : /* Handle a "warn_unused_result" attribute. No special handling. */
6269 :
6270 : static tree
6271 2811781 : handle_warn_unused_result_attribute (tree *node, tree name,
6272 : tree ARG_UNUSED (args),
6273 : int ARG_UNUSED (flags), bool *no_add_attrs)
6274 : {
6275 : /* Ignore the attribute for functions not returning any value. */
6276 2811781 : if (VOID_TYPE_P (TREE_TYPE (*node)))
6277 : {
6278 9 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6279 9 : *no_add_attrs = true;
6280 : }
6281 :
6282 2811781 : return NULL_TREE;
6283 : }
6284 :
6285 : /* Handle a "sentinel" attribute. */
6286 :
6287 : static tree
6288 1072028 : handle_sentinel_attribute (tree *node, tree name, tree args,
6289 : int ARG_UNUSED (flags), bool *no_add_attrs)
6290 : {
6291 1072028 : if (!prototype_p (*node))
6292 : {
6293 2 : warning (OPT_Wattributes,
6294 : "%qE attribute requires prototypes with named arguments", name);
6295 2 : *no_add_attrs = true;
6296 : }
6297 : else
6298 : {
6299 1072026 : if (!stdarg_p (*node))
6300 : {
6301 2 : warning (OPT_Wattributes,
6302 : "%qE attribute only applies to variadic functions", name);
6303 2 : *no_add_attrs = true;
6304 : }
6305 : }
6306 :
6307 1072028 : if (args)
6308 : {
6309 357331 : tree position = TREE_VALUE (args);
6310 357331 : if (position && TREE_CODE (position) != IDENTIFIER_NODE
6311 357331 : && TREE_CODE (position) != FUNCTION_DECL)
6312 357327 : position = default_conversion (position);
6313 :
6314 357331 : if (TREE_CODE (position) != INTEGER_CST
6315 357331 : || !INTEGRAL_TYPE_P (TREE_TYPE (position)))
6316 : {
6317 6 : warning (OPT_Wattributes,
6318 : "requested position is not an integer constant");
6319 6 : *no_add_attrs = true;
6320 : }
6321 : else
6322 : {
6323 357325 : if (tree_int_cst_lt (position, integer_zero_node))
6324 : {
6325 2 : warning (OPT_Wattributes,
6326 : "requested position is less than zero");
6327 2 : *no_add_attrs = true;
6328 : }
6329 : }
6330 : }
6331 :
6332 1072028 : return NULL_TREE;
6333 : }
6334 :
6335 : /* Handle a "type_generic" attribute. */
6336 :
6337 : static tree
6338 6366703 : handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
6339 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
6340 : bool * ARG_UNUSED (no_add_attrs))
6341 : {
6342 : /* Ensure we have a function type. */
6343 6366703 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
6344 :
6345 : /* Ensure we have a variadic function. */
6346 6366703 : gcc_assert (!prototype_p (*node) || stdarg_p (*node));
6347 :
6348 6366703 : return NULL_TREE;
6349 : }
6350 :
6351 : /* Handle a "target" attribute. */
6352 :
6353 : static tree
6354 23877354 : handle_target_attribute (tree *node, tree name, tree args, int flags,
6355 : bool *no_add_attrs)
6356 : {
6357 : /* Ensure we have a function declaration. */
6358 23877354 : if (TREE_CODE (*node) != FUNCTION_DECL)
6359 : {
6360 1 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6361 1 : *no_add_attrs = true;
6362 : }
6363 23877353 : else if (! targetm.target_option.valid_attribute_p (*node, name, args,
6364 : flags))
6365 123 : *no_add_attrs = true;
6366 :
6367 : /* Check that there's no empty string in values of the attribute. */
6368 48549607 : for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
6369 : {
6370 24672253 : tree value = TREE_VALUE (t);
6371 24672253 : if (TREE_CODE (value) == STRING_CST
6372 24672244 : && TREE_STRING_LENGTH (value) == 1
6373 24672262 : && TREE_STRING_POINTER (value)[0] == '\0')
6374 : {
6375 9 : warning (OPT_Wattributes, "empty string in attribute %<target%>");
6376 9 : *no_add_attrs = true;
6377 : }
6378 : }
6379 :
6380 23877354 : return NULL_TREE;
6381 : }
6382 :
6383 : /* Handle a "target_version" attribute. */
6384 :
6385 : static tree
6386 0 : handle_target_version_attribute (tree *node, tree name, tree args, int flags,
6387 : bool *no_add_attrs)
6388 : {
6389 : /* Ensure we have a function declaration. */
6390 0 : if (TREE_CODE (*node) != FUNCTION_DECL)
6391 : {
6392 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6393 0 : *no_add_attrs = true;
6394 : }
6395 0 : else if (!targetm.target_option.valid_version_attribute_p (*node, name, args,
6396 : flags))
6397 0 : *no_add_attrs = true;
6398 :
6399 0 : return NULL_TREE;
6400 : }
6401 :
6402 : /* Handle a "target_clones" attribute. */
6403 :
6404 : static tree
6405 112 : handle_target_clones_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6406 : int ARG_UNUSED (flags), bool *no_add_attrs)
6407 : {
6408 : /* Ensure we have a function declaration. */
6409 112 : if (TREE_CODE (*node) == FUNCTION_DECL)
6410 : {
6411 406 : for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
6412 : {
6413 296 : tree value = TREE_VALUE (t);
6414 296 : if (TREE_CODE (value) != STRING_CST)
6415 : {
6416 2 : error ("%qE attribute argument not a string constant", name);
6417 2 : *no_add_attrs = true;
6418 2 : return NULL_TREE;
6419 : }
6420 : }
6421 :
6422 110 : int num_defaults = 0;
6423 110 : auto_vec<string_slice> versions = get_clone_attr_versions
6424 : (args,
6425 : &num_defaults,
6426 110 : false);
6427 :
6428 637 : for (auto v : versions)
6429 307 : targetm.check_target_clone_version
6430 307 : (v, &DECL_SOURCE_LOCATION (*node));
6431 :
6432 : /* Lone target_clones version is always ignored for target attr semantics.
6433 : Only ignore under target_version semantics if it is a default
6434 : version. */
6435 110 : if (versions.length () == 1
6436 : && (TARGET_HAS_FMV_TARGET_ATTRIBUTE || num_defaults == 1))
6437 : {
6438 1 : if (TARGET_HAS_FMV_TARGET_ATTRIBUTE)
6439 1 : warning (OPT_Wattributes,
6440 : "single %<target_clones%> attribute is ignored");
6441 1 : *no_add_attrs = true;
6442 : }
6443 : else
6444 : /* Do not inline functions with multiple clone targets. */
6445 109 : DECL_UNINLINABLE (*node) = 1;
6446 110 : }
6447 : else
6448 : {
6449 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6450 0 : *no_add_attrs = true;
6451 : }
6452 : return NULL_TREE;
6453 : }
6454 :
6455 : /* For handling "optimize" attribute. arguments as in
6456 : struct attribute_spec.handler. */
6457 :
6458 : static tree
6459 343521 : handle_optimize_attribute (tree *node, tree name, tree args,
6460 : int ARG_UNUSED (flags), bool *no_add_attrs)
6461 : {
6462 : /* Ensure we have a function type. */
6463 343521 : if (TREE_CODE (*node) != FUNCTION_DECL)
6464 : {
6465 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
6466 0 : *no_add_attrs = true;
6467 : }
6468 : else
6469 : {
6470 343521 : struct cl_optimization cur_opts;
6471 343521 : tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
6472 :
6473 : /* Save current options. */
6474 343521 : cl_optimization_save (&cur_opts, &global_options, &global_options_set);
6475 343521 : tree prev_target_node = build_target_option_node (&global_options,
6476 : &global_options_set);
6477 :
6478 : /* If we previously had some optimization options, use them as the
6479 : default. */
6480 343521 : gcc_options *saved_global_options = NULL;
6481 :
6482 : /* When #pragma GCC optimize pragma is used, it modifies global_options
6483 : without calling targetm.override_options_after_change. That can leave
6484 : target flags inconsistent for comparison. */
6485 343521 : if (flag_checking && optimization_current_node == optimization_default_node)
6486 : {
6487 286643 : saved_global_options = XNEW (gcc_options);
6488 286643 : *saved_global_options = global_options;
6489 : }
6490 :
6491 343521 : if (old_opts)
6492 65796 : cl_optimization_restore (&global_options, &global_options_set,
6493 65796 : TREE_OPTIMIZATION (old_opts));
6494 :
6495 : /* Parse options, and update the vector. */
6496 343521 : parse_optimize_options (args, true);
6497 343521 : DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
6498 343521 : = build_optimization_node (&global_options, &global_options_set);
6499 343521 : tree target_node = build_target_option_node (&global_options,
6500 : &global_options_set);
6501 343521 : if (prev_target_node != target_node)
6502 0 : DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
6503 :
6504 : /* Also update the cgraph_node, if it's already built. */
6505 343521 : if (cgraph_node *cn = cgraph_node::get (*node))
6506 12 : cn->semantic_interposition = flag_semantic_interposition;
6507 :
6508 : /* Restore current options. */
6509 343521 : cl_optimization_restore (&global_options, &global_options_set,
6510 : &cur_opts);
6511 343521 : cl_target_option_restore (&global_options, &global_options_set,
6512 343521 : TREE_TARGET_OPTION (prev_target_node));
6513 :
6514 343521 : if (saved_global_options != NULL)
6515 : {
6516 286643 : if (!seen_error ())
6517 286636 : cl_optimization_compare (saved_global_options, &global_options);
6518 286643 : free (saved_global_options);
6519 : }
6520 : }
6521 :
6522 343521 : return NULL_TREE;
6523 : }
6524 :
6525 : /* Handle a "no_split_stack" attribute. */
6526 :
6527 : static tree
6528 488 : handle_no_split_stack_attribute (tree *node, tree name,
6529 : tree ARG_UNUSED (args),
6530 : int ARG_UNUSED (flags),
6531 : bool *no_add_attrs)
6532 : {
6533 488 : tree decl = *node;
6534 :
6535 488 : if (TREE_CODE (decl) != FUNCTION_DECL)
6536 : {
6537 0 : error_at (DECL_SOURCE_LOCATION (decl),
6538 : "%qE attribute applies only to functions", name);
6539 0 : *no_add_attrs = true;
6540 : }
6541 488 : else if (DECL_INITIAL (decl))
6542 : {
6543 0 : error_at (DECL_SOURCE_LOCATION (decl),
6544 : "cannot set %qE attribute after definition", name);
6545 0 : *no_add_attrs = true;
6546 : }
6547 :
6548 488 : return NULL_TREE;
6549 : }
6550 :
6551 : /* Handle a "zero_call_used_regs" attribute; arguments as in
6552 : struct attribute_spec.handler. */
6553 :
6554 : static tree
6555 100 : handle_zero_call_used_regs_attribute (tree *node, tree name, tree args,
6556 : int ARG_UNUSED (flags),
6557 : bool *no_add_attrs)
6558 : {
6559 100 : tree decl = *node;
6560 100 : tree id = TREE_VALUE (args);
6561 :
6562 100 : if (TREE_CODE (decl) != FUNCTION_DECL)
6563 : {
6564 4 : error_at (DECL_SOURCE_LOCATION (decl),
6565 : "%qE attribute applies only to functions", name);
6566 4 : *no_add_attrs = true;
6567 4 : return NULL_TREE;
6568 : }
6569 :
6570 96 : if (TREE_CODE (id) != STRING_CST)
6571 : {
6572 4 : error_at (DECL_SOURCE_LOCATION (decl),
6573 : "%qE argument not a string", name);
6574 4 : *no_add_attrs = true;
6575 4 : return NULL_TREE;
6576 : }
6577 :
6578 552 : bool found = false;
6579 552 : for (unsigned int i = 0; zero_call_used_regs_opts[i].name != NULL; ++i)
6580 548 : if (strcmp (TREE_STRING_POINTER (id),
6581 548 : zero_call_used_regs_opts[i].name) == 0)
6582 : {
6583 : found = true;
6584 : break;
6585 : }
6586 :
6587 92 : if (!found)
6588 : {
6589 4 : error_at (DECL_SOURCE_LOCATION (decl),
6590 : "unrecognized %qE attribute argument %qs",
6591 4 : name, TREE_STRING_POINTER (id));
6592 4 : *no_add_attrs = true;
6593 : }
6594 :
6595 : return NULL_TREE;
6596 : }
6597 :
6598 : /* Handle a "returns_nonnull" attribute; arguments as in
6599 : struct attribute_spec.handler. */
6600 :
6601 : static tree
6602 1195288 : handle_returns_nonnull_attribute (tree *node, tree name, tree, int,
6603 : bool *no_add_attrs)
6604 : {
6605 : // Even without a prototype we still have a return type we can check.
6606 1195288 : if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
6607 : {
6608 4 : error ("%qE attribute on a function not returning a pointer", name);
6609 4 : *no_add_attrs = true;
6610 : }
6611 1195288 : return NULL_TREE;
6612 : }
6613 :
6614 : /* Handle a "designated_init" attribute; arguments as in
6615 : struct attribute_spec.handler. */
6616 :
6617 : static tree
6618 19 : handle_designated_init_attribute (tree *node, tree name, tree, int,
6619 : bool *no_add_attrs)
6620 : {
6621 19 : if (TREE_CODE (*node) != RECORD_TYPE)
6622 : {
6623 3 : error ("%qE attribute is only valid on %<struct%> type", name);
6624 3 : *no_add_attrs = true;
6625 : }
6626 19 : return NULL_TREE;
6627 : }
6628 :
6629 :
6630 : /* Handle a "fallthrough" attribute; arguments as in struct
6631 : attribute_spec.handler. */
6632 :
6633 : tree
6634 193 : handle_fallthrough_attribute (tree *, tree name, tree, int,
6635 : bool *no_add_attrs)
6636 : {
6637 193 : pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name);
6638 193 : *no_add_attrs = true;
6639 193 : return NULL_TREE;
6640 : }
6641 :
6642 : /* Handle a "assume" attribute; arguments as in struct
6643 : attribute_spec.handler. */
6644 :
6645 : tree
6646 203 : handle_assume_attribute (tree *, tree name, tree, int,
6647 : bool *no_add_attrs)
6648 : {
6649 203 : pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored", name);
6650 203 : *no_add_attrs = true;
6651 203 : return NULL_TREE;
6652 : }
6653 :
6654 : /* Handle a "patchable_function_entry" attributes; arguments as in
6655 : struct attribute_spec.handler. */
6656 :
6657 : static tree
6658 44 : handle_patchable_function_entry_attribute (tree *, tree name, tree args,
6659 : int, bool *no_add_attrs)
6660 : {
6661 76 : for (; args; args = TREE_CHAIN (args))
6662 : {
6663 60 : tree val = TREE_VALUE (args);
6664 60 : if (val && TREE_CODE (val) != IDENTIFIER_NODE
6665 60 : && TREE_CODE (val) != FUNCTION_DECL)
6666 60 : val = default_conversion (val);
6667 :
6668 60 : if (!tree_fits_uhwi_p (val))
6669 : {
6670 16 : warning (OPT_Wattributes,
6671 : "%qE attribute argument %qE is not an integer constant",
6672 : name, val);
6673 16 : *no_add_attrs = true;
6674 16 : return NULL_TREE;
6675 : }
6676 :
6677 44 : if (tree_to_uhwi (val) > USHRT_MAX)
6678 : {
6679 12 : warning (OPT_Wattributes,
6680 : "%qE attribute argument %qE exceeds %u",
6681 : name, val, USHRT_MAX);
6682 12 : *no_add_attrs = true;
6683 12 : return NULL_TREE;
6684 : }
6685 : }
6686 : return NULL_TREE;
6687 : }
6688 :
6689 : /* Handle a "NSObject" attributes; arguments as in
6690 : struct attribute_spec.handler. */
6691 :
6692 : static tree
6693 0 : handle_nsobject_attribute (tree *node, tree name, tree args,
6694 : int /*flags*/, bool *no_add_attrs)
6695 : {
6696 0 : *no_add_attrs = true;
6697 :
6698 : /* This attribute only applies to typedefs (or field decls for properties),
6699 : we drop it otherwise - but warn about this if enabled. */
6700 0 : if (TREE_CODE (*node) != TYPE_DECL && TREE_CODE (*node) != FIELD_DECL)
6701 : {
6702 0 : warning (OPT_WNSObject_attribute, "%qE attribute may be put on a"
6703 : " typedef only; attribute is ignored", name);
6704 0 : return NULL_TREE;
6705 : }
6706 :
6707 : /* The original implementation only allowed pointers to records, however
6708 : recent implementations also allow void *. */
6709 0 : tree type = TREE_TYPE (*node);
6710 0 : if (!type || !POINTER_TYPE_P (type)
6711 0 : || (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE
6712 0 : && !VOID_TYPE_P (TREE_TYPE (type))))
6713 : {
6714 0 : error ("%qE attribute is for pointer types only", name);
6715 0 : return NULL_TREE;
6716 : }
6717 :
6718 0 : tree t = tree_cons (name, args, TYPE_ATTRIBUTES (type));
6719 0 : TREE_TYPE (*node) = build_type_attribute_variant (type, t);
6720 :
6721 0 : return NULL_TREE;
6722 : }
6723 :
6724 : /* Handle a "objc_root_class" attributes; arguments as in
6725 : struct attribute_spec.handler. */
6726 :
6727 : static tree
6728 0 : handle_objc_root_class_attribute (tree */*node*/, tree name, tree /*args*/,
6729 : int /*flags*/, bool *no_add_attrs)
6730 : {
6731 : /* This has no meaning outside Objective-C. */
6732 0 : if (!c_dialect_objc())
6733 0 : warning (OPT_Wattributes, "%qE is only applicable to Objective-C"
6734 : " class interfaces, attribute ignored", name);
6735 :
6736 0 : *no_add_attrs = true;
6737 0 : return NULL_TREE;
6738 : }
6739 :
6740 : /* Handle an "objc_nullability" attribute; arguments as in
6741 : struct attribute_spec.handler. */
6742 :
6743 : static tree
6744 0 : handle_objc_nullability_attribute (tree *node, tree name, tree args,
6745 : int /*flags*/,
6746 : bool *no_add_attrs)
6747 : {
6748 0 : *no_add_attrs = true;
6749 :
6750 0 : tree type = TREE_TYPE (*node);
6751 0 : if (TREE_CODE (*node) == FUNCTION_DECL)
6752 0 : type = TREE_TYPE (type);
6753 :
6754 0 : if (type && !POINTER_TYPE_P (type))
6755 : {
6756 0 : error ("%qE cannot be applied to non-pointer type %qT", name, type);
6757 0 : return NULL_TREE;
6758 : }
6759 :
6760 : /* We accept objc_nullability() with a single argument.
6761 : string: "unspecified", "nullable", "nonnull" or "resettable"
6762 : integer: 0 and 3 where the values have the same meaning as
6763 : the strings. */
6764 0 : tree val = TREE_VALUE (args);
6765 0 : if (TREE_CODE (val) == INTEGER_CST)
6766 : {
6767 0 : val = default_conversion (val);
6768 0 : if (!tree_fits_uhwi_p (val) || tree_to_uhwi (val) > 3)
6769 0 : error ("%qE attribute argument %qE is not an integer constant"
6770 : " between 0 and 3", name, val);
6771 : else
6772 0 : *no_add_attrs = false; /* OK */
6773 : }
6774 0 : else if (TREE_CODE (val) == STRING_CST
6775 0 : && (strcmp (TREE_STRING_POINTER (val), "nullable") == 0
6776 0 : || strcmp (TREE_STRING_POINTER (val), "nonnull") == 0
6777 0 : || strcmp (TREE_STRING_POINTER (val), "unspecified") == 0
6778 0 : || strcmp (TREE_STRING_POINTER (val), "resettable") == 0))
6779 0 : *no_add_attrs = false; /* OK */
6780 0 : else if (val != error_mark_node)
6781 0 : error ("%qE attribute argument %qE is not recognized", name, val);
6782 :
6783 : return NULL_TREE;
6784 : }
6785 :
6786 : /* Handle a "tainted_args" attribute; arguments as in
6787 : struct attribute_spec.handler. */
6788 :
6789 : static tree
6790 188 : handle_tainted_args_attribute (tree *node, tree name, tree, int,
6791 : bool *no_add_attrs)
6792 : {
6793 188 : if (TREE_CODE (*node) != FUNCTION_DECL
6794 14 : && TREE_CODE (*node) != FIELD_DECL)
6795 : {
6796 4 : warning (OPT_Wattributes, "%qE attribute ignored; valid only "
6797 : "for functions and function pointer fields",
6798 : name);
6799 4 : *no_add_attrs = true;
6800 4 : return NULL_TREE;
6801 : }
6802 :
6803 184 : if (TREE_CODE (*node) == FIELD_DECL
6804 184 : && !(TREE_CODE (TREE_TYPE (*node)) == POINTER_TYPE
6805 6 : && TREE_CODE (TREE_TYPE (TREE_TYPE (*node))) == FUNCTION_TYPE))
6806 : {
6807 4 : warning (OPT_Wattributes, "%qE attribute ignored;"
6808 : " field must be a function pointer",
6809 : name);
6810 4 : *no_add_attrs = true;
6811 4 : return NULL_TREE;
6812 : }
6813 :
6814 180 : *no_add_attrs = false; /* OK */
6815 :
6816 180 : return NULL_TREE;
6817 : }
6818 :
6819 : /* Attempt to partially validate a single attribute ATTR as if
6820 : it were to be applied to an entity OPER. */
6821 :
6822 : static bool
6823 2833 : validate_attribute (location_t atloc, tree oper, tree attr)
6824 : {
6825 : /* Determine whether the name of the attribute is valid
6826 : and fail with an error if not. */
6827 2833 : tree atname = get_attribute_name (attr);
6828 2833 : if (!lookup_attribute_spec (atname))
6829 : {
6830 8 : if (atloc != UNKNOWN_LOCATION)
6831 8 : error_at (atloc, "unknown attribute %qE", atname);
6832 8 : return false;
6833 : }
6834 :
6835 2825 : tree args = TREE_VALUE (attr);
6836 2825 : if (!args)
6837 : return true;
6838 :
6839 : /* FIXME: Do some validation. */
6840 1639 : const char *atstr = IDENTIFIER_POINTER (atname);
6841 1639 : if (!strcmp (atstr, "format"))
6842 : return true;
6843 :
6844 : /* Only when attribute arguments have been provided try to validate
6845 : the whole thing. decl_attributes doesn't return an indication of
6846 : success or failure so proceed regardless. */
6847 1631 : const char tmpname[] = "__builtin_has_attribute_tmp.";
6848 1631 : tree tmpid = get_identifier (tmpname);
6849 1631 : tree tmpdecl;
6850 1631 : if (!strcmp (atstr, "vector_size"))
6851 : {
6852 176 : tree type = TYPE_P (oper) ? oper : TREE_TYPE (oper);
6853 : /* Check for function type here since type_for_vector_size
6854 : strips it while looking for a function's return type. */
6855 176 : if (FUNC_OR_METHOD_TYPE_P (type))
6856 : {
6857 0 : warning_at (atloc, OPT_Wattributes,
6858 : "invalid operand type %qT for %qs", type, atstr);
6859 0 : return false;
6860 : }
6861 :
6862 176 : type = type_for_vector_size (type);
6863 176 : if (VECTOR_TYPE_P (type))
6864 164 : type = TREE_TYPE (type);
6865 : /* Avoid trying to apply attribute vector_size to OPER since
6866 : it's overly restrictive. Simply make sure it has the right
6867 : type. */
6868 176 : return type_valid_for_vector_size (type, atname, args, NULL);
6869 : }
6870 :
6871 1455 : if (TYPE_P (oper))
6872 308 : tmpdecl = build_decl (atloc, TYPE_DECL, tmpid, oper);
6873 1147 : else if (DECL_P (oper))
6874 564 : tmpdecl = build_decl (atloc, TREE_CODE (oper), tmpid, TREE_TYPE (oper));
6875 583 : else if (EXPR_P (oper))
6876 583 : tmpdecl = build_decl (atloc, TYPE_DECL, tmpid, TREE_TYPE (oper));
6877 : else
6878 : return false;
6879 :
6880 : /* Temporarily clear CURRENT_FUNCTION_DECL to make decl_attributes
6881 : believe the DECL declared above is at file scope. (See bug 87526.) */
6882 1455 : tree save_curfunc = current_function_decl;
6883 1455 : current_function_decl = NULL_TREE;
6884 1455 : if (DECL_P (tmpdecl))
6885 : {
6886 1455 : if (DECL_P (oper))
6887 : /* An alias cannot be a definition so declare the symbol extern. */
6888 564 : DECL_EXTERNAL (tmpdecl) = true;
6889 : /* Attribute visibility only applies to symbols visible from other
6890 : translation units so make it "public." */
6891 1455 : TREE_PUBLIC (tmpdecl) = TREE_PUBLIC (oper);
6892 : }
6893 1455 : decl_attributes (&tmpdecl, attr, 0);
6894 1455 : current_function_decl = save_curfunc;
6895 :
6896 : /* FIXME: Change decl_attributes to indicate success or failure (and
6897 : parameterize it to avoid failing with errors). */
6898 1455 : return true;
6899 : }
6900 :
6901 : /* Return true if the DECL, EXPR, or TYPE t has been declared with
6902 : attribute ATTR. For DECL, consider also its type. For EXPR,
6903 : consider just its type. */
6904 :
6905 : bool
6906 2834 : has_attribute (location_t atloc, tree t, tree attr, tree (*convert)(tree))
6907 : {
6908 2834 : if (!attr || !t || t == error_mark_node)
6909 : return false;
6910 :
6911 2833 : if (!validate_attribute (atloc, t, attr))
6912 : return false;
6913 :
6914 2773 : tree type = NULL_TREE;
6915 2773 : tree expr = NULL_TREE;
6916 2773 : if (TYPE_P (t))
6917 : type = t;
6918 : else
6919 : {
6920 2403 : do
6921 : {
6922 : /* Determine the array element/member declaration from
6923 : a COMPONENT_REF and an INDIRECT_REF involving a refeence. */
6924 2403 : STRIP_NOPS (t);
6925 2403 : tree_code code = TREE_CODE (t);
6926 2403 : if (code == INDIRECT_REF)
6927 : {
6928 439 : tree op0 = TREE_OPERAND (t, 0);
6929 439 : if (TREE_CODE (TREE_TYPE (op0)) == REFERENCE_TYPE)
6930 : t = op0;
6931 : else
6932 : break;
6933 : }
6934 1964 : else if (code == COMPONENT_REF)
6935 160 : t = TREE_OPERAND (t, 1);
6936 : else
6937 : break;
6938 : } while (true);
6939 : expr = t;
6940 : }
6941 :
6942 : /* Set to true when an attribute is found in the referenced entity
6943 : that matches the specified attribute. */
6944 2773 : bool found_match = false;
6945 :
6946 2773 : tree atname = get_attribute_name (attr);
6947 2773 : const char *namestr = IDENTIFIER_POINTER (atname);
6948 :
6949 : /* Iterate once for a type and twice for a function or variable
6950 : declaration: once for the DECL and the second time for its
6951 : TYPE. */
6952 5472 : for (bool done = false; !found_match && !done; )
6953 : {
6954 3542 : tree atlist;
6955 3542 : if (type)
6956 : {
6957 1317 : if (type == error_mark_node)
6958 : {
6959 : /* This could be a label. FIXME: add support for labels. */
6960 0 : warning_at (atloc, OPT_Wattributes,
6961 0 : (TYPE_P (t)
6962 : ? G_("%qs attribute not supported for %qT "
6963 : "in %<__builtin_has_attribute%>")
6964 : : G_("%qs attribute not supported for %qE "
6965 : "in %<__builtin_has_attribute%>")),
6966 : namestr, t);
6967 0 : return false;
6968 : }
6969 :
6970 : /* Clear EXPR to prevent considering it again below. */
6971 1317 : atlist = TYPE_ATTRIBUTES (type);
6972 1317 : expr = NULL_TREE;
6973 1317 : done = true;
6974 : }
6975 2225 : else if (DECL_P (expr))
6976 : {
6977 : /* Set TYPE to the DECL's type to process it on the next
6978 : iteration. */
6979 1306 : atlist = DECL_ATTRIBUTES (expr);
6980 1306 : type = TREE_TYPE (expr);
6981 : }
6982 : else
6983 : {
6984 919 : type = TREE_TYPE (expr);
6985 919 : atlist = TYPE_ATTRIBUTES (type);
6986 919 : done = true;
6987 : }
6988 :
6989 : /* True when an attribute with the sought name (though not necessarily
6990 : with the sought attributes) has been found on the attribute chain. */
6991 3542 : bool found_attr = false;
6992 :
6993 : /* When clear, the first mismatched attribute argument results
6994 : in failure. Otherwise, the first matched attribute argument
6995 : results in success. */
6996 3542 : bool attr_nonnull = !strcmp ("nonnull", namestr);
6997 3542 : bool ignore_mismatches = attr_nonnull;
6998 :
6999 : /* Iterate over the instances of the sought attribute on the DECL or
7000 : TYPE (there may be multiple instances with different arguments). */
7001 3895 : for (; (atlist = lookup_attribute (namestr, atlist));
7002 353 : found_attr = true, atlist = TREE_CHAIN (atlist))
7003 : {
7004 : /* If there are no arguments to match the result is true except
7005 : for nonnull where the attribute with no arguments must match. */
7006 992 : if (!TREE_VALUE (attr))
7007 449 : return attr_nonnull ? !TREE_VALUE (atlist) : true;
7008 :
7009 : /* Attribute nonnull with no arguments subsumes all values of
7010 : the attribute. FIXME: This is overly broad since it only
7011 : applies to pointer arguments, but querying non-pointer
7012 : arguments is diagnosed. */
7013 551 : if (!TREE_VALUE (atlist) && attr_nonnull)
7014 : return true;
7015 :
7016 : /* Iterate over the DECL or TYPE attribute argument's values. */
7017 871 : for (tree val = TREE_VALUE (atlist); val; val = TREE_CHAIN (val))
7018 : {
7019 : /* Iterate over the arguments in the sought attribute comparing
7020 : their values to those specified for the DECL or TYPE. */
7021 538 : for (tree arg = TREE_VALUE (attr); arg; arg = TREE_CHAIN (arg))
7022 : {
7023 518 : tree v1 = TREE_VALUE (val);
7024 518 : tree v2 = TREE_VALUE (arg);
7025 518 : if (v1 == v2)
7026 : return true;
7027 :
7028 394 : if (!v1 || !v2)
7029 : break;
7030 :
7031 394 : if (TREE_CODE (v1) == IDENTIFIER_NODE
7032 390 : || TREE_CODE (v2) == IDENTIFIER_NODE)
7033 : /* Two identifiers are the same if their values are
7034 : equal (that's handled above). Otherwise ther are
7035 : either not the same or oneis not an identifier. */
7036 : return false;
7037 :
7038 : /* Convert to make them equality-comparable. */
7039 390 : v1 = convert (v1);
7040 390 : v2 = convert (v2);
7041 :
7042 : /* A positive value indicates equality, negative means
7043 : "don't know." */
7044 390 : if (simple_cst_equal (v1, v2) == 1)
7045 : return true;
7046 :
7047 332 : if (!ignore_mismatches)
7048 : break;
7049 : }
7050 : }
7051 : }
7052 :
7053 2903 : if (!found_attr)
7054 : {
7055 : /* Some attributes are encoded directly in the tree node. */
7056 2572 : if (!strcmp ("aligned", namestr))
7057 : {
7058 1344 : if (tree arg = TREE_VALUE (attr))
7059 : {
7060 996 : arg = convert (TREE_VALUE (arg));
7061 996 : if (!tree_fits_uhwi_p (arg))
7062 : /* Invalid argument. */;
7063 624 : else if (expr && DECL_P (expr)
7064 1048 : && DECL_USER_ALIGN (expr))
7065 0 : found_match = DECL_ALIGN_UNIT (expr) == tree_to_uhwi (arg);
7066 992 : else if (type && TYPE_USER_ALIGN (type))
7067 608 : found_match = TYPE_ALIGN_UNIT (type) == tree_to_uhwi (arg);
7068 : }
7069 348 : else if (expr && DECL_P (expr))
7070 14 : found_match = DECL_USER_ALIGN (expr);
7071 334 : else if (type)
7072 334 : found_match = TYPE_USER_ALIGN (type);
7073 : }
7074 1228 : else if (!strcmp ("const", namestr))
7075 : {
7076 24 : if (expr && DECL_P (expr))
7077 12 : found_match = TREE_READONLY (expr);
7078 : }
7079 1204 : else if (!strcmp ("noreturn", namestr))
7080 : {
7081 : /* C11 _Noreturn sets the volatile bit without attaching
7082 : an attribute to the decl. */
7083 9 : if (expr
7084 1 : && DECL_P (expr)
7085 10 : && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr)))
7086 1 : found_match = TREE_THIS_VOLATILE (expr);
7087 : }
7088 1195 : else if (!strcmp ("pure", namestr))
7089 : {
7090 24 : if (expr && DECL_P (expr))
7091 12 : found_match = DECL_PURE_P (expr);
7092 : }
7093 1171 : else if (!strcmp ("deprecated", namestr))
7094 : {
7095 0 : found_match = TREE_DEPRECATED (expr ? expr : type);
7096 0 : if (found_match)
7097 : return true;
7098 : }
7099 1171 : else if (!strcmp ("vector_size", namestr))
7100 : {
7101 200 : if (!type || !VECTOR_TYPE_P (type))
7102 : return false;
7103 :
7104 120 : if (tree arg = TREE_VALUE (attr))
7105 : {
7106 : /* Compare the vector size argument for equality. */
7107 88 : arg = convert (TREE_VALUE (arg));
7108 88 : return tree_int_cst_equal (arg, TYPE_SIZE_UNIT (type)) == 1;
7109 : }
7110 : else
7111 : return true;
7112 : }
7113 971 : else if (!strcmp ("warn_if_not_aligned", namestr))
7114 : {
7115 24 : if (tree arg = TREE_VALUE (attr))
7116 : {
7117 24 : arg = convert (TREE_VALUE (arg));
7118 24 : if (expr && DECL_P (expr))
7119 0 : found_match = (DECL_WARN_IF_NOT_ALIGN (expr)
7120 0 : == tree_to_uhwi (arg) * BITS_PER_UNIT);
7121 24 : else if (type)
7122 24 : found_match = (TYPE_WARN_IF_NOT_ALIGN (type)
7123 24 : == tree_to_uhwi (arg) * BITS_PER_UNIT);
7124 : }
7125 0 : else if (expr && DECL_P (expr))
7126 0 : found_match = DECL_WARN_IF_NOT_ALIGN (expr);
7127 0 : else if (type)
7128 0 : found_match = TYPE_WARN_IF_NOT_ALIGN (type);
7129 : }
7130 947 : else if (!strcmp ("transparent_union", namestr))
7131 : {
7132 20 : if (type)
7133 20 : found_match = TYPE_TRANSPARENT_AGGR (type) != 0;
7134 : }
7135 927 : else if (!strcmp ("mode", namestr))
7136 : {
7137 : /* Finally issue a warning for attributes that cannot
7138 : be supported in this context. Attribute mode is not
7139 : added to a symbol and cannot be determined from it. */
7140 4 : warning_at (atloc, OPT_Wattributes,
7141 : "%qs attribute not supported in "
7142 : "%<__builtin_has_attribute%>", namestr);
7143 4 : break;
7144 : }
7145 : }
7146 : }
7147 : return found_match;
7148 : }
|