rtl: ICE with thread_local and inline asm [PR104777]
[official-gcc.git] / gcc / d / d-attribs.cc
blobc271de0c77e8fbd4fc3cb3f8ee3992a6cd6fb1a5
1 /* d-attribs.c -- D attributes handling.
2 Copyright (C) 2015-2022 Free Software Foundation, Inc.
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
18 /* Implementation of attribute handlers for user defined attributes and
19 internal built-in functions. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
25 #include "dmd/attrib.h"
26 #include "dmd/declaration.h"
27 #include "dmd/expression.h"
28 #include "dmd/module.h"
29 #include "dmd/mtype.h"
30 #include "dmd/template.h"
32 #include "tree.h"
33 #include "diagnostic.h"
34 #include "tm.h"
35 #include "cgraph.h"
36 #include "toplev.h"
37 #include "target.h"
38 #include "common/common-target.h"
39 #include "stringpool.h"
40 #include "attribs.h"
41 #include "varasm.h"
42 #include "fold-const.h"
43 #include "opts.h"
45 #include "d-tree.h"
48 /* Internal attribute handlers for built-in functions. */
49 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
50 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
51 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
52 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
53 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
54 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
55 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
56 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
57 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
58 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
59 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
60 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
62 /* D attribute handlers for user defined attributes. */
63 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
64 static tree d_handle_always_inline_attribute (tree *, tree, tree, int, bool *);
65 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
66 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
67 static tree d_handle_target_clones_attribute (tree *, tree, tree, int, bool *);
68 static tree d_handle_optimize_attribute (tree *, tree, tree, int, bool *);
69 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
70 static tree d_handle_noicf_attribute (tree *, tree, tree, int, bool *);
71 static tree d_handle_noipa_attribute (tree *, tree, tree, int, bool *);
72 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
73 static tree d_handle_symver_attribute (tree *, tree, tree, int, bool *);
74 static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ;
75 static tree d_handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
76 static tree d_handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
77 static tree d_handle_cold_attribute (tree *, tree, tree, int, bool *);
78 static tree d_handle_restrict_attribute (tree *, tree, tree, int, bool *);
79 static tree d_handle_used_attribute (tree *, tree, tree, int, bool *);
81 /* Helper to define attribute exclusions. */
82 #define ATTR_EXCL(name, function, type, variable) \
83 { name, function, type, variable }
85 /* Define attributes that are mutually exclusive with one another. */
86 static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
88 ATTR_EXCL ("alloc_size", true, true, true),
89 ATTR_EXCL ("const", true, true, true),
90 ATTR_EXCL ("malloc", true, true, true),
91 ATTR_EXCL ("pure", true, true, true),
92 ATTR_EXCL ("returns_twice", true, true, true),
93 ATTR_EXCL (NULL, false, false, false),
96 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
98 ATTR_EXCL ("noreturn", true, true, true),
99 ATTR_EXCL (NULL, false, false, false),
102 static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
104 ATTR_EXCL ("alloc_size", true, true, true),
105 ATTR_EXCL ("const", true, true, true),
106 ATTR_EXCL ("noreturn", true, true, true),
107 ATTR_EXCL ("pure", true, true, true),
108 ATTR_EXCL (NULL, false, false, false)
111 static const struct attribute_spec::exclusions attr_inline_exclusions[] =
113 ATTR_EXCL ("noinline", true, true, true),
114 ATTR_EXCL ("target_clones", true, true, true),
115 ATTR_EXCL (NULL, false, false, false),
118 static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
120 ATTR_EXCL ("always_inline", true, true, true),
121 ATTR_EXCL (NULL, false, false, false),
124 static const struct attribute_spec::exclusions attr_target_exclusions[] =
126 ATTR_EXCL ("target_clones", true, true, true),
127 ATTR_EXCL (NULL, false, false, false),
130 static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
132 ATTR_EXCL ("always_inline", true, true, true),
133 ATTR_EXCL ("target", true, true, true),
134 ATTR_EXCL (NULL, false, false, false),
137 static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
139 ATTR_EXCL ("const", true, true, true),
140 ATTR_EXCL ("noreturn", true, true, true),
141 ATTR_EXCL ("pure", true, true, true),
142 ATTR_EXCL (NULL, false, false, false),
145 extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
147 ATTR_EXCL ("cold", true, true, true),
148 ATTR_EXCL ("hot", true, true, true),
149 ATTR_EXCL (NULL, false, false, false)
152 /* Helper to define an attribute. */
153 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
154 affects_type_identity, handler, exclude) \
155 { name, min_len, max_len, decl_req, type_req, fn_type_req, \
156 affects_type_identity, handler, exclude }
158 /* Table of machine-independent attributes.
159 For internal use (marking of built-ins) only. */
160 const attribute_spec d_langhook_common_attribute_table[] =
162 ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
163 handle_noreturn_attribute, attr_noreturn_exclusions),
164 ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
165 handle_leaf_attribute, NULL),
166 ATTR_SPEC ("const", 0, 0, true, false, false, false,
167 handle_const_attribute, attr_const_pure_exclusions),
168 ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
169 handle_malloc_attribute, NULL),
170 ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
171 handle_returns_twice_attribute, attr_returns_twice_exclusions),
172 ATTR_SPEC ("pure", 0, 0, true, false, false, false,
173 handle_pure_attribute, attr_const_pure_exclusions),
174 ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
175 handle_nonnull_attribute, NULL),
176 ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
177 handle_nothrow_attribute, NULL),
178 ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
179 handle_transaction_pure_attribute, NULL),
180 ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
181 handle_novops_attribute, NULL),
182 ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
183 handle_type_generic_attribute, NULL),
184 ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
185 handle_fnspec_attribute, NULL),
186 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
189 /* Table of D language attributes exposed by `gcc.attribute' UDAs. */
190 const attribute_spec d_langhook_attribute_table[] =
192 ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
193 d_handle_noinline_attribute, attr_noinline_exclusions),
194 ATTR_SPEC ("always_inline", 0, 0, true, false, false, false,
195 d_handle_always_inline_attribute, attr_inline_exclusions),
196 ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
197 d_handle_flatten_attribute, NULL),
198 ATTR_SPEC ("target", 1, -1, true, false, false, false,
199 d_handle_target_attribute, attr_target_exclusions),
200 ATTR_SPEC ("target_clones", 1, -1, true, false, false, false,
201 d_handle_target_clones_attribute, attr_target_clones_exclusions),
202 ATTR_SPEC ("optimize", 1, -1, true, false, false, false,
203 d_handle_optimize_attribute, NULL),
204 ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
205 d_handle_noclone_attribute, NULL),
206 ATTR_SPEC ("no_icf", 0, 0, true, false, false, false,
207 d_handle_noicf_attribute, NULL),
208 ATTR_SPEC ("noipa", 0, 0, true, false, false, false,
209 d_handle_noipa_attribute, NULL),
210 ATTR_SPEC ("section", 1, 1, true, false, false, false,
211 d_handle_section_attribute, NULL),
212 ATTR_SPEC ("symver", 1, -1, true, false, false, false,
213 d_handle_symver_attribute, NULL),
214 ATTR_SPEC ("weak", 0, 0, true, false, false, false,
215 d_handle_weak_attribute, NULL),
216 ATTR_SPEC ("noplt", 0, 0, true, false, false, false,
217 d_handle_noplt_attribute, NULL),
218 ATTR_SPEC ("alloc_size", 1, 3, false, true, true, false,
219 d_handle_alloc_size_attribute, attr_alloc_exclusions),
220 ATTR_SPEC ("cold", 0, 0, true, false, false, false,
221 d_handle_cold_attribute, attr_cold_hot_exclusions),
222 ATTR_SPEC ("restrict", 0, 0, true, false, false, false,
223 d_handle_restrict_attribute, NULL),
224 ATTR_SPEC ("used", 0, 0, true, false, false, false,
225 d_handle_used_attribute, NULL),
226 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
230 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
231 Returns a new variant of the original type declaration. */
233 tree
234 insert_type_attribute (tree type, const char *attrname, tree value)
236 tree ident = get_identifier (attrname);
238 if (value)
239 value = tree_cons (NULL_TREE, value, NULL_TREE);
241 tree attribs = merge_attributes (TYPE_ATTRIBUTES (type),
242 tree_cons (ident, value, NULL_TREE));
244 return build_type_attribute_variant (type, attribs);
247 /* Insert the decl attribute ATTRNAME with value VALUE into DECL. */
249 tree
250 insert_decl_attribute (tree decl, const char *attrname, tree value)
252 tree ident = get_identifier (attrname);
254 if (value)
255 value = tree_cons (NULL_TREE, value, NULL_TREE);
257 tree attribs = merge_attributes (DECL_ATTRIBUTES (decl),
258 tree_cons (ident, value, NULL_TREE));
260 return build_decl_attribute_variant (decl, attribs);
263 /* Returns TRUE if NAME is an attribute recognized as being handled by
264 the `gcc.attribute' module. */
266 static bool
267 uda_attribute_p (const char *name)
269 tree ident = get_identifier (name);
271 /* Search both our language, and target attribute tables.
272 Common and format attributes are kept internal. */
273 for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
275 if (get_identifier (p->name) == ident)
276 return true;
279 if (targetm.attribute_table)
281 for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
283 if (get_identifier (p->name) == ident)
284 return true;
288 return false;
291 /* [attribute/uda]
293 User Defined Attributes (UDA) are compile time expressions that can be
294 attached to a declaration. These attributes can then be queried, extracted,
295 and manipulated at compile-time. There is no run-time component to them.
297 Expand and merge all UDAs found in the EATTRS list that are of type
298 `gcc.attribute.Attribute'. This symbol is internally recognized by the
299 compiler and maps them to their equivalent GCC attribute. */
301 static tree
302 build_attributes (Expressions *eattrs)
304 if (!eattrs)
305 return NULL_TREE;
307 expandTuples (eattrs);
309 tree attribs = NULL_TREE;
311 for (size_t i = 0; i < eattrs->length; i++)
313 Expression *attr = (*eattrs)[i];
314 Dsymbol *sym = attr->type->toDsymbol (0);
316 if (!sym)
318 /* If attribute is a template symbol, perhaps arguments were not
319 supplied, so warn about attribute having no effect. */
320 if (TemplateExp *te = attr->isTemplateExp ())
322 if (!te->td || !te->td->onemember)
323 continue;
325 sym = te->td->onemember;
327 else
328 continue;
331 /* Attribute symbol must come from the `gcc.attribute' module. */
332 Dsymbol *mod = sym->getModule ();
333 if (!(strcmp (mod->toChars (), "attributes") == 0
334 && mod->parent != NULL
335 && strcmp (mod->parent->toChars (), "gcc") == 0
336 && !mod->parent->parent))
337 continue;
339 /* Get the result of the attribute if it hasn't already been folded. */
340 if (attr->op == EXP::call)
341 attr = attr->ctfeInterpret ();
343 if (attr->op != EXP::structLiteral)
345 warning_at (make_location_t (attr->loc), OPT_Wattributes,
346 "%qE attribute has no effect",
347 get_identifier (sym->toChars ()));
348 continue;
351 /* Should now have a struct `Attribute("attrib", "value", ...)'
352 initializer list. */
353 Expressions *elems = attr->isStructLiteralExp ()->elements;
354 Expression *e0 = (*elems)[0];
356 if (e0->op != EXP::string_)
358 warning_at (make_location_t (attr->loc), OPT_Wattributes,
359 "unknown attribute %qs", e0->toChars());
360 continue;
363 StringExp *se = e0->toStringExp ();
364 gcc_assert (se->sz == 1);
366 /* Empty string attribute, just ignore it. */
367 if (se->len == 0)
368 continue;
370 /* Check if the attribute is recognized and handled.
371 Done here to report the diagnostic at the right location. */
372 const char *name = (const char *)(se->len ? se->string : "");
373 if (!uda_attribute_p (name))
375 warning_at (make_location_t (attr->loc), OPT_Wattributes,
376 "unknown attribute %qs", name);
377 continue;
380 /* Chain all attribute arguments together. */
381 tree args = NULL_TREE;
383 for (size_t j = 1; j < elems->length; j++)
385 Expression *e = (*elems)[j];
386 /* Stop after the first `void' argument. */
387 if (e == NULL)
388 break;
390 StringExp *s = e->isStringExp ();
391 tree t;
392 if (s != NULL && s->sz == 1)
394 const char *string = (const char *)(s->len ? s->string : "");
395 t = build_string (s->len, string);
397 else
398 t = build_expr (e);
400 args = chainon (args, build_tree_list (0, t));
403 tree list = build_tree_list (get_identifier (name), args);
404 attribs = chainon (attribs, list);
407 return attribs;
410 /* If any GCC attributes are found in the declaration SYM, apply them to the
411 type or decl NODE. */
413 void
414 apply_user_attributes (Dsymbol *sym, tree node)
416 if (!sym->userAttribDecl)
418 if (DECL_P (node) && DECL_ATTRIBUTES (node) != NULL)
419 decl_attributes (&node, DECL_ATTRIBUTES (node), 0);
421 return;
424 location_t saved_location = input_location;
425 input_location = make_location_t (sym->loc);
427 Expressions *attrs = sym->userAttribDecl->getAttributes ();
428 decl_attributes (&node, build_attributes (attrs),
429 TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0);
431 input_location = saved_location;
434 /* Built-in attribute handlers.
435 These functions take the arguments:
436 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
438 /* Handle a "noreturn" attribute; arguments as in
439 struct attribute_spec.handler. */
441 static tree
442 handle_noreturn_attribute (tree *node, tree, tree, int, bool *)
444 tree type = TREE_TYPE (*node);
446 if (TREE_CODE (*node) == FUNCTION_DECL)
447 TREE_THIS_VOLATILE (*node) = 1;
448 else if (TREE_CODE (type) == POINTER_TYPE
449 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
450 TREE_TYPE (*node)
451 = build_pointer_type
452 (build_type_variant (TREE_TYPE (type),
453 TYPE_READONLY (TREE_TYPE (type)), 1));
454 else
455 gcc_unreachable ();
457 return NULL_TREE;
460 /* Handle a "leaf" attribute; arguments as in
461 struct attribute_spec.handler. */
463 static tree
464 handle_leaf_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
466 if (TREE_CODE (*node) != FUNCTION_DECL)
468 warning (OPT_Wattributes, "%qE attribute ignored", name);
469 *no_add_attrs = true;
471 if (!TREE_PUBLIC (*node))
473 warning (OPT_Wattributes, "%qE attribute has no effect", name);
474 *no_add_attrs = true;
477 return NULL_TREE;
480 /* Handle a "const" attribute; arguments as in
481 struct attribute_spec.handler. */
483 static tree
484 handle_const_attribute (tree *node, tree, tree, int, bool *)
486 tree type = TREE_TYPE (*node);
488 if (TREE_CODE (*node) == FUNCTION_DECL)
489 TREE_READONLY (*node) = 1;
490 else if (TREE_CODE (type) == POINTER_TYPE
491 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
492 TREE_TYPE (*node)
493 = build_pointer_type
494 (build_type_variant (TREE_TYPE (type), 1,
495 TREE_THIS_VOLATILE (TREE_TYPE (type))));
496 else
497 gcc_unreachable ();
499 return NULL_TREE;
502 /* Handle a "malloc" attribute; arguments as in
503 struct attribute_spec.handler. */
505 tree
506 handle_malloc_attribute (tree *node, tree, tree, int, bool *)
508 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
509 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
510 DECL_IS_MALLOC (*node) = 1;
511 return NULL_TREE;
514 /* Handle a "pure" attribute; arguments as in
515 struct attribute_spec.handler. */
517 static tree
518 handle_pure_attribute (tree *node, tree, tree, int, bool *)
520 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
521 DECL_PURE_P (*node) = 1;
522 return NULL_TREE;
525 /* Handle a "no vops" attribute; arguments as in
526 struct attribute_spec.handler. */
528 static tree
529 handle_novops_attribute (tree *node, tree, tree, int, bool *)
531 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
532 DECL_IS_NOVOPS (*node) = 1;
533 return NULL_TREE;
536 /* Helper for nonnull attribute handling; fetch the operand number
537 from the attribute argument list. */
539 static bool
540 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
542 /* Verify the arg number is a constant. */
543 if (!tree_fits_uhwi_p (arg_num_expr))
544 return false;
546 *valp = TREE_INT_CST_LOW (arg_num_expr);
547 return true;
550 /* Handle the "nonnull" attribute. */
552 static tree
553 handle_nonnull_attribute (tree *node, tree, tree args, int, bool *)
555 tree type = *node;
557 /* If no arguments are specified, all pointer arguments should be
558 non-null. Verify a full prototype is given so that the arguments
559 will have the correct types when we actually check them later.
560 Avoid diagnosing type-generic built-ins since those have no
561 prototype. */
562 if (!args)
564 gcc_assert (prototype_p (type)
565 || !TYPE_ATTRIBUTES (type)
566 || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
568 return NULL_TREE;
571 /* Argument list specified. Verify that each argument number references
572 a pointer argument. */
573 for (; args; args = TREE_CHAIN (args))
575 tree argument;
576 unsigned HOST_WIDE_INT arg_num = 0, ck_num;
578 if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
579 gcc_unreachable ();
581 argument = TYPE_ARG_TYPES (type);
582 if (argument)
584 for (ck_num = 1; ; ck_num++)
586 if (!argument || ck_num == arg_num)
587 break;
588 argument = TREE_CHAIN (argument);
591 gcc_assert (argument
592 && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
596 return NULL_TREE;
599 /* Handle a "nothrow" attribute; arguments as in
600 struct attribute_spec.handler. */
602 static tree
603 handle_nothrow_attribute (tree *node, tree, tree, int, bool *)
605 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
606 TREE_NOTHROW (*node) = 1;
607 return NULL_TREE;
610 /* Handle a "type generic" attribute; arguments as in
611 struct attribute_spec.handler. */
613 static tree
614 handle_type_generic_attribute (tree *node, tree, tree, int, bool *)
616 /* Ensure we have a function type. */
617 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
619 /* Ensure we have a variadic function. */
620 gcc_assert (!prototype_p (*node) || stdarg_p (*node));
622 return NULL_TREE;
625 /* Handle a "transaction_pure" attribute; arguments as in
626 struct attribute_spec.handler. */
628 static tree
629 handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *)
631 /* Ensure we have a function type. */
632 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
634 return NULL_TREE;
637 /* Handle a "returns_twice" attribute; arguments as in
638 struct attribute_spec.handler. */
640 static tree
641 handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
643 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
645 DECL_IS_RETURNS_TWICE (*node) = 1;
647 return NULL_TREE;
650 /* Handle a "fn spec" attribute; arguments as in
651 struct attribute_spec.handler. */
653 tree
654 handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
656 gcc_assert (args
657 && TREE_CODE (TREE_VALUE (args)) == STRING_CST
658 && !TREE_CHAIN (args));
659 return NULL_TREE;
662 /* Language specific attribute handlers.
663 These functions take the arguments:
664 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
666 /* Handle a "noinline" attribute; arguments as in
667 struct attribute_spec.handler. */
669 static tree
670 d_handle_noinline_attribute (tree *node, tree name, tree, int,
671 bool *no_add_attrs)
673 if (TREE_CODE (*node) == FUNCTION_DECL)
674 DECL_UNINLINABLE (*node) = 1;
675 else
677 warning (OPT_Wattributes, "%qE attribute ignored", name);
678 *no_add_attrs = true;
681 return NULL_TREE;
684 /* Handle a "always_inline" attribute; arguments as in
685 struct attribute_spec.handler. */
687 static tree
688 d_handle_always_inline_attribute (tree *node, tree name, tree, int,
689 bool *no_add_attrs)
691 if (TREE_CODE (*node) == FUNCTION_DECL)
693 DECL_DECLARED_INLINE_P (*node) = 1;
694 DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
696 else
698 warning (OPT_Wattributes, "%qE attribute ignored", name);
699 *no_add_attrs = true;
702 return NULL_TREE;
705 /* Handle a "flatten" attribute; arguments as in
706 struct attribute_spec.handler. */
708 static tree
709 d_handle_flatten_attribute (tree *node, tree name, tree, int,
710 bool *no_add_attrs)
712 if (TREE_CODE (*node) != FUNCTION_DECL)
714 warning (OPT_Wattributes, "%qE attribute ignored", name);
715 *no_add_attrs = true;
718 return NULL_TREE;
721 /* Handle a "target" attribute; arguments as in
722 struct attribute_spec.handler. */
724 static tree
725 d_handle_target_attribute (tree *node, tree name, tree args, int flags,
726 bool *no_add_attrs)
728 /* Ensure we have a function type. */
729 if (TREE_CODE (*node) != FUNCTION_DECL)
731 warning (OPT_Wattributes, "%qE attribute ignored", name);
732 *no_add_attrs = true;
734 else if (!targetm.target_option.valid_attribute_p (*node, name, args, flags))
735 *no_add_attrs = true;
737 /* Check that there's no empty string in values of the attribute. */
738 for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
740 tree value = TREE_VALUE (t);
741 if (TREE_CODE (value) != STRING_CST
742 || (TREE_STRING_LENGTH (value) != 0
743 && TREE_STRING_POINTER (value)[0] != '\0'))
744 continue;
746 warning (OPT_Wattributes, "empty string in attribute %<target%>");
747 *no_add_attrs = true;
750 return NULL_TREE;
753 /* Handle a "target_clones" attribute; arguments as in
754 struct attribute_spec.handler. */
756 static tree
757 d_handle_target_clones_attribute (tree *node, tree name, tree, int,
758 bool *no_add_attrs)
760 /* Ensure we have a function type. */
761 if (TREE_CODE (*node) != FUNCTION_DECL)
763 warning (OPT_Wattributes, "%qE attribute ignored", name);
764 *no_add_attrs = true;
766 else
768 /* Do not inline functions with multiple clone targets. */
769 DECL_UNINLINABLE (*node) = 1;
772 return NULL_TREE;
775 /* Arguments being collected for optimization. */
776 static GTY(()) vec <const char *, va_gc> *optimize_args;
778 /* Inner function to convert a TREE_LIST to argv string to parse the optimize
779 options in ARGS. */
781 static bool
782 parse_optimize_options (tree args)
784 bool ret = true;
786 /* Build up argv vector. Just in case the string is stored away, use garbage
787 collected strings. */
788 vec_safe_truncate (optimize_args, 0);
789 vec_safe_push (optimize_args, (const char *) NULL);
791 for (tree ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
793 tree value = TREE_VALUE (ap);
795 if (TREE_CODE (value) == INTEGER_CST)
797 char buffer[20];
798 sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
799 vec_safe_push (optimize_args, ggc_strdup (buffer));
801 else if (TREE_CODE (value) == STRING_CST)
803 size_t len = TREE_STRING_LENGTH (value);
804 const char *p = TREE_STRING_POINTER (value);
806 /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
807 options. */
808 if (*p == '-' && p[1] != 'O' && p[1] != 'f')
810 ret = false;
811 warning (OPT_Wattributes,
812 "bad option %qs to attribute %<optimize%>", p);
813 continue;
816 /* Can't use GC memory here. */
817 char *q = XOBNEWVEC (&opts_obstack, char, len + 3);
818 char *r = q;
820 if (*p != '-')
822 *r++ = '-';
824 /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
825 itself is -Os, and any other switch begins with a -f. */
826 if ((*p >= '0' && *p <= '9') || (p[0] == 's' && p[1] == '\0'))
827 *r++ = 'O';
828 else if (*p != 'O')
829 *r++ = 'f';
832 memcpy (r, p, len);
833 r[len] = '\0';
834 vec_safe_push (optimize_args, (const char *) q);
838 unsigned opt_argc = optimize_args->length ();
839 const char **opt_argv
840 = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
842 for (unsigned i = 1; i < opt_argc; i++)
843 opt_argv[i] = (*optimize_args)[i];
845 /* Now parse the options. */
846 struct cl_decoded_option *decoded_options;
847 unsigned int decoded_options_count;
849 decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
850 &decoded_options,
851 &decoded_options_count);
852 /* Drop non-Optimization options. */
853 unsigned j = 1;
854 for (unsigned i = 1; i < decoded_options_count; ++i)
856 unsigned opt_index = decoded_options[i].opt_index;
857 if (opt_index >= cl_options_count
858 || ! (cl_options[opt_index].flags & CL_OPTIMIZATION))
860 ret = false;
861 warning (OPT_Wattributes,
862 "bad option %qs to attribute %<optimize%>",
863 decoded_options[i].orig_option_with_args_text);
864 continue;
866 if (i != j)
867 decoded_options[j] = decoded_options[i];
868 j++;
870 decoded_options_count = j;
871 /* And apply them. */
872 decode_options (&global_options, &global_options_set,
873 decoded_options, decoded_options_count,
874 input_location, global_dc, NULL);
876 targetm.override_options_after_change();
878 optimize_args->truncate (0);
879 return ret;
882 /* Handle a "optimize" attribute; arguments as in
883 struct attribute_spec.handler. */
885 static tree
886 d_handle_optimize_attribute (tree *node, tree name, tree args, int,
887 bool *no_add_attrs)
889 /* Ensure we have a function type. */
890 if (TREE_CODE (*node) != FUNCTION_DECL)
892 warning (OPT_Wattributes, "%qE attribute ignored", name);
893 *no_add_attrs = true;
895 else
897 struct cl_optimization cur_opts;
898 tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
900 /* Save current options. */
901 cl_optimization_save (&cur_opts, &global_options, &global_options_set);
902 tree prev_target_node = build_target_option_node (&global_options,
903 &global_options_set);
905 /* If we previously had some optimization options, use them as the
906 default. */
907 gcc_options *saved_global_options = NULL;
908 if (flag_checking)
910 saved_global_options = XNEW (gcc_options);
911 *saved_global_options = global_options;
914 if (old_opts)
915 cl_optimization_restore (&global_options, &global_options_set,
916 TREE_OPTIMIZATION (old_opts));
918 /* Parse options, and update the vector. */
919 parse_optimize_options (args);
920 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
921 = build_optimization_node (&global_options, &global_options_set);
922 tree target_node = build_target_option_node (&global_options,
923 &global_options_set);
924 if (prev_target_node != target_node)
925 DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
927 /* Restore current options. */
928 cl_optimization_restore (&global_options, &global_options_set,
929 &cur_opts);
930 cl_target_option_restore (&global_options, &global_options_set,
931 TREE_TARGET_OPTION (prev_target_node));
932 if (saved_global_options != NULL)
934 cl_optimization_compare (saved_global_options, &global_options);
935 free (saved_global_options);
939 return NULL_TREE;
942 /* Handle a "noclone" attribute; arguments as in
943 struct attribute_spec.handler. */
945 static tree
946 d_handle_noclone_attribute (tree *node, tree name, tree, int,
947 bool *no_add_attrs)
949 if (TREE_CODE (*node) != FUNCTION_DECL)
951 warning (OPT_Wattributes, "%qE attribute ignored", name);
952 *no_add_attrs = true;
955 return NULL_TREE;
958 /* Handle a "no_icf" attribute; arguments as in
959 struct attribute_spec.handler. */
961 static tree
962 d_handle_noicf_attribute (tree *node, tree name, tree, int,
963 bool *no_add_attrs)
965 if (TREE_CODE (*node) != FUNCTION_DECL)
967 warning (OPT_Wattributes, "%qE attribute ignored", name);
968 *no_add_attrs = true;
971 return NULL_TREE;
974 /* Handle a "noipa" attribute; arguments as in
975 struct attribute_spec.handler. */
977 static tree
978 d_handle_noipa_attribute (tree *node, tree name, tree, int,
979 bool *no_add_attrs)
981 if (TREE_CODE (*node) != FUNCTION_DECL)
983 warning (OPT_Wattributes, "%qE attribute ignored", name);
984 *no_add_attrs = true;
987 return NULL_TREE;
990 /* Handle a "section" attribute; arguments as in
991 struct attribute_spec.handler. */
993 static tree
994 d_handle_section_attribute (tree *node, tree name, tree args, int flags,
995 bool *no_add_attrs)
997 if (!targetm_common.have_named_sections)
999 error ("section attributes are not supported for this target");
1000 *no_add_attrs = true;
1001 return NULL_TREE;
1004 if (!VAR_OR_FUNCTION_DECL_P (*node))
1006 error ("section attribute not allowed for %q+D", *node);
1007 *no_add_attrs = true;
1008 return NULL_TREE;
1011 if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
1013 error ("section attribute argument not a string constant");
1014 *no_add_attrs = true;
1015 return NULL_TREE;
1018 if (VAR_P (*node)
1019 && current_function_decl != NULL_TREE
1020 && !TREE_STATIC (*node))
1022 error ("section attribute cannot be specified for local variables");
1023 *no_add_attrs = true;
1024 return NULL_TREE;
1027 /* The decl may have already been given a section attribute
1028 from a previous declaration. Ensure they match. */
1029 if (DECL_SECTION_NAME (*node) != NULL
1030 && strcmp (DECL_SECTION_NAME (*node),
1031 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
1033 error ("section of %q+D conflicts with previous declaration", *node);
1034 *no_add_attrs = true;
1035 return NULL_TREE;
1038 if (VAR_P (*node)
1039 && !targetm.have_tls && targetm.emutls.tmpl_section
1040 && DECL_THREAD_LOCAL_P (*node))
1042 error ("section of %q+D cannot be overridden", *node);
1043 *no_add_attrs = true;
1044 return NULL_TREE;
1047 tree res = targetm.handle_generic_attribute (node, name, args, flags,
1048 no_add_attrs);
1050 /* If the back end confirms the attribute can be added then continue onto
1051 final processing. */
1052 if (*no_add_attrs)
1053 return NULL_TREE;
1055 set_decl_section_name (*node, TREE_STRING_POINTER (TREE_VALUE (args)));
1056 return res;
1059 /* Handle a "symver" and attribute; arguments as in
1060 struct attribute_spec.handler. */
1062 static tree
1063 d_handle_symver_attribute (tree *node, tree, tree args, int, bool *no_add_attrs)
1065 if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
1067 warning (OPT_Wattributes,
1068 "%<symver%> attribute only applies to functions and variables");
1069 *no_add_attrs = true;
1070 return NULL_TREE;
1073 if (!decl_in_symtab_p (*node))
1075 warning (OPT_Wattributes,
1076 "%<symver%> attribute is only applicable to symbols");
1077 *no_add_attrs = true;
1078 return NULL_TREE;
1081 for (; args; args = TREE_CHAIN (args))
1083 tree symver = TREE_VALUE (args);
1084 if (TREE_CODE (symver) != STRING_CST)
1086 error ("%<symver%> attribute argument not a string constant");
1087 *no_add_attrs = true;
1088 return NULL_TREE;
1091 const char *symver_str = TREE_STRING_POINTER (symver);
1093 int ats = 0;
1094 for (int n = 0; (int)n < TREE_STRING_LENGTH (symver); n++)
1095 if (symver_str[n] == '@')
1096 ats++;
1098 if (ats != 1 && ats != 2)
1100 error ("symver attribute argument must have format %<name@nodename%>");
1101 error ("%<symver%> attribute argument %qs must contain one or two "
1102 "%<@%>", symver_str);
1103 *no_add_attrs = true;
1104 return NULL_TREE;
1108 return NULL_TREE;
1111 /* Handle a "weak" attribute; arguments as in
1112 struct attribute_spec.handler. */
1114 static tree
1115 d_handle_weak_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1117 if (TREE_CODE (*node) == FUNCTION_DECL
1118 && DECL_DECLARED_INLINE_P (*node))
1120 warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
1121 *no_add_attrs = true;
1123 else if (VAR_OR_FUNCTION_DECL_P (*node))
1125 struct symtab_node *n = symtab_node::get (*node);
1126 if (n && n->refuse_visibility_changes)
1127 error ("%q+D declared weak after being used", *node);
1128 declare_weak (*node);
1130 else
1131 warning (OPT_Wattributes, "%qE attribute ignored", name);
1133 return NULL_TREE;
1136 /* Handle a "noplt" attribute; arguments as in
1137 struct attribute_spec.handler. */
1139 static tree
1140 d_handle_noplt_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1142 if (TREE_CODE (*node) != FUNCTION_DECL)
1144 warning (OPT_Wattributes, "%qE attribute ignored", name);
1145 *no_add_attrs = true;
1148 return NULL_TREE;
1151 /* Verify that argument value POS at position ARGNO to attribute ATNAME applied
1152 to function FNTYPE refers to a function parameter at position POS and is a
1153 valid integer type. When ZERO_BASED is true, POS is adjusted to be 1-based.
1154 If successful, POS is returned. Otherwise, issue appropriate warnings and
1155 return null. A non-zero 1-based ARGNO should be passed in by callers only
1156 for attributes with more than one argument. */
1158 static tree
1159 positional_argument (const_tree fntype, const_tree atname, tree pos,
1160 int argno, bool zero_based)
1162 tree postype = TREE_TYPE (pos);
1164 if (pos == error_mark_node || !postype)
1166 /* Only mention the positional argument number when it's non-zero. */
1167 if (argno < 1)
1168 warning (OPT_Wattributes,
1169 "%qE attribute argument is invalid", atname);
1170 else
1171 warning (OPT_Wattributes,
1172 "%qE attribute argument %i is invalid", atname, argno);
1174 return NULL_TREE;
1177 if (!INTEGRAL_TYPE_P (postype))
1179 /* Handle this case specially to avoid mentioning the value
1180 of pointer constants in diagnostics. Only mention
1181 the positional argument number when it's non-zero. */
1182 if (argno < 1)
1183 warning (OPT_Wattributes,
1184 "%qE attribute argument has type %qT",
1185 atname, postype);
1186 else
1187 warning (OPT_Wattributes,
1188 "%qE attribute argument %i has type %qT",
1189 atname, argno, postype);
1191 return NULL_TREE;
1194 if (TREE_CODE (pos) != INTEGER_CST)
1196 /* Only mention the argument number when it's non-zero. */
1197 if (argno < 1)
1198 warning (OPT_Wattributes,
1199 "%qE attribute argument value %qE is not an integer "
1200 "constant",
1201 atname, pos);
1202 else
1203 warning (OPT_Wattributes,
1204 "%qE attribute argument %i value %qE is not an integer "
1205 "constant",
1206 atname, argno, pos);
1208 return NULL_TREE;
1211 /* Validate the value of the position argument. If 0-based, then it should
1212 not be negative. If 1-based, it should be greater than zero. */
1213 if ((zero_based && tree_int_cst_sgn (pos) < 0)
1214 || (!zero_based && tree_int_cst_sgn (pos) < 1))
1216 if (argno < 1)
1217 warning (OPT_Wattributes,
1218 "%qE attribute argument value %qE does not refer to "
1219 "a function parameter",
1220 atname, pos);
1221 else
1222 warning (OPT_Wattributes,
1223 "%qE attribute argument %i value %qE does not refer to "
1224 "a function parameter",
1225 atname, argno, pos);
1227 return NULL_TREE;
1230 /* Adjust the value of pos to be 1-based. */
1231 tree adjusted_pos = (zero_based)
1232 ? int_const_binop (PLUS_EXPR, pos, integer_one_node) : pos;
1234 if (!prototype_p (fntype))
1235 return adjusted_pos;
1237 /* Verify that the argument position does not exceed the number
1238 of formal arguments to the function. */
1239 unsigned nargs = type_num_arguments (fntype);
1240 if (!nargs
1241 || !tree_fits_uhwi_p (adjusted_pos)
1242 || !IN_RANGE (tree_to_uhwi (adjusted_pos), 1, nargs))
1244 if (argno < 1)
1245 warning (OPT_Wattributes,
1246 "%qE attribute argument value %qE exceeds the number "
1247 "of function parameters %u",
1248 atname, pos, nargs);
1249 else
1250 warning (OPT_Wattributes,
1251 "%qE attribute argument %i value %qE exceeds the number "
1252 "of function parameters %u",
1253 atname, argno, pos, nargs);
1255 return NULL_TREE;
1258 /* Verify that the type of the referenced formal argument matches
1259 the expected type. */
1260 unsigned HOST_WIDE_INT ipos = tree_to_uhwi (adjusted_pos);
1262 /* Zero was handled above. */
1263 gcc_assert (ipos != 0);
1265 if (tree argtype = type_argument_type (fntype, ipos))
1267 /* Accept types that match INTEGRAL_TYPE_P except for bool. */
1268 if (!INTEGRAL_TYPE_P (argtype) || TREE_CODE (argtype) == BOOLEAN_TYPE)
1270 if (argno < 1)
1271 warning (OPT_Wattributes,
1272 "%qE attribute argument value %qE refers to "
1273 "parameter type %qT",
1274 atname, pos, argtype);
1275 else
1276 warning (OPT_Wattributes,
1277 "%qE attribute argument %i value %qE refers to "
1278 "parameter type %qT",
1279 atname, argno, pos, argtype);
1281 return NULL_TREE;
1284 return adjusted_pos;
1287 /* Argument position exceeding number of parameters was handled above. */
1288 gcc_unreachable ();
1291 /* Handle a "alloc_size" attribute; arguments as in
1292 struct attribute_spec.handler. */
1294 static tree
1295 d_handle_alloc_size_attribute (tree *node, tree name, tree args, int,
1296 bool *no_add_attrs)
1298 tree fntype = *node;
1299 tree rettype = TREE_TYPE (fntype);
1300 if (!POINTER_TYPE_P (rettype))
1302 warning (OPT_Wattributes,
1303 "%qE attribute ignored on a function returning %qT",
1304 name, rettype);
1305 *no_add_attrs = true;
1306 return NULL_TREE;
1309 /* The first argument SIZE_ARG is never null. */
1310 tree size_arg = TREE_VALUE (args);
1311 tree next = TREE_CHAIN (args);
1313 /* NUM_ARG is null when the attribute includes just one argument, or is
1314 explictly set to null if it has been left uninitialized by the caller. */
1315 tree num_arg = NULL_TREE;
1316 if (next != NULL_TREE)
1318 if (TREE_VALUE (next) != TYPE_MIN_VALUE (d_int_type))
1319 num_arg = TREE_VALUE (next);
1321 next = TREE_CHAIN (next);
1324 /* If ZERO_ARG is set and true, arguments positions are treated as 0-based.
1325 Otherwise the default is 1-based. */
1326 bool zero_based = false;
1327 if (next != NULL_TREE)
1328 zero_based = integer_truep (TREE_VALUE (next));
1330 /* Update the argument values with the real argument position. */
1331 if (tree val = positional_argument (fntype, name, size_arg, num_arg ? 1 : 0,
1332 zero_based))
1333 TREE_VALUE (args) = val;
1334 else
1335 *no_add_attrs = true;
1337 if (num_arg != NULL_TREE)
1339 args = TREE_CHAIN (args);
1340 if (tree val = positional_argument (fntype, name, num_arg, 2, zero_based))
1341 TREE_VALUE (args) = val;
1342 else
1343 *no_add_attrs = true;
1346 /* Terminate the original TREE_CHAIN in `args' to remove any remaining
1347 D-specific `alloc_size` arguments. */
1348 TREE_CHAIN (args) = NULL_TREE;
1350 return NULL_TREE;
1353 /* Handle a "cold" and attribute; arguments as in
1354 struct attribute_spec.handler. */
1356 static tree
1357 d_handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1359 if (TREE_CODE (*node) != FUNCTION_DECL)
1361 warning (OPT_Wattributes, "%qE attribute ignored", name);
1362 *no_add_attrs = true;
1365 return NULL_TREE;
1368 /* Handle a "restrict" attribute; arguments as in
1369 struct attribute_spec.handler. */
1371 static tree
1372 d_handle_restrict_attribute (tree *node, tree name, tree, int,
1373 bool *no_add_attrs)
1375 if (TREE_CODE (*node) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (*node)))
1377 TREE_TYPE (*node) = build_qualified_type (TREE_TYPE (*node),
1378 TYPE_QUAL_RESTRICT);
1380 else
1382 warning (OPT_Wattributes, "%qE attribute ignored", name);
1383 *no_add_attrs = true;
1386 return NULL_TREE;
1389 /* Handle a "used" attribute; arguments as in
1390 struct attribute_spec.handler. */
1392 static tree
1393 d_handle_used_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
1395 if (TREE_CODE (*node) == FUNCTION_DECL
1396 || (VAR_P (*node) && TREE_STATIC (*node))
1397 || (TREE_CODE (*node) == TYPE_DECL))
1399 TREE_USED (*node) = 1;
1400 DECL_PRESERVE_P (*node) = 1;
1401 if (VAR_P (*node))
1402 DECL_READ_P (*node) = 1;
1404 else
1406 warning (OPT_Wattributes, "%qE attribute ignored", name);
1407 *no_add_attrs = true;
1410 return NULL_TREE;