1 /* d-attribs.c -- D attributes handling.
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
17
18 /* Implementation of attribute handlers for user defined attributes and
19 internal built-in functions. */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24
25 #include "dmd/attrib.h"
26 #include "dmd/declaration.h"
27 #include "dmd/mtype.h"
28
29 #include "tree.h"
30 #include "diagnostic.h"
31 #include "tm.h"
32 #include "cgraph.h"
33 #include "toplev.h"
34 #include "target.h"
35 #include "common/common-target.h"
36 #include "stringpool.h"
37 #include "attribs.h"
38 #include "varasm.h"
39
40 #include "d-tree.h"
41
42
43 /* Internal attribute handlers for built-in functions. */
44 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
45 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
46 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
47 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
48 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
49 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
50 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
51 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
52 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
53 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
54 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
55 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
56 static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *);
57
58 /* D attribute handlers for user defined attributes. */
59 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
60 static tree d_handle_forceinline_attribute (tree *, tree, tree, int, bool *);
61 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
62 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
63 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
64 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
65 static tree d_handle_alias_attribute (tree *, tree, tree, int, bool *);
66 static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ;
67
68 /* Helper to define attribute exclusions. */
69 #define ATTR_EXCL(name, function, type, variable) \
70 { name, function, type, variable }
71
72 /* Define attributes that are mutually exclusive with one another. */
73 static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
74 {
75 ATTR_EXCL ("const", true, true, true),
76 ATTR_EXCL ("malloc", true, true, true),
77 ATTR_EXCL ("pure", true, true, true),
78 ATTR_EXCL ("returns_twice", true, true, true),
79 ATTR_EXCL (NULL, false, false, false),
80 };
81
82 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
83 {
84 ATTR_EXCL ("noreturn", true, true, true),
85 ATTR_EXCL (NULL, false, false, false),
86 };
87
88 static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
89 {
90 ATTR_EXCL ("const", true, true, true),
91 ATTR_EXCL ("noreturn", true, true, true),
92 ATTR_EXCL ("pure", true, true, true),
93 ATTR_EXCL (NULL, false, false, false)
94 };
95
96 static const struct attribute_spec::exclusions attr_inline_exclusions[] =
97 {
98 ATTR_EXCL ("noinline", true, true, true),
99 ATTR_EXCL (NULL, false, false, false),
100 };
101
102 static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
103 {
104 ATTR_EXCL ("forceinline", true, true, true),
105 ATTR_EXCL (NULL, false, false, false),
106 };
107
108 /* Helper to define an attribute. */
109 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
110 affects_type_identity, handler, exclude) \
111 { name, min_len, max_len, decl_req, type_req, fn_type_req, \
112 affects_type_identity, handler, exclude }
113
114 /* Table of machine-independent attributes.
115 For internal use (marking of built-ins) only. */
116 const attribute_spec d_langhook_common_attribute_table[] =
117 {
118 ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
119 handle_noreturn_attribute, attr_noreturn_exclusions),
120 ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
121 handle_leaf_attribute, NULL),
122 ATTR_SPEC ("const", 0, 0, true, false, false, false,
123 handle_const_attribute, attr_const_pure_exclusions),
124 ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
125 handle_malloc_attribute, NULL),
126 ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
127 handle_returns_twice_attribute, attr_returns_twice_exclusions),
128 ATTR_SPEC ("pure", 0, 0, true, false, false, false,
129 handle_pure_attribute, attr_const_pure_exclusions),
130 ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
131 handle_nonnull_attribute, NULL),
132 ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
133 handle_nothrow_attribute, NULL),
134 ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
135 handle_transaction_pure_attribute, NULL),
136 ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
137 handle_novops_attribute, NULL),
138 ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
139 handle_type_generic_attribute, NULL),
140 ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
141 handle_fnspec_attribute, NULL),
142 ATTR_SPEC ("always_inline", 0, 0, true, false, false, false,
143 handle_always_inline_attribute, NULL),
144 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
145 };
146
147 /* Table of D language attributes exposed by `gcc.attribute' UDAs. */
148 const attribute_spec d_langhook_attribute_table[] =
149 {
150 ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
151 d_handle_noinline_attribute, attr_noinline_exclusions),
152 ATTR_SPEC ("forceinline", 0, 0, true, false, false, false,
153 d_handle_forceinline_attribute, attr_inline_exclusions),
154 ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
155 d_handle_flatten_attribute, NULL),
156 ATTR_SPEC ("target", 1, -1, true, false, false, false,
157 d_handle_target_attribute, NULL),
158 ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
159 d_handle_noclone_attribute, NULL),
160 ATTR_SPEC ("section", 1, 1, true, false, false, false,
161 d_handle_section_attribute, NULL),
162 ATTR_SPEC ("alias", 1, 1, true, false, false, false,
163 d_handle_alias_attribute, NULL),
164 ATTR_SPEC ("weak", 0, 0, true, false, false, false,
165 d_handle_weak_attribute, NULL),
166 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
167 };
168
169
170 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
171 Returns a new variant of the original type declaration. */
172
173 tree
insert_type_attribute(tree type,const char * attrname,tree value)174 insert_type_attribute (tree type, const char *attrname, tree value)
175 {
176 tree ident = get_identifier (attrname);
177
178 if (value)
179 value = tree_cons (NULL_TREE, value, NULL_TREE);
180
181 tree attribs = merge_attributes (TYPE_ATTRIBUTES (type),
182 tree_cons (ident, value, NULL_TREE));
183
184 return build_type_attribute_variant (type, attribs);
185 }
186
187 /* Insert the decl attribute ATTRNAME with value VALUE into DECL. */
188
189 tree
insert_decl_attribute(tree decl,const char * attrname,tree value)190 insert_decl_attribute (tree decl, const char *attrname, tree value)
191 {
192 tree ident = get_identifier (attrname);
193
194 if (value)
195 value = tree_cons (NULL_TREE, value, NULL_TREE);
196
197 tree attribs = merge_attributes (DECL_ATTRIBUTES (decl),
198 tree_cons (ident, value, NULL_TREE));
199
200 return build_decl_attribute_variant (decl, attribs);
201 }
202
203 /* Returns TRUE if NAME is an attribute recognized as being handled by
204 the `gcc.attribute' module. */
205
206 static bool
uda_attribute_p(const char * name)207 uda_attribute_p (const char *name)
208 {
209 tree ident = get_identifier (name);
210
211 /* Search both our language, and target attribute tables.
212 Common and format attributes are kept internal. */
213 for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
214 {
215 if (get_identifier (p->name) == ident)
216 return true;
217 }
218
219 if (targetm.attribute_table)
220 {
221 for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
222 {
223 if (get_identifier (p->name) == ident)
224 return true;
225 }
226 }
227
228 return false;
229 }
230
231 /* [attribute/uda]
232
233 User Defined Attributes (UDA) are compile time expressions that can be
234 attached to a declaration. These attributes can then be queried, extracted,
235 and manipulated at compile-time. There is no run-time component to them.
236
237 Expand and merge all UDAs found in the EATTRS list that are of type
238 `gcc.attribute.Attribute'. This symbol is internally recognized by the
239 compiler and maps them to their equivalent GCC attribute. */
240
241 static tree
build_attributes(Expressions * eattrs)242 build_attributes (Expressions *eattrs)
243 {
244 if (!eattrs)
245 return NULL_TREE;
246
247 expandTuples (eattrs);
248
249 tree attribs = NULL_TREE;
250
251 for (size_t i = 0; i < eattrs->dim; i++)
252 {
253 Expression *attr = (*eattrs)[i];
254 Dsymbol *sym = attr->type->toDsymbol (0);
255
256 if (!sym)
257 continue;
258
259 /* Attribute symbol must come from the `gcc.attribute' module. */
260 Dsymbol *mod = (Dsymbol*) sym->getModule ();
261 if (!(strcmp (mod->toChars (), "attribute") == 0
262 && mod->parent != NULL
263 && strcmp (mod->parent->toChars (), "gcc") == 0
264 && !mod->parent->parent))
265 continue;
266
267 /* Get the result of the attribute if it hasn't already been folded. */
268 if (attr->op == TOKcall)
269 attr = attr->ctfeInterpret ();
270
271 /* Should now have a struct `Attribute("attrib", "value", ...)'
272 initializer list. */
273 gcc_assert (attr->op == TOKstructliteral);
274 Expressions *elems = ((StructLiteralExp*) attr)->elements;
275 Expression *e0 = (*elems)[0];
276
277 if (e0->op != TOKstring)
278 {
279 error ("expected string attribute, not %qs", e0->toChars ());
280 return error_mark_node;
281 }
282
283 StringExp *se = (StringExp*) e0;
284 gcc_assert (se->sz == 1);
285
286 /* Empty string attribute, just ignore it. */
287 if (se->len == 0)
288 continue;
289
290 /* Check if the attribute is recognized and handled.
291 Done here to report the diagnostic at the right location. */
292 const char *name = (const char *)(se->len ? se->string : "");
293 if (!uda_attribute_p (name))
294 {
295 warning_at (make_location_t (e0->loc), OPT_Wattributes,
296 "unknown attribute %qs", name);
297 return error_mark_node;
298 }
299
300 /* Chain all attribute arguments together. */
301 tree args = NULL_TREE;
302
303 for (size_t j = 1; j < elems->dim; j++)
304 {
305 Expression *e = (*elems)[j];
306 tree t;
307 if (e->op == TOKstring && ((StringExp *) e)->sz == 1)
308 {
309 StringExp *s = (StringExp *) e;
310 const char *string = (const char *)(s->len ? s->string : "");
311 t = build_string (s->len, string);
312 }
313 else
314 t = build_expr (e);
315
316 args = chainon (args, build_tree_list (0, t));
317 }
318
319 tree list = build_tree_list (get_identifier (name), args);
320 attribs = chainon (attribs, list);
321 }
322
323 return attribs;
324 }
325
326 /* If any GCC attributes are found in the declaration SYM, apply them to the
327 type or decl NODE. */
328
329 void
apply_user_attributes(Dsymbol * sym,tree node)330 apply_user_attributes (Dsymbol *sym, tree node)
331 {
332 if (!sym->userAttribDecl)
333 {
334 if (DECL_P (node) && DECL_ATTRIBUTES (node) != NULL)
335 decl_attributes (&node, DECL_ATTRIBUTES (node), 0);
336
337 return;
338 }
339
340 location_t saved_location = input_location;
341 input_location = make_location_t (sym->loc);
342
343 Expressions *attrs = sym->userAttribDecl->getAttributes ();
344 decl_attributes (&node, build_attributes (attrs),
345 TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0);
346
347 input_location = saved_location;
348 }
349
350 /* Built-in attribute handlers. */
351
352 /* Handle a "noreturn" attribute; arguments as in
353 struct attribute_spec.handler. */
354
355 static tree
handle_noreturn_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))356 handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
357 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
358 bool * ARG_UNUSED (no_add_attrs))
359 {
360 tree type = TREE_TYPE (*node);
361
362 if (TREE_CODE (*node) == FUNCTION_DECL)
363 TREE_THIS_VOLATILE (*node) = 1;
364 else if (TREE_CODE (type) == POINTER_TYPE
365 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
366 TREE_TYPE (*node)
367 = build_pointer_type
368 (build_type_variant (TREE_TYPE (type),
369 TYPE_READONLY (TREE_TYPE (type)), 1));
370 else
371 gcc_unreachable ();
372
373 return NULL_TREE;
374 }
375
376 /* Handle a "leaf" attribute; arguments as in
377 struct attribute_spec.handler. */
378
379 static tree
handle_leaf_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)380 handle_leaf_attribute (tree *node, tree name,
381 tree ARG_UNUSED (args),
382 int ARG_UNUSED (flags), bool *no_add_attrs)
383 {
384 if (TREE_CODE (*node) != FUNCTION_DECL)
385 {
386 warning (OPT_Wattributes, "%qE attribute ignored", name);
387 *no_add_attrs = true;
388 }
389 if (!TREE_PUBLIC (*node))
390 {
391 warning (OPT_Wattributes, "%qE attribute has no effect", name);
392 *no_add_attrs = true;
393 }
394
395 return NULL_TREE;
396 }
397
398 /* Handle a "const" attribute; arguments as in
399 struct attribute_spec.handler. */
400
401 static tree
handle_const_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))402 handle_const_attribute (tree *node, tree ARG_UNUSED (name),
403 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
404 bool * ARG_UNUSED (no_add_attrs))
405 {
406 tree type = TREE_TYPE (*node);
407
408 if (TREE_CODE (*node) == FUNCTION_DECL)
409 TREE_READONLY (*node) = 1;
410 else if (TREE_CODE (type) == POINTER_TYPE
411 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
412 TREE_TYPE (*node)
413 = build_pointer_type
414 (build_type_variant (TREE_TYPE (type), 1,
415 TREE_THIS_VOLATILE (TREE_TYPE (type))));
416 else
417 gcc_unreachable ();
418
419 return NULL_TREE;
420 }
421
422 /* Handle a "malloc" attribute; arguments as in
423 struct attribute_spec.handler. */
424
425 tree
handle_malloc_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))426 handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
427 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
428 bool * ARG_UNUSED (no_add_attrs))
429 {
430 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
431 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
432 DECL_IS_MALLOC (*node) = 1;
433 return NULL_TREE;
434 }
435
436 /* Handle a "pure" attribute; arguments as in
437 struct attribute_spec.handler. */
438
439 static tree
handle_pure_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))440 handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
441 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
442 bool * ARG_UNUSED (no_add_attrs))
443 {
444 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
445 DECL_PURE_P (*node) = 1;
446 return NULL_TREE;
447 }
448
449 /* Handle a "no vops" attribute; arguments as in
450 struct attribute_spec.handler. */
451
452 static tree
handle_novops_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))453 handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
454 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
455 bool * ARG_UNUSED (no_add_attrs))
456 {
457 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
458 DECL_IS_NOVOPS (*node) = 1;
459 return NULL_TREE;
460 }
461
462 /* Helper for nonnull attribute handling; fetch the operand number
463 from the attribute argument list. */
464
465 static bool
get_nonnull_operand(tree arg_num_expr,unsigned HOST_WIDE_INT * valp)466 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
467 {
468 /* Verify the arg number is a constant. */
469 if (!tree_fits_uhwi_p (arg_num_expr))
470 return false;
471
472 *valp = TREE_INT_CST_LOW (arg_num_expr);
473 return true;
474 }
475
476 /* Handle the "nonnull" attribute. */
477
478 static tree
handle_nonnull_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))479 handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
480 tree args, int ARG_UNUSED (flags),
481 bool * ARG_UNUSED (no_add_attrs))
482 {
483 tree type = *node;
484
485 /* If no arguments are specified, all pointer arguments should be
486 non-null. Verify a full prototype is given so that the arguments
487 will have the correct types when we actually check them later.
488 Avoid diagnosing type-generic built-ins since those have no
489 prototype. */
490 if (!args)
491 {
492 gcc_assert (prototype_p (type)
493 || !TYPE_ATTRIBUTES (type)
494 || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
495
496 return NULL_TREE;
497 }
498
499 /* Argument list specified. Verify that each argument number references
500 a pointer argument. */
501 for (; args; args = TREE_CHAIN (args))
502 {
503 tree argument;
504 unsigned HOST_WIDE_INT arg_num = 0, ck_num;
505
506 if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
507 gcc_unreachable ();
508
509 argument = TYPE_ARG_TYPES (type);
510 if (argument)
511 {
512 for (ck_num = 1; ; ck_num++)
513 {
514 if (!argument || ck_num == arg_num)
515 break;
516 argument = TREE_CHAIN (argument);
517 }
518
519 gcc_assert (argument
520 && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
521 }
522 }
523
524 return NULL_TREE;
525 }
526
527 /* Handle a "nothrow" attribute; arguments as in
528 struct attribute_spec.handler. */
529
530 static tree
handle_nothrow_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))531 handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
532 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
533 bool * ARG_UNUSED (no_add_attrs))
534 {
535 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
536 TREE_NOTHROW (*node) = 1;
537 return NULL_TREE;
538 }
539
540 /* Handle a "type_generic" attribute. */
541
542 static tree
handle_type_generic_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))543 handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
544 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
545 bool * ARG_UNUSED (no_add_attrs))
546 {
547 /* Ensure we have a function type. */
548 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
549
550 /* Ensure we have a variadic function. */
551 gcc_assert (!prototype_p (*node) || stdarg_p (*node));
552
553 return NULL_TREE;
554 }
555
556 /* Handle a "transaction_pure" attribute. */
557
558 static tree
handle_transaction_pure_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))559 handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
560 tree ARG_UNUSED (args),
561 int ARG_UNUSED (flags),
562 bool * ARG_UNUSED (no_add_attrs))
563 {
564 /* Ensure we have a function type. */
565 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
566
567 return NULL_TREE;
568 }
569
570 /* Handle a "returns_twice" attribute. */
571
572 static tree
handle_returns_twice_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))573 handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
574 tree ARG_UNUSED (args),
575 int ARG_UNUSED (flags),
576 bool * ARG_UNUSED (no_add_attrs))
577 {
578 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
579
580 DECL_IS_RETURNS_TWICE (*node) = 1;
581
582 return NULL_TREE;
583 }
584
585 /* Handle a "fn spec" attribute; arguments as in
586 struct attribute_spec.handler. */
587
588 tree
handle_fnspec_attribute(tree * node ATTRIBUTE_UNUSED,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs ATTRIBUTE_UNUSED)589 handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
590 tree args, int ARG_UNUSED (flags),
591 bool *no_add_attrs ATTRIBUTE_UNUSED)
592 {
593 gcc_assert (args
594 && TREE_CODE (TREE_VALUE (args)) == STRING_CST
595 && !TREE_CHAIN (args));
596 return NULL_TREE;
597 }
598
599 /* Handle a "always_inline" attribute; arguments as in
600 struct attribute_spec.handler. */
601
602 static tree
handle_always_inline_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs ATTRIBUTE_UNUSED)603 handle_always_inline_attribute (tree *node, tree ARG_UNUSED (name),
604 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
605 bool *no_add_attrs ATTRIBUTE_UNUSED)
606 {
607 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
608
609 return NULL_TREE;
610 }
611
612 /* Language specific attribute handlers. */
613
614 /* Handle a "noinline" attribute. */
615
616 static tree
d_handle_noinline_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)617 d_handle_noinline_attribute (tree *node, tree name,
618 tree ARG_UNUSED (args),
619 int ARG_UNUSED (flags), bool *no_add_attrs)
620 {
621 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
622
623 if (t->ty == Tfunction)
624 DECL_UNINLINABLE (*node) = 1;
625 else
626 {
627 warning (OPT_Wattributes, "%qE attribute ignored", name);
628 *no_add_attrs = true;
629 }
630
631 return NULL_TREE;
632 }
633
634 /* Handle a "forceinline" attribute. */
635
636 static tree
d_handle_forceinline_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)637 d_handle_forceinline_attribute (tree *node, tree name,
638 tree ARG_UNUSED (args),
639 int ARG_UNUSED (flags),
640 bool *no_add_attrs)
641 {
642 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
643
644 if (t->ty == Tfunction)
645 {
646 tree attributes = DECL_ATTRIBUTES (*node);
647
648 /* Push attribute always_inline. */
649 if (! lookup_attribute ("always_inline", attributes))
650 DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("always_inline"),
651 NULL_TREE, attributes);
652
653 DECL_DECLARED_INLINE_P (*node) = 1;
654 DECL_NO_INLINE_WARNING_P (*node) = 1;
655 DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
656 }
657 else
658 {
659 warning (OPT_Wattributes, "%qE attribute ignored", name);
660 *no_add_attrs = true;
661 }
662
663 return NULL_TREE;
664 }
665
666 /* Handle a "flatten" attribute. */
667
668 static tree
d_handle_flatten_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)669 d_handle_flatten_attribute (tree *node, tree name,
670 tree args ATTRIBUTE_UNUSED,
671 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
672 {
673 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
674
675 if (t->ty != Tfunction)
676 {
677 warning (OPT_Wattributes, "%qE attribute ignored", name);
678 *no_add_attrs = true;
679 }
680
681 return NULL_TREE;
682 }
683
684 /* Handle a "target" attribute. */
685
686 static tree
d_handle_target_attribute(tree * node,tree name,tree args,int flags,bool * no_add_attrs)687 d_handle_target_attribute (tree *node, tree name, tree args, int flags,
688 bool *no_add_attrs)
689 {
690 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
691
692 /* Ensure we have a function type. */
693 if (t->ty != Tfunction)
694 {
695 warning (OPT_Wattributes, "%qE attribute ignored", name);
696 *no_add_attrs = true;
697 }
698 else if (! targetm.target_option.valid_attribute_p (*node, name, args, flags))
699 *no_add_attrs = true;
700
701 return NULL_TREE;
702 }
703
704 /* Handle a "noclone" attribute. */
705
706 static tree
d_handle_noclone_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)707 d_handle_noclone_attribute (tree *node, tree name,
708 tree ARG_UNUSED (args),
709 int ARG_UNUSED (flags),
710 bool *no_add_attrs)
711 {
712 Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
713
714 if (t->ty == Tfunction)
715 {
716 tree attributes = DECL_ATTRIBUTES (*node);
717
718 /* Push attribute noclone. */
719 if (! lookup_attribute ("noclone", attributes))
720 DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("noclone"),
721 NULL_TREE, attributes);
722 }
723 else
724 {
725 warning (OPT_Wattributes, "%qE attribute ignored", name);
726 *no_add_attrs = true;
727 }
728
729 return NULL_TREE;
730 }
731
732 /* Handle a "section" attribute; arguments as in
733 struct attribute_spec.handler. */
734
735 static tree
d_handle_section_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs)736 d_handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
737 int ARG_UNUSED (flags), bool *no_add_attrs)
738 {
739 tree decl = *node;
740
741 if (targetm_common.have_named_sections)
742 {
743 if (VAR_OR_FUNCTION_DECL_P (decl)
744 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
745 {
746 if (VAR_P (decl)
747 && current_function_decl != NULL_TREE
748 && !TREE_STATIC (decl))
749 {
750 error_at (DECL_SOURCE_LOCATION (decl),
751 "section attribute cannot be specified for "
752 "local variables");
753 *no_add_attrs = true;
754 }
755
756 /* The decl may have already been given a section attribute
757 from a previous declaration. Ensure they match. */
758 else if (DECL_SECTION_NAME (decl) != NULL
759 && strcmp (DECL_SECTION_NAME (decl),
760 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
761 {
762 error ("section of %q+D conflicts with previous declaration",
763 *node);
764 *no_add_attrs = true;
765 }
766 else if (VAR_P (decl)
767 && !targetm.have_tls && targetm.emutls.tmpl_section
768 && DECL_THREAD_LOCAL_P (decl))
769 {
770 error ("section of %q+D cannot be overridden", *node);
771 *no_add_attrs = true;
772 }
773 else
774 set_decl_section_name (decl,
775 TREE_STRING_POINTER (TREE_VALUE (args)));
776 }
777 else
778 {
779 error ("section attribute not allowed for %q+D", *node);
780 *no_add_attrs = true;
781 }
782 }
783 else
784 {
785 error_at (DECL_SOURCE_LOCATION (*node),
786 "section attributes are not supported for this target");
787 *no_add_attrs = true;
788 }
789
790 return NULL_TREE;
791 }
792
793 /* Handle an "alias" attribute; arguments as in
794 struct attribute_spec.handler. */
795
796 static tree
d_handle_alias_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs ATTRIBUTE_UNUSED)797 d_handle_alias_attribute (tree *node, tree ARG_UNUSED (name),
798 tree args, int ARG_UNUSED (flags),
799 bool *no_add_attrs ATTRIBUTE_UNUSED)
800 {
801 tree decl = *node;
802
803 if (TREE_CODE (decl) != FUNCTION_DECL
804 && TREE_CODE (decl) != VAR_DECL)
805 {
806 warning (OPT_Wattributes, "%qE attribute ignored", name);
807 *no_add_attrs = true;
808 return NULL_TREE;
809 }
810 else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
811 || (TREE_CODE (decl) != FUNCTION_DECL
812 && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
813 /* A static variable declaration is always a tentative definition,
814 but the alias is a non-tentative definition which overrides. */
815 || (TREE_CODE (decl) != FUNCTION_DECL
816 && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
817 {
818 error ("%q+D defined both normally and as %qE attribute", decl, name);
819 *no_add_attrs = true;
820 return NULL_TREE;
821 }
822 else if (decl_function_context (decl))
823 {
824 error ("%q+D alias functions must be global", name);
825 *no_add_attrs = true;
826 return NULL_TREE;
827 }
828 else
829 {
830 tree id;
831
832 id = TREE_VALUE (args);
833 if (TREE_CODE (id) != STRING_CST)
834 {
835 error ("attribute %qE argument not a string", name);
836 *no_add_attrs = true;
837 return NULL_TREE;
838 }
839 id = get_identifier (TREE_STRING_POINTER (id));
840 /* This counts as a use of the object pointed to. */
841 TREE_USED (id) = 1;
842
843 if (TREE_CODE (decl) == FUNCTION_DECL)
844 DECL_INITIAL (decl) = error_mark_node;
845 else
846 TREE_STATIC (decl) = 1;
847
848 return NULL_TREE;
849 }
850 }
851
852 /* Handle a "weak" attribute; arguments as in
853 struct attribute_spec.handler. */
854
855 static tree
d_handle_weak_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))856 d_handle_weak_attribute (tree *node, tree name,
857 tree ARG_UNUSED (args),
858 int ARG_UNUSED (flags),
859 bool * ARG_UNUSED (no_add_attrs))
860 {
861 if (TREE_CODE (*node) == FUNCTION_DECL
862 && DECL_DECLARED_INLINE_P (*node))
863 {
864 warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
865 *no_add_attrs = true;
866 }
867 else if (VAR_OR_FUNCTION_DECL_P (*node))
868 {
869 struct symtab_node *n = symtab_node::get (*node);
870 if (n && n->refuse_visibility_changes)
871 error ("%q+D declared weak after being used", *node);
872 declare_weak (*node);
873 }
874 else
875 warning (OPT_Wattributes, "%qE attribute ignored", name);
876
877 return NULL_TREE;
878 }
879
880