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