Line data Source code
1 : /* Language-independent attribute handlers shared across front ends.
2 : Copyright (C) 2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 : #include "config.h"
21 : #include "system.h"
22 : #include "coretypes.h"
23 : #include "target.h"
24 : #include "function.h"
25 : #include "tree.h"
26 : #include "stringpool.h"
27 : #include "attribs.h"
28 : #include "attr-handlers.h"
29 : #include "diagnostic-core.h"
30 : #include "options.h"
31 : #include "cgraph.h"
32 : #include "varasm.h"
33 : #include "common/common-target.h"
34 : #include "tree-pretty-print.h"
35 :
36 : /* Helper to define attribute exclusions. */
37 : #define ATTR_EXCL(name, function, type, variable) \
38 : { name, function, type, variable }
39 :
40 : /* Define attributes that are mutually exclusive with one another. */
41 : const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
42 : {
43 : ATTR_EXCL ("alloc_align", true, true, true),
44 : ATTR_EXCL ("alloc_size", true, true, true),
45 : ATTR_EXCL ("const", true, true, true),
46 : ATTR_EXCL ("malloc", true, true, true),
47 : ATTR_EXCL ("pure", true, true, true),
48 : ATTR_EXCL ("returns_twice", true, true, true),
49 : ATTR_EXCL ("warn_unused_result", true, true, true),
50 : ATTR_EXCL (NULL, false, false, false),
51 : };
52 :
53 : const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
54 : {
55 : ATTR_EXCL ("noreturn", true, true, true),
56 : ATTR_EXCL (NULL, false, false, false),
57 : };
58 :
59 : /* Exclusions that apply to attribute alloc_align, alloc_size, and malloc. */
60 : const struct attribute_spec::exclusions attr_alloc_exclusions[] =
61 : {
62 : ATTR_EXCL ("const", true, true, true),
63 : ATTR_EXCL ("noreturn", true, true, true),
64 : ATTR_EXCL ("pure", true, true, true),
65 : ATTR_EXCL (NULL, false, false, false),
66 : };
67 :
68 : const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
69 : {
70 : ATTR_EXCL ("const", true, true, true),
71 : ATTR_EXCL ("alloc_align", true, true, true),
72 : ATTR_EXCL ("alloc_size", true, true, true),
73 : ATTR_EXCL ("malloc", true, true, true),
74 : ATTR_EXCL ("noreturn", true, true, true),
75 : ATTR_EXCL ("pure", true, true, true),
76 : ATTR_EXCL (NULL, false, false, false)
77 : };
78 :
79 : const struct attribute_spec::exclusions attr_always_inline_exclusions[] =
80 : {
81 : ATTR_EXCL ("noinline", true, true, true),
82 : ATTR_EXCL ("target_clones", true, true, true),
83 : ATTR_EXCL (NULL, false, false, false),
84 : };
85 :
86 : const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
87 : {
88 : ATTR_EXCL ("cold", true, true, true),
89 : ATTR_EXCL ("hot", true, true, true),
90 : ATTR_EXCL (NULL, false, false, false)
91 : };
92 :
93 : const struct attribute_spec::exclusions attr_noinline_exclusions[] =
94 : {
95 : ATTR_EXCL ("always_inline", true, true, true),
96 : ATTR_EXCL ("gnu_inline", true, true, true),
97 : ATTR_EXCL (NULL, false, false, false),
98 : };
99 :
100 : const struct attribute_spec::exclusions attr_target_exclusions[] =
101 : {
102 : ATTR_EXCL ("target_clones", TARGET_HAS_FMV_TARGET_ATTRIBUTE,
103 : TARGET_HAS_FMV_TARGET_ATTRIBUTE, TARGET_HAS_FMV_TARGET_ATTRIBUTE),
104 : ATTR_EXCL (NULL, false, false, false),
105 : };
106 :
107 : /* Exclusions that apply to attributes that put declarations in specific
108 : sections. */
109 : const struct attribute_spec::exclusions attr_section_exclusions[] =
110 : {
111 : ATTR_EXCL ("noinit", true, true, true),
112 : ATTR_EXCL ("persistent", true, true, true),
113 : ATTR_EXCL ("section", true, true, true),
114 : ATTR_EXCL (NULL, false, false, false),
115 : };
116 :
117 : /* Return the first of DECL or TYPE attributes installed in NODE if it's
118 : a DECL, or TYPE attributes if it's a TYPE, or null otherwise. */
119 :
120 : static tree
121 2635459 : decl_or_type_attrs (tree node)
122 : {
123 2635459 : if (DECL_P (node))
124 : {
125 137695 : if (tree attrs = DECL_ATTRIBUTES (node))
126 : return attrs;
127 :
128 57347 : tree type = TREE_TYPE (node);
129 57347 : if (type == error_mark_node)
130 : return NULL_TREE;
131 57346 : return TYPE_ATTRIBUTES (type);
132 : }
133 :
134 2497764 : if (TYPE_P (node))
135 2497764 : return TYPE_ATTRIBUTES (node);
136 :
137 : return NULL_TREE;
138 : }
139 :
140 : /* Given a pair of NODEs for arbitrary DECLs or TYPEs, validate one or
141 : two integral or string attribute arguments NEWARGS to be applied to
142 : NODE[0] for the absence of conflicts with the same attribute arguments
143 : already applied to NODE[1]. Issue a warning for conflicts and return
144 : false. Otherwise, when no conflicts are found, return true. */
145 :
146 : bool
147 4996498 : validate_attr_args (tree node[2], tree name, tree newargs[2])
148 : {
149 : /* First validate the arguments against those already applied to
150 : the same declaration (or type). */
151 4996498 : tree self[2] = { node[0], node[0] };
152 4996498 : if (node[0] != node[1] && !validate_attr_args (self, name, newargs))
153 : return false;
154 :
155 4996462 : if (!node[1])
156 : return true;
157 :
158 : /* Extract the same attribute from the previous declaration or type. */
159 2635459 : tree prevattr = decl_or_type_attrs (node[1]);
160 2635459 : const char* const namestr = IDENTIFIER_POINTER (name);
161 2635459 : prevattr = lookup_attribute (namestr, prevattr);
162 2635459 : if (!prevattr)
163 : return true;
164 :
165 : /* Extract one or both attribute arguments. */
166 28618 : tree prevargs[2];
167 28618 : prevargs[0] = TREE_VALUE (TREE_VALUE (prevattr));
168 28618 : prevargs[1] = TREE_CHAIN (TREE_VALUE (prevattr));
169 28618 : if (prevargs[1])
170 33 : prevargs[1] = TREE_VALUE (prevargs[1]);
171 :
172 : /* Both arguments must be equal or, for the second pair, neither must
173 : be provided to succeed. */
174 28618 : bool arg1eq, arg2eq;
175 28618 : if (TREE_CODE (newargs[0]) == INTEGER_CST)
176 : {
177 28609 : arg1eq = tree_int_cst_equal (newargs[0], prevargs[0]);
178 28609 : if (newargs[1] && prevargs[1])
179 16 : arg2eq = tree_int_cst_equal (newargs[1], prevargs[1]);
180 : else
181 28593 : arg2eq = newargs[1] == prevargs[1];
182 : }
183 9 : else if (TREE_CODE (newargs[0]) == STRING_CST)
184 : {
185 9 : const char *s0 = TREE_STRING_POINTER (newargs[0]);
186 9 : const char *s1 = TREE_STRING_POINTER (prevargs[0]);
187 9 : arg1eq = strcmp (s0, s1) == 0;
188 9 : if (newargs[1] && prevargs[1])
189 : {
190 0 : s0 = TREE_STRING_POINTER (newargs[1]);
191 0 : s1 = TREE_STRING_POINTER (prevargs[1]);
192 0 : arg2eq = strcmp (s0, s1) == 0;
193 : }
194 : else
195 9 : arg2eq = newargs[1] == prevargs[1];
196 : }
197 : else
198 0 : gcc_unreachable ();
199 :
200 28618 : if (arg1eq && arg2eq)
201 : return true;
202 :
203 : /* If the two locations are different print a note pointing to
204 : the previous one. */
205 48 : const location_t curloc = input_location;
206 48 : const location_t prevloc
207 48 : = DECL_P (node[1]) ? DECL_SOURCE_LOCATION (node[1]) : curloc;
208 :
209 : /* Format the attribute specification for convenience. */
210 48 : char newspec[80], prevspec[80];
211 48 : if (newargs[1])
212 2 : snprintf (newspec, sizeof newspec, "%s (%s, %s)", namestr,
213 : print_generic_expr_to_str (newargs[0]),
214 : print_generic_expr_to_str (newargs[1]));
215 : else
216 46 : snprintf (newspec, sizeof newspec, "%s (%s)", namestr,
217 : print_generic_expr_to_str (newargs[0]));
218 :
219 48 : if (prevargs[1])
220 17 : snprintf (prevspec, sizeof prevspec, "%s (%s, %s)", namestr,
221 : print_generic_expr_to_str (prevargs[0]),
222 : print_generic_expr_to_str (prevargs[1]));
223 : else
224 31 : snprintf (prevspec, sizeof prevspec, "%s (%s)", namestr,
225 : print_generic_expr_to_str (prevargs[0]));
226 :
227 84 : if (warning_at (curloc, OPT_Wattributes,
228 : "ignoring attribute %qs because it conflicts "
229 : "with previous %qs",
230 : newspec, prevspec)
231 48 : && curloc != prevloc)
232 12 : inform (prevloc, "previous declaration here");
233 :
234 : return false;
235 : }
236 :
237 : /* Convenience wrapper for validate_attr_args to validate a single
238 : attribute argument. Used by handlers for attributes that take
239 : just a single argument. */
240 :
241 : bool
242 104939 : validate_attr_arg (tree node[2], tree name, tree newarg)
243 : {
244 104939 : tree argarray[2] = { newarg, NULL_TREE };
245 104939 : return validate_attr_args (node, name, argarray);
246 : }
247 :
248 : /* Handle an "alias" or "ifunc" attribute; arguments as in
249 : struct attribute_spec.handler, except that IS_ALIAS tells us
250 : whether this is an alias as opposed to ifunc attribute. */
251 :
252 : tree
253 5711 : handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
254 : bool *no_add_attrs)
255 : {
256 5711 : tree decl = *node;
257 :
258 5711 : if (TREE_CODE (decl) != FUNCTION_DECL
259 202 : && (!is_alias || !VAR_P (decl)))
260 : {
261 1 : warning (OPT_Wattributes, "%qE attribute ignored", name);
262 1 : *no_add_attrs = true;
263 : }
264 5509 : else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
265 5710 : || (TREE_CODE (decl) != FUNCTION_DECL
266 201 : && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
267 : /* A static variable declaration is always a tentative definition,
268 : but the alias is a non-tentative definition which overrides. */
269 11420 : || (TREE_CODE (decl) != FUNCTION_DECL
270 201 : && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
271 : {
272 0 : error ("%q+D defined both normally and as %qE attribute", decl, name);
273 0 : *no_add_attrs = true;
274 0 : return NULL_TREE;
275 : }
276 5710 : else if (!is_alias
277 5710 : && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
278 117 : || lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))))
279 : {
280 1 : error ("weak %q+D cannot be defined %qE", decl, name);
281 1 : *no_add_attrs = true;
282 1 : return NULL_TREE;
283 : }
284 :
285 : /* Note that the very first time we process a nested declaration,
286 : decl_function_context will not be set. Indeed, *would* never
287 : be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
288 : we do below. After such frobbery, pushdecl would set the context.
289 : In any case, this is never what we want. */
290 5709 : else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
291 : {
292 5702 : tree id;
293 :
294 5702 : id = TREE_VALUE (args);
295 5702 : if (TREE_CODE (id) != STRING_CST)
296 : {
297 0 : error ("attribute %qE argument not a string", name);
298 0 : *no_add_attrs = true;
299 0 : return NULL_TREE;
300 : }
301 5702 : id = get_identifier (TREE_STRING_POINTER (id));
302 : /* This counts as a use of the object pointed to. */
303 5702 : TREE_USED (id) = 1;
304 :
305 5702 : if (TREE_CODE (decl) == FUNCTION_DECL)
306 5501 : DECL_INITIAL (decl) = error_mark_node;
307 : else
308 201 : TREE_STATIC (decl) = 1;
309 :
310 5702 : if (!is_alias)
311 : {
312 : /* ifuncs are also aliases, so set that attribute too. */
313 117 : DECL_ATTRIBUTES (decl)
314 117 : = tree_cons (get_identifier ("alias"), args,
315 117 : DECL_ATTRIBUTES (decl));
316 117 : DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("ifunc"),
317 117 : NULL, DECL_ATTRIBUTES (decl));
318 : }
319 : }
320 : else
321 : {
322 7 : warning (OPT_Wattributes, "%qE attribute ignored", name);
323 7 : *no_add_attrs = true;
324 : }
325 :
326 5710 : if (decl_in_symtab_p (*node))
327 : {
328 5709 : struct symtab_node *n = symtab_node::get (decl);
329 5709 : if (n && n->refuse_visibility_changes)
330 0 : error ("%+qD declared %qs after being used",
331 : decl, is_alias ? "alias" : "ifunc");
332 : }
333 :
334 : return NULL_TREE;
335 : }
336 :
337 : /* Ignore the given attribute. Used when this attribute may be usefully
338 : overridden by the target, but is not used generically. */
339 :
340 : tree
341 0 : ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
342 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
343 : bool *no_add_attrs)
344 : {
345 0 : *no_add_attrs = true;
346 0 : return NULL_TREE;
347 : }
348 :
349 : /* Handle a "leaf" attribute; arguments as in
350 : struct attribute_spec.handler. */
351 :
352 : tree
353 438739378 : handle_leaf_attribute (tree *node, tree name,
354 : tree ARG_UNUSED (args),
355 : int ARG_UNUSED (flags), bool *no_add_attrs)
356 : {
357 438739378 : if (TREE_CODE (*node) != FUNCTION_DECL)
358 : {
359 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
360 0 : *no_add_attrs = true;
361 : }
362 438739378 : if (!TREE_PUBLIC (*node))
363 : {
364 7 : warning (OPT_Wattributes, "%qE attribute has no effect on unit local "
365 : "functions", name);
366 7 : *no_add_attrs = true;
367 : }
368 :
369 438739378 : return NULL_TREE;
370 : }
371 :
372 : /* Handle a "const" attribute; arguments as in
373 : struct attribute_spec.handler. */
374 :
375 : tree
376 187775157 : handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
377 : int flags, bool *no_add_attrs)
378 : {
379 187775157 : tree type = TREE_TYPE (*node);
380 :
381 : /* See FIXME comment on noreturn in c_common_attribute_table. */
382 187775157 : if (TREE_CODE (*node) == FUNCTION_DECL)
383 187775121 : TREE_READONLY (*node) = 1;
384 36 : else if (TREE_CODE (type) == POINTER_TYPE
385 36 : && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
386 31 : TREE_TYPE (*node)
387 31 : = (build_qualified_type
388 31 : (build_pointer_type
389 62 : (build_type_variant (TREE_TYPE (type), 1,
390 : TREE_THIS_VOLATILE (TREE_TYPE (type)))),
391 31 : TYPE_QUALS (type)));
392 : else
393 : {
394 5 : warning (OPT_Wattributes, "%qE attribute ignored", name);
395 5 : *no_add_attrs = true;
396 : }
397 :
398 : /* void __builtin_unreachable (void) is const. Accept other such
399 : built-ins but warn on user-defined functions that return void. */
400 187775157 : if (!(flags & ATTR_FLAG_BUILT_IN)
401 3221299 : && TREE_CODE (*node) == FUNCTION_DECL
402 190996420 : && VOID_TYPE_P (TREE_TYPE (type)))
403 14 : warning (OPT_Wattributes, "%qE attribute on function "
404 : "returning %<void%>", name);
405 :
406 187775157 : return NULL_TREE;
407 : }
408 :
409 : /* Handle a "pure" attribute; arguments as in
410 : struct attribute_spec.handler. */
411 :
412 : tree
413 20484103 : handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
414 : int ARG_UNUSED (flags), bool *no_add_attrs)
415 : {
416 20484103 : if (TREE_CODE (*node) == FUNCTION_DECL)
417 : {
418 20484103 : tree type = TREE_TYPE (*node);
419 20484103 : if (VOID_TYPE_P (TREE_TYPE (type)))
420 3 : warning (OPT_Wattributes, "%qE attribute on function "
421 : "returning %<void%>", name);
422 :
423 20484103 : DECL_PURE_P (*node) = 1;
424 : /* ??? TODO: Support types. */
425 : }
426 : else
427 : {
428 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
429 0 : *no_add_attrs = true;
430 : }
431 :
432 20484103 : return NULL_TREE;
433 : }
434 :
435 : /* Handle a "no vops" attribute; arguments as in
436 : struct attribute_spec.handler. */
437 :
438 : tree
439 1710783 : handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
440 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
441 : bool *ARG_UNUSED (no_add_attrs))
442 : {
443 1710783 : gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
444 1710783 : DECL_IS_NOVOPS (*node) = 1;
445 1710783 : return NULL_TREE;
446 : }
447 :
448 : /* Handle a "nothrow" attribute; arguments as in
449 : struct attribute_spec.handler. */
450 :
451 : tree
452 450752458 : handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
453 : int ARG_UNUSED (flags), bool *no_add_attrs)
454 : {
455 450752458 : if (TREE_CODE (*node) == FUNCTION_DECL)
456 450752458 : TREE_NOTHROW (*node) = 1;
457 : /* ??? TODO: Support types. */
458 : else
459 : {
460 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
461 0 : *no_add_attrs = true;
462 : }
463 :
464 450752458 : return NULL_TREE;
465 : }
466 :
467 : /* Handle a "type_generic" attribute. */
468 :
469 : tree
470 6705677 : handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
471 : tree ARG_UNUSED (args), int ARG_UNUSED (flags),
472 : bool * ARG_UNUSED (no_add_attrs))
473 : {
474 : /* Ensure we have a function type. */
475 6705677 : gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
476 :
477 : /* Ensure we have a variadic function. */
478 6705677 : gcc_assert (!prototype_p (*node) || stdarg_p (*node));
479 :
480 6705677 : return NULL_TREE;
481 : }
482 :
483 : /* Handle a "returns_twice" attribute. */
484 :
485 : tree
486 228290 : handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
487 : int ARG_UNUSED (flags), bool *no_add_attrs)
488 : {
489 228290 : if (TREE_CODE (*node) == FUNCTION_DECL)
490 228290 : DECL_IS_RETURNS_TWICE (*node) = 1;
491 : else
492 : {
493 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
494 0 : *no_add_attrs = true;
495 : }
496 :
497 228290 : return NULL_TREE;
498 : }
499 :
500 : /* Handle a "fn spec" attribute; arguments as in
501 : struct attribute_spec.handler. */
502 :
503 : tree
504 135493648 : handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
505 : tree args, int ARG_UNUSED (flags),
506 : bool *no_add_attrs ATTRIBUTE_UNUSED)
507 : {
508 270987296 : gcc_assert (args
509 : && TREE_CODE (TREE_VALUE (args)) == STRING_CST
510 : && !TREE_CHAIN (args));
511 135493648 : return NULL_TREE;
512 : }
513 :
514 : /* Handle an "visibility" attribute; arguments as in
515 : struct attribute_spec.handler. */
516 :
517 : tree
518 695910 : handle_visibility_attribute (tree *node, tree name, tree args,
519 : int ARG_UNUSED (flags),
520 : bool *ARG_UNUSED (no_add_attrs))
521 : {
522 695910 : tree decl = *node;
523 695910 : tree id = TREE_VALUE (args);
524 695910 : enum symbol_visibility vis;
525 :
526 695910 : if (TYPE_P (*node))
527 : {
528 130 : if (TREE_CODE (*node) == ENUMERAL_TYPE)
529 : /* OK. */;
530 127 : else if (!RECORD_OR_UNION_TYPE_P (*node))
531 : {
532 2 : warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
533 : name);
534 2 : return NULL_TREE;
535 : }
536 125 : else if (TYPE_FIELDS (*node))
537 : {
538 0 : error ("%qE attribute ignored because %qT is already defined",
539 : name, *node);
540 0 : return NULL_TREE;
541 : }
542 : }
543 695780 : else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
544 : {
545 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
546 0 : return NULL_TREE;
547 : }
548 :
549 695908 : if (TREE_CODE (id) != STRING_CST)
550 : {
551 0 : error ("visibility argument not a string");
552 0 : return NULL_TREE;
553 : }
554 :
555 : /* If this is a type, set the visibility on the type decl. */
556 695908 : if (TYPE_P (decl))
557 : {
558 128 : decl = TYPE_NAME (decl);
559 128 : if (!decl)
560 : return NULL_TREE;
561 128 : if (TREE_CODE (decl) == IDENTIFIER_NODE)
562 : {
563 1 : warning (OPT_Wattributes, "%qE attribute ignored on types",
564 : name);
565 1 : return NULL_TREE;
566 : }
567 : }
568 :
569 695907 : if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
570 : vis = VISIBILITY_DEFAULT;
571 638181 : else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
572 : vis = VISIBILITY_INTERNAL;
573 638121 : else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
574 : vis = VISIBILITY_HIDDEN;
575 66 : else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
576 : vis = VISIBILITY_PROTECTED;
577 : else
578 : {
579 0 : error ("attribute %qE argument must be one of %qs, %qs, %qs, or %qs",
580 : name, "default", "hidden", "protected", "internal");
581 0 : vis = VISIBILITY_DEFAULT;
582 : }
583 :
584 695907 : if (DECL_VISIBILITY_SPECIFIED (decl)
585 695907 : && vis != DECL_VISIBILITY (decl))
586 : {
587 21 : tree attributes = (TYPE_P (*node)
588 21 : ? TYPE_ATTRIBUTES (*node)
589 21 : : DECL_ATTRIBUTES (decl));
590 21 : if (lookup_attribute ("visibility", attributes))
591 3 : error ("%qD redeclared with different visibility", decl);
592 : else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
593 : && lookup_attribute ("dllimport", attributes))
594 : error ("%qD was declared %qs which implies default visibility",
595 : decl, "dllimport");
596 : else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
597 : && lookup_attribute ("dllexport", attributes))
598 : error ("%qD was declared %qs which implies default visibility",
599 : decl, "dllexport");
600 : }
601 :
602 695907 : DECL_VISIBILITY (decl) = vis;
603 695907 : DECL_VISIBILITY_SPECIFIED (decl) = 1;
604 :
605 : /* Go ahead and attach the attribute to the node as well. This is needed
606 : so we can determine whether we have VISIBILITY_DEFAULT because the
607 : visibility was not specified, or because it was explicitly overridden
608 : from the containing scope. */
609 :
610 695907 : return NULL_TREE;
611 : }
612 :
613 : /* Handle a "always_inline" attribute; arguments as in
614 : struct attribute_spec.handler. */
615 :
616 : tree
617 43189130 : handle_always_inline_attribute (tree *node, tree name,
618 : tree ARG_UNUSED (args),
619 : int ARG_UNUSED (flags),
620 : bool *no_add_attrs)
621 : {
622 43189130 : if (TREE_CODE (*node) == FUNCTION_DECL)
623 : {
624 : /* Set the attribute and mark it for disregarding inline
625 : limits. */
626 43189130 : DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
627 : }
628 : else
629 : {
630 0 : warning (OPT_Wattributes, "%qE attribute ignored", name);
631 0 : *no_add_attrs = true;
632 : }
633 :
634 43189130 : return NULL_TREE;
635 : }
636 :
637 : /* Handle a "noinline" attribute; arguments as in
638 : struct attribute_spec.handler. */
639 :
640 : tree
641 909793 : handle_noinline_attribute (tree *node, tree name,
642 : tree ARG_UNUSED (args),
643 : int ARG_UNUSED (flags), bool *no_add_attrs)
644 : {
645 909793 : if (TREE_CODE (*node) == FUNCTION_DECL)
646 909785 : DECL_UNINLINABLE (*node) = 1;
647 : else
648 : {
649 8 : warning (OPT_Wattributes, "%qE attribute ignored", name);
650 8 : *no_add_attrs = true;
651 : }
652 :
653 909793 : return NULL_TREE;
654 : }
655 :
656 : /* Handle a "weak" attribute; arguments as in
657 : struct attribute_spec.handler. */
658 :
659 : tree
660 9087 : handle_weak_attribute (tree *node, tree name,
661 : tree ARG_UNUSED (args),
662 : int ARG_UNUSED (flags),
663 : bool * ARG_UNUSED (no_add_attrs))
664 : {
665 9087 : if (TREE_CODE (*node) == FUNCTION_DECL
666 9087 : && DECL_DECLARED_INLINE_P (*node))
667 : {
668 1 : warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
669 1 : *no_add_attrs = true;
670 : }
671 9086 : else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
672 : {
673 1 : error ("indirect function %q+D cannot be declared weak", *node);
674 1 : *no_add_attrs = true;
675 1 : return NULL_TREE;
676 : }
677 9085 : else if (VAR_OR_FUNCTION_DECL_P (*node))
678 9080 : declare_weak (*node);
679 : else
680 5 : warning (OPT_Wattributes, "%qE attribute ignored", name);
681 :
682 : return NULL_TREE;
683 : }
684 :
685 : /* Handle a "target" attribute. */
686 :
687 : tree
688 24940633 : handle_target_attribute (tree *node, tree name, tree args, int flags,
689 : bool *no_add_attrs)
690 : {
691 : /* Ensure we have a function declaration. */
692 24940633 : if (TREE_CODE (*node) != FUNCTION_DECL)
693 : {
694 1 : warning (OPT_Wattributes, "%qE attribute ignored", name);
695 1 : *no_add_attrs = true;
696 : }
697 24940632 : else if (! targetm.target_option.valid_attribute_p (*node, name, args,
698 : flags))
699 123 : *no_add_attrs = true;
700 :
701 : /* Check that there's no empty string in values of the attribute. */
702 50681602 : for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
703 : {
704 25740969 : tree value = TREE_VALUE (t);
705 25740969 : if (TREE_CODE (value) == STRING_CST
706 25740960 : && TREE_STRING_LENGTH (value) == 1
707 25740978 : && TREE_STRING_POINTER (value)[0] == '\0')
708 : {
709 9 : warning (OPT_Wattributes, "empty string in attribute %<target%>");
710 9 : *no_add_attrs = true;
711 : }
712 : }
713 :
714 24940633 : return NULL_TREE;
715 : }
716 :
717 : /* Handle a "used" attribute; arguments as in
718 : struct attribute_spec.handler. */
719 :
720 : tree
721 1810 : handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
722 : int ARG_UNUSED (flags), bool *no_add_attrs)
723 : {
724 1810 : tree node = *pnode;
725 :
726 1810 : if (TREE_CODE (node) == FUNCTION_DECL
727 960 : || (VAR_P (node) && TREE_STATIC (node))
728 34 : || (TREE_CODE (node) == TYPE_DECL))
729 : {
730 1791 : TREE_USED (node) = 1;
731 1791 : DECL_PRESERVE_P (node) = 1;
732 1791 : if (VAR_P (node))
733 926 : DECL_READ_P (node) = 1;
734 : }
735 : else
736 : {
737 19 : warning (OPT_Wattributes, "%qE attribute ignored", name);
738 19 : *no_add_attrs = true;
739 : }
740 :
741 1810 : return NULL_TREE;
742 : }
743 :
744 : /* Handle an "alias" or "ifunc" attribute; arguments as in
745 : struct attribute_spec.handler. */
746 :
747 : tree
748 5593 : handle_alias_attribute (tree *node, tree name, tree args,
749 : int ARG_UNUSED (flags), bool *no_add_attrs)
750 : {
751 5593 : return handle_alias_ifunc_attribute (true, node, name, args, no_add_attrs);
752 : }
753 :
754 : /* Handle a "section" attribute; arguments as in
755 : struct attribute_spec.handler. */
756 :
757 : tree
758 487 : handle_section_attribute (tree *node, tree name, tree args,
759 : int flags, bool *no_add_attrs)
760 : {
761 487 : tree decl = *node;
762 487 : tree res = NULL_TREE;
763 487 : tree argval = TREE_VALUE (args);
764 487 : const char* new_section_name;
765 :
766 487 : if (!targetm_common.have_named_sections)
767 : {
768 0 : error_at (DECL_SOURCE_LOCATION (*node),
769 : "section attributes are not supported for this target");
770 0 : goto fail;
771 : }
772 :
773 487 : if (!VAR_OR_FUNCTION_DECL_P (decl))
774 : {
775 0 : error ("section attribute not allowed for %q+D", *node);
776 0 : goto fail;
777 : }
778 :
779 487 : if (TREE_CODE (argval) != STRING_CST)
780 : {
781 0 : error ("section attribute argument not a string constant");
782 0 : goto fail;
783 : }
784 :
785 487 : if (VAR_P (decl)
786 374 : && current_function_decl != NULL_TREE
787 32 : && !TREE_STATIC (decl))
788 : {
789 0 : error_at (DECL_SOURCE_LOCATION (decl),
790 : "section attribute cannot be specified for local variables");
791 0 : goto fail;
792 : }
793 :
794 487 : new_section_name = TREE_STRING_POINTER (argval);
795 :
796 : /* The decl may have already been given a section attribute
797 : from a previous declaration. Ensure they match. */
798 487 : if (const char* const old_section_name = DECL_SECTION_NAME (decl))
799 2 : if (strcmp (old_section_name, new_section_name) != 0)
800 : {
801 2 : error ("section of %q+D conflicts with previous declaration",
802 : *node);
803 2 : goto fail;
804 : }
805 :
806 485 : if (VAR_P (decl)
807 374 : && !targetm.have_tls && targetm.emutls.tmpl_section
808 485 : && DECL_THREAD_LOCAL_P (decl))
809 : {
810 0 : error ("section of %q+D cannot be overridden", *node);
811 0 : goto fail;
812 : }
813 :
814 485 : if (!validate_attr_arg (node, name, argval))
815 1 : goto fail;
816 :
817 484 : res = targetm.handle_generic_attribute (node, name, args, flags,
818 : no_add_attrs);
819 :
820 : /* If the back end confirms the attribute can be added then continue onto
821 : final processing. */
822 484 : if (!(*no_add_attrs))
823 : {
824 484 : set_decl_section_name (decl, new_section_name);
825 484 : return res;
826 : }
827 :
828 0 : fail:
829 3 : *no_add_attrs = true;
830 3 : return res;
831 : }
832 :
833 : /* Handle a "retain" attribute; arguments as in
834 : struct attribute_spec.handler. */
835 :
836 : tree
837 262 : handle_retain_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
838 : int ARG_UNUSED (flags), bool *no_add_attrs)
839 : {
840 262 : tree node = *pnode;
841 :
842 262 : if (SUPPORTS_SHF_GNU_RETAIN
843 262 : && (TREE_CODE (node) == FUNCTION_DECL
844 186 : || (VAR_P (node) && TREE_STATIC (node))))
845 : ;
846 : else
847 : {
848 4 : warning (OPT_Wattributes, "%qE attribute ignored", name);
849 4 : *no_add_attrs = true;
850 : }
851 :
852 262 : return NULL_TREE;
853 : }
854 :
855 : /* Part of the `malloc` attribute handling which is shared by libgccjit and
856 : the C-family front-end. */
857 :
858 : tree
859 3010410 : handle_malloc_common (tree *node, tree name, tree ARG_UNUSED (args),
860 : int ARG_UNUSED (flags), bool *no_add_attrs)
861 : {
862 3010410 : if (TREE_CODE (*node) != FUNCTION_DECL)
863 : {
864 0 : warning (OPT_Wattributes, "%qE attribute ignored; valid only "
865 : "for functions", name);
866 0 : *no_add_attrs = true;
867 0 : return NULL_TREE;
868 : }
869 :
870 3010410 : tree rettype = TREE_TYPE (TREE_TYPE (*node));
871 3010410 : if (!POINTER_TYPE_P (rettype))
872 : {
873 4 : warning (OPT_Wattributes, "%qE attribute ignored on functions "
874 : "returning %qT; valid only for pointer return types",
875 : name, rettype);
876 4 : *no_add_attrs = true;
877 4 : return NULL_TREE;
878 : }
879 :
880 3010406 : DECL_IS_MALLOC (*node) = 1;
881 3010406 : return NULL_TREE;
882 : }
|