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