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