1 /* d-attribs.c -- D attributes handling.
2 Copyright (C) 2015-2021 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)
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. */
23 #include "coretypes.h"
25 #include "dmd/attrib.h"
26 #include "dmd/declaration.h"
27 #include "dmd/module.h"
28 #include "dmd/mtype.h"
29 #include "dmd/template.h"
32 #include "diagnostic.h"
37 #include "common/common-target.h"
38 #include "stringpool.h"
41 #include "fold-const.h"
47 /* Internal attribute handlers for built-in functions. */
48 static tree
handle_noreturn_attribute (tree
*, tree
, tree
, int, bool *);
49 static tree
handle_leaf_attribute (tree
*, tree
, tree
, int, bool *);
50 static tree
handle_const_attribute (tree
*, tree
, tree
, int, bool *);
51 static tree
handle_malloc_attribute (tree
*, tree
, tree
, int, bool *);
52 static tree
handle_pure_attribute (tree
*, tree
, tree
, int, bool *);
53 static tree
handle_novops_attribute (tree
*, tree
, tree
, int, bool *);
54 static tree
handle_nonnull_attribute (tree
*, tree
, tree
, int, bool *);
55 static tree
handle_nothrow_attribute (tree
*, tree
, tree
, int, bool *);
56 static tree
handle_type_generic_attribute (tree
*, tree
, tree
, int, bool *);
57 static tree
handle_transaction_pure_attribute (tree
*, tree
, tree
, int, bool *);
58 static tree
handle_returns_twice_attribute (tree
*, tree
, tree
, int, bool *);
59 static tree
handle_fnspec_attribute (tree
*, tree
, tree
, int, bool *);
61 /* D attribute handlers for user defined attributes. */
62 static tree
d_handle_noinline_attribute (tree
*, tree
, tree
, int, bool *);
63 static tree
d_handle_always_inline_attribute (tree
*, tree
, tree
, int, bool *);
64 static tree
d_handle_flatten_attribute (tree
*, tree
, tree
, int, bool *);
65 static tree
d_handle_target_attribute (tree
*, tree
, tree
, int, bool *);
66 static tree
d_handle_target_clones_attribute (tree
*, tree
, tree
, int, bool *);
67 static tree
d_handle_optimize_attribute (tree
*, tree
, tree
, int, bool *);
68 static tree
d_handle_noclone_attribute (tree
*, tree
, tree
, int, bool *);
69 static tree
d_handle_noicf_attribute (tree
*, tree
, tree
, int, bool *);
70 static tree
d_handle_noipa_attribute (tree
*, tree
, tree
, int, bool *);
71 static tree
d_handle_section_attribute (tree
*, tree
, tree
, int, bool *);
72 static tree
d_handle_symver_attribute (tree
*, tree
, tree
, int, bool *);
73 static tree
d_handle_weak_attribute (tree
*, tree
, tree
, int, bool *) ;
74 static tree
d_handle_noplt_attribute (tree
*, tree
, tree
, int, bool *) ;
75 static tree
d_handle_alloc_size_attribute (tree
*, tree
, tree
, int, bool *);
76 static tree
d_handle_cold_attribute (tree
*, tree
, tree
, int, bool *);
77 static tree
d_handle_restrict_attribute (tree
*, tree
, tree
, int, bool *);
78 static tree
d_handle_used_attribute (tree
*, tree
, tree
, int, bool *);
80 /* Helper to define attribute exclusions. */
81 #define ATTR_EXCL(name, function, type, variable) \
82 { name, function, type, variable }
84 /* Define attributes that are mutually exclusive with one another. */
85 static const struct attribute_spec::exclusions attr_noreturn_exclusions
[] =
87 ATTR_EXCL ("alloc_size", true, true, true),
88 ATTR_EXCL ("const", true, true, true),
89 ATTR_EXCL ("malloc", true, true, true),
90 ATTR_EXCL ("pure", true, true, true),
91 ATTR_EXCL ("returns_twice", true, true, true),
92 ATTR_EXCL (NULL
, false, false, false),
95 static const struct attribute_spec::exclusions attr_returns_twice_exclusions
[] =
97 ATTR_EXCL ("noreturn", true, true, true),
98 ATTR_EXCL (NULL
, false, false, false),
101 static const struct attribute_spec::exclusions attr_const_pure_exclusions
[] =
103 ATTR_EXCL ("alloc_size", true, true, true),
104 ATTR_EXCL ("const", true, true, true),
105 ATTR_EXCL ("noreturn", true, true, true),
106 ATTR_EXCL ("pure", true, true, true),
107 ATTR_EXCL (NULL
, false, false, false)
110 static const struct attribute_spec::exclusions attr_inline_exclusions
[] =
112 ATTR_EXCL ("noinline", true, true, true),
113 ATTR_EXCL ("target_clones", true, true, true),
114 ATTR_EXCL (NULL
, false, false, false),
117 static const struct attribute_spec::exclusions attr_noinline_exclusions
[] =
119 ATTR_EXCL ("always_inline", true, true, true),
120 ATTR_EXCL (NULL
, false, false, false),
123 static const struct attribute_spec::exclusions attr_target_exclusions
[] =
125 ATTR_EXCL ("target_clones", true, true, true),
126 ATTR_EXCL (NULL
, false, false, false),
129 static const struct attribute_spec::exclusions attr_target_clones_exclusions
[] =
131 ATTR_EXCL ("always_inline", true, true, true),
132 ATTR_EXCL ("target", true, true, true),
133 ATTR_EXCL (NULL
, false, false, false),
136 static const struct attribute_spec::exclusions attr_alloc_exclusions
[] =
138 ATTR_EXCL ("const", true, true, true),
139 ATTR_EXCL ("noreturn", true, true, true),
140 ATTR_EXCL ("pure", true, true, true),
141 ATTR_EXCL (NULL
, false, false, false),
144 extern const struct attribute_spec::exclusions attr_cold_hot_exclusions
[] =
146 ATTR_EXCL ("cold", true, true, true),
147 ATTR_EXCL ("hot", true, true, true),
148 ATTR_EXCL (NULL
, false, false, false)
151 /* Helper to define an attribute. */
152 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
153 affects_type_identity, handler, exclude) \
154 { name, min_len, max_len, decl_req, type_req, fn_type_req, \
155 affects_type_identity, handler, exclude }
157 /* Table of machine-independent attributes.
158 For internal use (marking of built-ins) only. */
159 const attribute_spec d_langhook_common_attribute_table
[] =
161 ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
162 handle_noreturn_attribute
, attr_noreturn_exclusions
),
163 ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
164 handle_leaf_attribute
, NULL
),
165 ATTR_SPEC ("const", 0, 0, true, false, false, false,
166 handle_const_attribute
, attr_const_pure_exclusions
),
167 ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
168 handle_malloc_attribute
, NULL
),
169 ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
170 handle_returns_twice_attribute
, attr_returns_twice_exclusions
),
171 ATTR_SPEC ("pure", 0, 0, true, false, false, false,
172 handle_pure_attribute
, attr_const_pure_exclusions
),
173 ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
174 handle_nonnull_attribute
, NULL
),
175 ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
176 handle_nothrow_attribute
, NULL
),
177 ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
178 handle_transaction_pure_attribute
, NULL
),
179 ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
180 handle_novops_attribute
, NULL
),
181 ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
182 handle_type_generic_attribute
, NULL
),
183 ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
184 handle_fnspec_attribute
, NULL
),
185 ATTR_SPEC (NULL
, 0, 0, false, false, false, false, NULL
, NULL
),
188 /* Table of D language attributes exposed by `gcc.attribute' UDAs. */
189 const attribute_spec d_langhook_attribute_table
[] =
191 ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
192 d_handle_noinline_attribute
, attr_noinline_exclusions
),
193 ATTR_SPEC ("always_inline", 0, 0, true, false, false, false,
194 d_handle_always_inline_attribute
, attr_inline_exclusions
),
195 ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
196 d_handle_flatten_attribute
, NULL
),
197 ATTR_SPEC ("target", 1, -1, true, false, false, false,
198 d_handle_target_attribute
, attr_target_exclusions
),
199 ATTR_SPEC ("target_clones", 1, -1, true, false, false, false,
200 d_handle_target_clones_attribute
, attr_target_clones_exclusions
),
201 ATTR_SPEC ("optimize", 1, -1, true, false, false, false,
202 d_handle_optimize_attribute
, NULL
),
203 ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
204 d_handle_noclone_attribute
, NULL
),
205 ATTR_SPEC ("no_icf", 0, 0, true, false, false, false,
206 d_handle_noicf_attribute
, NULL
),
207 ATTR_SPEC ("noipa", 0, 0, true, false, false, false,
208 d_handle_noipa_attribute
, NULL
),
209 ATTR_SPEC ("section", 1, 1, true, false, false, false,
210 d_handle_section_attribute
, NULL
),
211 ATTR_SPEC ("symver", 1, -1, true, false, false, false,
212 d_handle_symver_attribute
, NULL
),
213 ATTR_SPEC ("weak", 0, 0, true, false, false, false,
214 d_handle_weak_attribute
, NULL
),
215 ATTR_SPEC ("noplt", 0, 0, true, false, false, false,
216 d_handle_noplt_attribute
, NULL
),
217 ATTR_SPEC ("alloc_size", 1, 3, false, true, true, false,
218 d_handle_alloc_size_attribute
, attr_alloc_exclusions
),
219 ATTR_SPEC ("cold", 0, 0, true, false, false, false,
220 d_handle_cold_attribute
, attr_cold_hot_exclusions
),
221 ATTR_SPEC ("restrict", 0, 0, true, false, false, false,
222 d_handle_restrict_attribute
, NULL
),
223 ATTR_SPEC ("used", 0, 0, true, false, false, false,
224 d_handle_used_attribute
, NULL
),
225 ATTR_SPEC (NULL
, 0, 0, false, false, false, false, NULL
, NULL
),
229 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
230 Returns a new variant of the original type declaration. */
233 insert_type_attribute (tree type
, const char *attrname
, tree value
)
235 tree ident
= get_identifier (attrname
);
238 value
= tree_cons (NULL_TREE
, value
, NULL_TREE
);
240 tree attribs
= merge_attributes (TYPE_ATTRIBUTES (type
),
241 tree_cons (ident
, value
, NULL_TREE
));
243 return build_type_attribute_variant (type
, attribs
);
246 /* Insert the decl attribute ATTRNAME with value VALUE into DECL. */
249 insert_decl_attribute (tree decl
, const char *attrname
, tree value
)
251 tree ident
= get_identifier (attrname
);
254 value
= tree_cons (NULL_TREE
, value
, NULL_TREE
);
256 tree attribs
= merge_attributes (DECL_ATTRIBUTES (decl
),
257 tree_cons (ident
, value
, NULL_TREE
));
259 return build_decl_attribute_variant (decl
, attribs
);
262 /* Returns TRUE if NAME is an attribute recognized as being handled by
263 the `gcc.attribute' module. */
266 uda_attribute_p (const char *name
)
268 tree ident
= get_identifier (name
);
270 /* Search both our language, and target attribute tables.
271 Common and format attributes are kept internal. */
272 for (const attribute_spec
*p
= d_langhook_attribute_table
; p
->name
; p
++)
274 if (get_identifier (p
->name
) == ident
)
278 if (targetm
.attribute_table
)
280 for (const attribute_spec
*p
= targetm
.attribute_table
; p
->name
; p
++)
282 if (get_identifier (p
->name
) == ident
)
292 User Defined Attributes (UDA) are compile time expressions that can be
293 attached to a declaration. These attributes can then be queried, extracted,
294 and manipulated at compile-time. There is no run-time component to them.
296 Expand and merge all UDAs found in the EATTRS list that are of type
297 `gcc.attribute.Attribute'. This symbol is internally recognized by the
298 compiler and maps them to their equivalent GCC attribute. */
301 build_attributes (Expressions
*eattrs
)
306 expandTuples (eattrs
);
308 tree attribs
= NULL_TREE
;
310 for (size_t i
= 0; i
< eattrs
->length
; i
++)
312 Expression
*attr
= (*eattrs
)[i
];
313 Dsymbol
*sym
= attr
->type
->toDsymbol (0);
317 /* If attribute is a template symbol, perhaps arguments were not
318 supplied, so warn about attribute having no effect. */
319 if (TemplateExp
*te
= attr
->isTemplateExp ())
321 if (!te
->td
|| !te
->td
->onemember
)
324 sym
= te
->td
->onemember
;
330 /* Attribute symbol must come from the `gcc.attribute' module. */
331 Dsymbol
*mod
= sym
->getModule ();
332 if (!(strcmp (mod
->toChars (), "attributes") == 0
333 && mod
->parent
!= NULL
334 && strcmp (mod
->parent
->toChars (), "gcc") == 0
335 && !mod
->parent
->parent
))
338 /* Get the result of the attribute if it hasn't already been folded. */
339 if (attr
->op
== TOKcall
)
340 attr
= attr
->ctfeInterpret ();
342 if (attr
->op
!= TOKstructliteral
)
344 warning_at (make_location_t (attr
->loc
), OPT_Wattributes
,
345 "%qE attribute has no effect",
346 get_identifier (sym
->toChars ()));
350 /* Should now have a struct `Attribute("attrib", "value", ...)'
352 Expressions
*elems
= attr
->isStructLiteralExp ()->elements
;
353 Expression
*e0
= (*elems
)[0];
355 if (e0
->op
!= TOKstring
)
357 warning_at (make_location_t (attr
->loc
), OPT_Wattributes
,
358 "unknown attribute %qs", e0
->toChars());
362 StringExp
*se
= e0
->toStringExp ();
363 gcc_assert (se
->sz
== 1);
365 /* Empty string attribute, just ignore it. */
369 /* Check if the attribute is recognized and handled.
370 Done here to report the diagnostic at the right location. */
371 const char *name
= (const char *)(se
->len
? se
->string
: "");
372 if (!uda_attribute_p (name
))
374 warning_at (make_location_t (attr
->loc
), OPT_Wattributes
,
375 "unknown attribute %qs", name
);
379 /* Chain all attribute arguments together. */
380 tree args
= NULL_TREE
;
382 for (size_t j
= 1; j
< elems
->length
; j
++)
384 Expression
*e
= (*elems
)[j
];
385 /* Stop after the first `void' argument. */
389 StringExp
*s
= e
->isStringExp ();
391 if (s
!= NULL
&& s
->sz
== 1)
393 const char *string
= (const char *)(s
->len
? s
->string
: "");
394 t
= build_string (s
->len
, string
);
399 args
= chainon (args
, build_tree_list (0, t
));
402 tree list
= build_tree_list (get_identifier (name
), args
);
403 attribs
= chainon (attribs
, list
);
409 /* If any GCC attributes are found in the declaration SYM, apply them to the
410 type or decl NODE. */
413 apply_user_attributes (Dsymbol
*sym
, tree node
)
415 if (!sym
->userAttribDecl
)
417 if (DECL_P (node
) && DECL_ATTRIBUTES (node
) != NULL
)
418 decl_attributes (&node
, DECL_ATTRIBUTES (node
), 0);
423 location_t saved_location
= input_location
;
424 input_location
= make_location_t (sym
->loc
);
426 Expressions
*attrs
= sym
->userAttribDecl
->getAttributes ();
427 decl_attributes (&node
, build_attributes (attrs
),
428 TYPE_P (node
) ? ATTR_FLAG_TYPE_IN_PLACE
: 0);
430 input_location
= saved_location
;
433 /* Built-in attribute handlers.
434 These functions take the arguments:
435 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
437 /* Handle a "noreturn" attribute; arguments as in
438 struct attribute_spec.handler. */
441 handle_noreturn_attribute (tree
*node
, tree
, tree
, int, bool *)
443 tree type
= TREE_TYPE (*node
);
445 if (TREE_CODE (*node
) == FUNCTION_DECL
)
446 TREE_THIS_VOLATILE (*node
) = 1;
447 else if (TREE_CODE (type
) == POINTER_TYPE
448 && TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
451 (build_type_variant (TREE_TYPE (type
),
452 TYPE_READONLY (TREE_TYPE (type
)), 1));
459 /* Handle a "leaf" attribute; arguments as in
460 struct attribute_spec.handler. */
463 handle_leaf_attribute (tree
*node
, tree name
, tree
, int, bool *no_add_attrs
)
465 if (TREE_CODE (*node
) != FUNCTION_DECL
)
467 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
468 *no_add_attrs
= true;
470 if (!TREE_PUBLIC (*node
))
472 warning (OPT_Wattributes
, "%qE attribute has no effect", name
);
473 *no_add_attrs
= true;
479 /* Handle a "const" attribute; arguments as in
480 struct attribute_spec.handler. */
483 handle_const_attribute (tree
*node
, tree
, tree
, int, bool *)
485 tree type
= TREE_TYPE (*node
);
487 if (TREE_CODE (*node
) == FUNCTION_DECL
)
488 TREE_READONLY (*node
) = 1;
489 else if (TREE_CODE (type
) == POINTER_TYPE
490 && TREE_CODE (TREE_TYPE (type
)) == FUNCTION_TYPE
)
493 (build_type_variant (TREE_TYPE (type
), 1,
494 TREE_THIS_VOLATILE (TREE_TYPE (type
))));
501 /* Handle a "malloc" attribute; arguments as in
502 struct attribute_spec.handler. */
505 handle_malloc_attribute (tree
*node
, tree
, tree
, int, bool *)
507 gcc_assert (TREE_CODE (*node
) == FUNCTION_DECL
508 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node
))));
509 DECL_IS_MALLOC (*node
) = 1;
513 /* Handle a "pure" attribute; arguments as in
514 struct attribute_spec.handler. */
517 handle_pure_attribute (tree
*node
, tree
, tree
, int, bool *)
519 gcc_assert (TREE_CODE (*node
) == FUNCTION_DECL
);
520 DECL_PURE_P (*node
) = 1;
524 /* Handle a "no vops" attribute; arguments as in
525 struct attribute_spec.handler. */
528 handle_novops_attribute (tree
*node
, tree
, tree
, int, bool *)
530 gcc_assert (TREE_CODE (*node
) == FUNCTION_DECL
);
531 DECL_IS_NOVOPS (*node
) = 1;
535 /* Helper for nonnull attribute handling; fetch the operand number
536 from the attribute argument list. */
539 get_nonnull_operand (tree arg_num_expr
, unsigned HOST_WIDE_INT
*valp
)
541 /* Verify the arg number is a constant. */
542 if (!tree_fits_uhwi_p (arg_num_expr
))
545 *valp
= TREE_INT_CST_LOW (arg_num_expr
);
549 /* Handle the "nonnull" attribute. */
552 handle_nonnull_attribute (tree
*node
, tree
, tree args
, int, bool *)
556 /* If no arguments are specified, all pointer arguments should be
557 non-null. Verify a full prototype is given so that the arguments
558 will have the correct types when we actually check them later.
559 Avoid diagnosing type-generic built-ins since those have no
563 gcc_assert (prototype_p (type
)
564 || !TYPE_ATTRIBUTES (type
)
565 || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type
)));
570 /* Argument list specified. Verify that each argument number references
571 a pointer argument. */
572 for (; args
; args
= TREE_CHAIN (args
))
575 unsigned HOST_WIDE_INT arg_num
= 0, ck_num
;
577 if (!get_nonnull_operand (TREE_VALUE (args
), &arg_num
))
580 argument
= TYPE_ARG_TYPES (type
);
583 for (ck_num
= 1; ; ck_num
++)
585 if (!argument
|| ck_num
== arg_num
)
587 argument
= TREE_CHAIN (argument
);
591 && TREE_CODE (TREE_VALUE (argument
)) == POINTER_TYPE
);
598 /* Handle a "nothrow" attribute; arguments as in
599 struct attribute_spec.handler. */
602 handle_nothrow_attribute (tree
*node
, tree
, tree
, int, bool *)
604 gcc_assert (TREE_CODE (*node
) == FUNCTION_DECL
);
605 TREE_NOTHROW (*node
) = 1;
609 /* Handle a "type generic" attribute; arguments as in
610 struct attribute_spec.handler. */
613 handle_type_generic_attribute (tree
*node
, tree
, tree
, int, bool *)
615 /* Ensure we have a function type. */
616 gcc_assert (TREE_CODE (*node
) == FUNCTION_TYPE
);
618 /* Ensure we have a variadic function. */
619 gcc_assert (!prototype_p (*node
) || stdarg_p (*node
));
624 /* Handle a "transaction_pure" attribute; arguments as in
625 struct attribute_spec.handler. */
628 handle_transaction_pure_attribute (tree
*node
, tree
, tree
, int, bool *)
630 /* Ensure we have a function type. */
631 gcc_assert (TREE_CODE (*node
) == FUNCTION_TYPE
);
636 /* Handle a "returns_twice" attribute; arguments as in
637 struct attribute_spec.handler. */
640 handle_returns_twice_attribute (tree
*node
, tree
, tree
, int, bool *)
642 gcc_assert (TREE_CODE (*node
) == FUNCTION_DECL
);
644 DECL_IS_RETURNS_TWICE (*node
) = 1;
649 /* Handle a "fn spec" attribute; arguments as in
650 struct attribute_spec.handler. */
653 handle_fnspec_attribute (tree
*, tree
, tree args
, int, bool *)
656 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
657 && !TREE_CHAIN (args
));
661 /* Language specific attribute handlers.
662 These functions take the arguments:
663 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */
665 /* Handle a "noinline" attribute; arguments as in
666 struct attribute_spec.handler. */
669 d_handle_noinline_attribute (tree
*node
, tree name
, tree
, int,
672 if (TREE_CODE (*node
) == FUNCTION_DECL
)
673 DECL_UNINLINABLE (*node
) = 1;
676 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
677 *no_add_attrs
= true;
683 /* Handle a "always_inline" attribute; arguments as in
684 struct attribute_spec.handler. */
687 d_handle_always_inline_attribute (tree
*node
, tree name
, tree
, int,
690 if (TREE_CODE (*node
) == FUNCTION_DECL
)
692 DECL_DECLARED_INLINE_P (*node
) = 1;
693 DECL_DISREGARD_INLINE_LIMITS (*node
) = 1;
697 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
698 *no_add_attrs
= true;
704 /* Handle a "flatten" attribute; arguments as in
705 struct attribute_spec.handler. */
708 d_handle_flatten_attribute (tree
*node
, tree name
, tree
, int,
711 if (TREE_CODE (*node
) != FUNCTION_DECL
)
713 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
714 *no_add_attrs
= true;
720 /* Handle a "target" attribute; arguments as in
721 struct attribute_spec.handler. */
724 d_handle_target_attribute (tree
*node
, tree name
, tree args
, int flags
,
727 /* Ensure we have a function type. */
728 if (TREE_CODE (*node
) != FUNCTION_DECL
)
730 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
731 *no_add_attrs
= true;
733 else if (!targetm
.target_option
.valid_attribute_p (*node
, name
, args
, flags
))
734 *no_add_attrs
= true;
736 /* Check that there's no empty string in values of the attribute. */
737 for (tree t
= args
; t
!= NULL_TREE
; t
= TREE_CHAIN (t
))
739 tree value
= TREE_VALUE (t
);
740 if (TREE_CODE (value
) != STRING_CST
741 || (TREE_STRING_LENGTH (value
) != 0
742 && TREE_STRING_POINTER (value
)[0] != '\0'))
745 warning (OPT_Wattributes
, "empty string in attribute %<target%>");
746 *no_add_attrs
= true;
752 /* Handle a "target_clones" attribute; arguments as in
753 struct attribute_spec.handler. */
756 d_handle_target_clones_attribute (tree
*node
, tree name
, tree
, int,
759 /* Ensure we have a function type. */
760 if (TREE_CODE (*node
) != FUNCTION_DECL
)
762 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
763 *no_add_attrs
= true;
767 /* Do not inline functions with multiple clone targets. */
768 DECL_UNINLINABLE (*node
) = 1;
774 /* Arguments being collected for optimization. */
775 static GTY(()) vec
<const char *, va_gc
> *optimize_args
;
777 /* Inner function to convert a TREE_LIST to argv string to parse the optimize
781 parse_optimize_options (tree args
)
785 /* Build up argv vector. Just in case the string is stored away, use garbage
786 collected strings. */
787 vec_safe_truncate (optimize_args
, 0);
788 vec_safe_push (optimize_args
, (const char *) NULL
);
790 for (tree ap
= args
; ap
!= NULL_TREE
; ap
= TREE_CHAIN (ap
))
792 tree value
= TREE_VALUE (ap
);
794 if (TREE_CODE (value
) == INTEGER_CST
)
797 sprintf (buffer
, "-O%ld", (long) TREE_INT_CST_LOW (value
));
798 vec_safe_push (optimize_args
, ggc_strdup (buffer
));
800 else if (TREE_CODE (value
) == STRING_CST
)
802 size_t len
= TREE_STRING_LENGTH (value
);
803 const char *p
= TREE_STRING_POINTER (value
);
805 /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
807 if (*p
== '-' && p
[1] != 'O' && p
[1] != 'f')
810 warning (OPT_Wattributes
,
811 "bad option %qs to attribute %<optimize%>", p
);
815 /* Can't use GC memory here. */
816 char *q
= XOBNEWVEC (&opts_obstack
, char, len
+ 3);
823 /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
824 itself is -Os, and any other switch begins with a -f. */
825 if ((*p
>= '0' && *p
<= '9') || (p
[0] == 's' && p
[1] == '\0'))
833 vec_safe_push (optimize_args
, (const char *) q
);
837 unsigned opt_argc
= optimize_args
->length ();
838 const char **opt_argv
839 = (const char **) alloca (sizeof (char *) * (opt_argc
+ 1));
841 for (unsigned i
= 1; i
< opt_argc
; i
++)
842 opt_argv
[i
] = (*optimize_args
)[i
];
844 /* Now parse the options. */
845 struct cl_decoded_option
*decoded_options
;
846 unsigned int decoded_options_count
;
848 decode_cmdline_options_to_array_default_mask (opt_argc
, opt_argv
,
850 &decoded_options_count
);
851 /* Drop non-Optimization options. */
853 for (unsigned i
= 1; i
< decoded_options_count
; ++i
)
855 unsigned opt_index
= decoded_options
[i
].opt_index
;
856 if (opt_index
>= cl_options_count
857 || ! (cl_options
[opt_index
].flags
& CL_OPTIMIZATION
))
860 warning (OPT_Wattributes
,
861 "bad option %qs to attribute %<optimize%>",
862 decoded_options
[i
].orig_option_with_args_text
);
866 decoded_options
[j
] = decoded_options
[i
];
869 decoded_options_count
= j
;
870 /* And apply them. */
871 decode_options (&global_options
, &global_options_set
,
872 decoded_options
, decoded_options_count
,
873 input_location
, global_dc
, NULL
);
875 targetm
.override_options_after_change();
877 optimize_args
->truncate (0);
881 /* Handle a "optimize" attribute; arguments as in
882 struct attribute_spec.handler. */
885 d_handle_optimize_attribute (tree
*node
, tree name
, tree args
, int,
888 /* Ensure we have a function type. */
889 if (TREE_CODE (*node
) != FUNCTION_DECL
)
891 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
892 *no_add_attrs
= true;
896 struct cl_optimization cur_opts
;
897 tree old_opts
= DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node
);
899 /* Save current options. */
900 cl_optimization_save (&cur_opts
, &global_options
, &global_options_set
);
901 tree prev_target_node
= build_target_option_node (&global_options
,
902 &global_options_set
);
904 /* If we previously had some optimization options, use them as the
906 gcc_options
*saved_global_options
= NULL
;
909 saved_global_options
= XNEW (gcc_options
);
910 *saved_global_options
= global_options
;
914 cl_optimization_restore (&global_options
, &global_options_set
,
915 TREE_OPTIMIZATION (old_opts
));
917 /* Parse options, and update the vector. */
918 parse_optimize_options (args
);
919 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node
)
920 = build_optimization_node (&global_options
, &global_options_set
);
921 tree target_node
= build_target_option_node (&global_options
,
922 &global_options_set
);
923 if (prev_target_node
!= target_node
)
924 DECL_FUNCTION_SPECIFIC_TARGET (*node
) = target_node
;
926 /* Restore current options. */
927 cl_optimization_restore (&global_options
, &global_options_set
,
929 cl_target_option_restore (&global_options
, &global_options_set
,
930 TREE_TARGET_OPTION (prev_target_node
));
931 if (saved_global_options
!= NULL
)
933 cl_optimization_compare (saved_global_options
, &global_options
);
934 free (saved_global_options
);
941 /* Handle a "noclone" attribute; arguments as in
942 struct attribute_spec.handler. */
945 d_handle_noclone_attribute (tree
*node
, tree name
, tree
, int,
948 if (TREE_CODE (*node
) != FUNCTION_DECL
)
950 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
951 *no_add_attrs
= true;
957 /* Handle a "no_icf" attribute; arguments as in
958 struct attribute_spec.handler. */
961 d_handle_noicf_attribute (tree
*node
, tree name
, tree
, int,
964 if (TREE_CODE (*node
) != FUNCTION_DECL
)
966 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
967 *no_add_attrs
= true;
973 /* Handle a "noipa" attribute; arguments as in
974 struct attribute_spec.handler. */
977 d_handle_noipa_attribute (tree
*node
, tree name
, tree
, int,
980 if (TREE_CODE (*node
) != FUNCTION_DECL
)
982 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
983 *no_add_attrs
= true;
989 /* Handle a "section" attribute; arguments as in
990 struct attribute_spec.handler. */
993 d_handle_section_attribute (tree
*node
, tree name
, tree args
, int flags
,
996 if (!targetm_common
.have_named_sections
)
998 error ("section attributes are not supported for this target");
999 *no_add_attrs
= true;
1003 if (!VAR_OR_FUNCTION_DECL_P (*node
))
1005 error ("section attribute not allowed for %q+D", *node
);
1006 *no_add_attrs
= true;
1010 if (TREE_CODE (TREE_VALUE (args
)) != STRING_CST
)
1012 error ("section attribute argument not a string constant");
1013 *no_add_attrs
= true;
1018 && current_function_decl
!= NULL_TREE
1019 && !TREE_STATIC (*node
))
1021 error ("section attribute cannot be specified for local variables");
1022 *no_add_attrs
= true;
1026 /* The decl may have already been given a section attribute
1027 from a previous declaration. Ensure they match. */
1028 if (DECL_SECTION_NAME (*node
) != NULL
1029 && strcmp (DECL_SECTION_NAME (*node
),
1030 TREE_STRING_POINTER (TREE_VALUE (args
))) != 0)
1032 error ("section of %q+D conflicts with previous declaration", *node
);
1033 *no_add_attrs
= true;
1038 && !targetm
.have_tls
&& targetm
.emutls
.tmpl_section
1039 && DECL_THREAD_LOCAL_P (*node
))
1041 error ("section of %q+D cannot be overridden", *node
);
1042 *no_add_attrs
= true;
1046 tree res
= targetm
.handle_generic_attribute (node
, name
, args
, flags
,
1049 /* If the back end confirms the attribute can be added then continue onto
1050 final processing. */
1054 set_decl_section_name (*node
, TREE_STRING_POINTER (TREE_VALUE (args
)));
1058 /* Handle a "symver" and attribute; arguments as in
1059 struct attribute_spec.handler. */
1062 d_handle_symver_attribute (tree
*node
, tree
, tree args
, int, bool *no_add_attrs
)
1064 if (TREE_CODE (*node
) != FUNCTION_DECL
&& TREE_CODE (*node
) != VAR_DECL
)
1066 warning (OPT_Wattributes
,
1067 "%<symver%> attribute only applies to functions and variables");
1068 *no_add_attrs
= true;
1072 if (!decl_in_symtab_p (*node
))
1074 warning (OPT_Wattributes
,
1075 "%<symver%> attribute is only applicable to symbols");
1076 *no_add_attrs
= true;
1080 for (; args
; args
= TREE_CHAIN (args
))
1082 tree symver
= TREE_VALUE (args
);
1083 if (TREE_CODE (symver
) != STRING_CST
)
1085 error ("%<symver%> attribute argument not a string constant");
1086 *no_add_attrs
= true;
1090 const char *symver_str
= TREE_STRING_POINTER (symver
);
1093 for (int n
= 0; (int)n
< TREE_STRING_LENGTH (symver
); n
++)
1094 if (symver_str
[n
] == '@')
1097 if (ats
!= 1 && ats
!= 2)
1099 error ("symver attribute argument must have format %<name@nodename%>");
1100 error ("%<symver%> attribute argument %qs must contain one or two "
1101 "%<@%>", symver_str
);
1102 *no_add_attrs
= true;
1110 /* Handle a "weak" attribute; arguments as in
1111 struct attribute_spec.handler. */
1114 d_handle_weak_attribute (tree
*node
, tree name
, tree
, int, bool *no_add_attrs
)
1116 if (TREE_CODE (*node
) == FUNCTION_DECL
1117 && DECL_DECLARED_INLINE_P (*node
))
1119 warning (OPT_Wattributes
, "inline function %q+D declared weak", *node
);
1120 *no_add_attrs
= true;
1122 else if (VAR_OR_FUNCTION_DECL_P (*node
))
1124 struct symtab_node
*n
= symtab_node::get (*node
);
1125 if (n
&& n
->refuse_visibility_changes
)
1126 error ("%q+D declared weak after being used", *node
);
1127 declare_weak (*node
);
1130 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
1135 /* Handle a "noplt" attribute; arguments as in
1136 struct attribute_spec.handler. */
1139 d_handle_noplt_attribute (tree
*node
, tree name
, tree
, int, bool *no_add_attrs
)
1141 if (TREE_CODE (*node
) != FUNCTION_DECL
)
1143 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
1144 *no_add_attrs
= true;
1150 /* Verify that argument value POS at position ARGNO to attribute ATNAME applied
1151 to function FNTYPE refers to a function parameter at position POS and is a
1152 valid integer type. When ZERO_BASED is true, POS is adjusted to be 1-based.
1153 If successful, POS is returned. Otherwise, issue appropriate warnings and
1154 return null. A non-zero 1-based ARGNO should be passed in by callers only
1155 for attributes with more than one argument. */
1158 positional_argument (const_tree fntype
, const_tree atname
, tree pos
,
1159 int argno
, bool zero_based
)
1161 tree postype
= TREE_TYPE (pos
);
1163 if (pos
== error_mark_node
|| !postype
)
1165 /* Only mention the positional argument number when it's non-zero. */
1167 warning (OPT_Wattributes
,
1168 "%qE attribute argument is invalid", atname
);
1170 warning (OPT_Wattributes
,
1171 "%qE attribute argument %i is invalid", atname
, argno
);
1176 if (!INTEGRAL_TYPE_P (postype
))
1178 /* Handle this case specially to avoid mentioning the value
1179 of pointer constants in diagnostics. Only mention
1180 the positional argument number when it's non-zero. */
1182 warning (OPT_Wattributes
,
1183 "%qE attribute argument has type %qT",
1186 warning (OPT_Wattributes
,
1187 "%qE attribute argument %i has type %qT",
1188 atname
, argno
, postype
);
1193 if (TREE_CODE (pos
) != INTEGER_CST
)
1195 /* Only mention the argument number when it's non-zero. */
1197 warning (OPT_Wattributes
,
1198 "%qE attribute argument value %qE is not an integer "
1202 warning (OPT_Wattributes
,
1203 "%qE attribute argument %i value %qE is not an integer "
1205 atname
, argno
, pos
);
1210 /* Validate the value of the position argument. If 0-based, then it should
1211 not be negative. If 1-based, it should be greater than zero. */
1212 if ((zero_based
&& tree_int_cst_sgn (pos
) < 0)
1213 || (!zero_based
&& tree_int_cst_sgn (pos
) < 1))
1216 warning (OPT_Wattributes
,
1217 "%qE attribute argument value %qE does not refer to "
1218 "a function parameter",
1221 warning (OPT_Wattributes
,
1222 "%qE attribute argument %i value %qE does not refer to "
1223 "a function parameter",
1224 atname
, argno
, pos
);
1229 /* Adjust the value of pos to be 1-based. */
1230 tree adjusted_pos
= (zero_based
)
1231 ? int_const_binop (PLUS_EXPR
, pos
, integer_one_node
) : pos
;
1233 if (!prototype_p (fntype
))
1234 return adjusted_pos
;
1236 /* Verify that the argument position does not exceed the number
1237 of formal arguments to the function. */
1238 unsigned nargs
= type_num_arguments (fntype
);
1240 || !tree_fits_uhwi_p (adjusted_pos
)
1241 || !IN_RANGE (tree_to_uhwi (adjusted_pos
), 1, nargs
))
1244 warning (OPT_Wattributes
,
1245 "%qE attribute argument value %qE exceeds the number "
1246 "of function parameters %u",
1247 atname
, pos
, nargs
);
1249 warning (OPT_Wattributes
,
1250 "%qE attribute argument %i value %qE exceeds the number "
1251 "of function parameters %u",
1252 atname
, argno
, pos
, nargs
);
1257 /* Verify that the type of the referenced formal argument matches
1258 the expected type. */
1259 unsigned HOST_WIDE_INT ipos
= tree_to_uhwi (adjusted_pos
);
1261 /* Zero was handled above. */
1262 gcc_assert (ipos
!= 0);
1264 if (tree argtype
= type_argument_type (fntype
, ipos
))
1266 /* Accept types that match INTEGRAL_TYPE_P except for bool. */
1267 if (!INTEGRAL_TYPE_P (argtype
) || TREE_CODE (argtype
) == BOOLEAN_TYPE
)
1270 warning (OPT_Wattributes
,
1271 "%qE attribute argument value %qE refers to "
1272 "parameter type %qT",
1273 atname
, pos
, argtype
);
1275 warning (OPT_Wattributes
,
1276 "%qE attribute argument %i value %qE refers to "
1277 "parameter type %qT",
1278 atname
, argno
, pos
, argtype
);
1283 return adjusted_pos
;
1286 /* Argument position exceeding number of parameters was handled above. */
1290 /* Handle a "alloc_size" attribute; arguments as in
1291 struct attribute_spec.handler. */
1294 d_handle_alloc_size_attribute (tree
*node
, tree name
, tree args
, int,
1297 tree fntype
= *node
;
1298 tree rettype
= TREE_TYPE (fntype
);
1299 if (!POINTER_TYPE_P (rettype
))
1301 warning (OPT_Wattributes
,
1302 "%qE attribute ignored on a function returning %qT",
1304 *no_add_attrs
= true;
1308 /* The first argument SIZE_ARG is never null. */
1309 tree size_arg
= TREE_VALUE (args
);
1310 tree next
= TREE_CHAIN (args
);
1312 /* NUM_ARG is null when the attribute includes just one argument, or is
1313 explictly set to null if it has been left uninitialized by the caller. */
1314 tree num_arg
= NULL_TREE
;
1315 if (next
!= NULL_TREE
)
1317 if (TREE_VALUE (next
) != TYPE_MIN_VALUE (d_int_type
))
1318 num_arg
= TREE_VALUE (next
);
1320 next
= TREE_CHAIN (next
);
1323 /* If ZERO_ARG is set and true, arguments positions are treated as 0-based.
1324 Otherwise the default is 1-based. */
1325 bool zero_based
= false;
1326 if (next
!= NULL_TREE
)
1327 zero_based
= integer_truep (TREE_VALUE (next
));
1329 /* Update the argument values with the real argument position. */
1330 if (tree val
= positional_argument (fntype
, name
, size_arg
, num_arg
? 1 : 0,
1332 TREE_VALUE (args
) = val
;
1334 *no_add_attrs
= true;
1336 if (num_arg
!= NULL_TREE
)
1338 args
= TREE_CHAIN (args
);
1339 if (tree val
= positional_argument (fntype
, name
, num_arg
, 2, zero_based
))
1340 TREE_VALUE (args
) = val
;
1342 *no_add_attrs
= true;
1345 /* Terminate the original TREE_CHAIN in `args' to remove any remaining
1346 D-specific `alloc_size` arguments. */
1347 TREE_CHAIN (args
) = NULL_TREE
;
1352 /* Handle a "cold" and attribute; arguments as in
1353 struct attribute_spec.handler. */
1356 d_handle_cold_attribute (tree
*node
, tree name
, tree
, int, bool *no_add_attrs
)
1358 if (TREE_CODE (*node
) != FUNCTION_DECL
)
1360 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
1361 *no_add_attrs
= true;
1367 /* Handle a "restrict" attribute; arguments as in
1368 struct attribute_spec.handler. */
1371 d_handle_restrict_attribute (tree
*node
, tree name
, tree
, int,
1374 if (TREE_CODE (*node
) == PARM_DECL
&& POINTER_TYPE_P (TREE_TYPE (*node
)))
1376 TREE_TYPE (*node
) = build_qualified_type (TREE_TYPE (*node
),
1377 TYPE_QUAL_RESTRICT
);
1381 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
1382 *no_add_attrs
= true;
1388 /* Handle a "used" attribute; arguments as in
1389 struct attribute_spec.handler. */
1392 d_handle_used_attribute (tree
*node
, tree name
, tree
, int, bool *no_add_attrs
)
1394 if (TREE_CODE (*node
) == FUNCTION_DECL
1395 || (VAR_P (*node
) && TREE_STATIC (*node
))
1396 || (TREE_CODE (*node
) == TYPE_DECL
))
1398 TREE_USED (*node
) = 1;
1399 DECL_PRESERVE_P (*node
) = 1;
1401 DECL_READ_P (*node
) = 1;
1405 warning (OPT_Wattributes
, "%qE attribute ignored", name
);
1406 *no_add_attrs
= true;