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