Home | History | Annotate | Line # | Download | only in d
d-attribs.cc revision 1.1.1.1
      1 /* d-attribs.c -- D attributes handling.
      2    Copyright (C) 2015-2019 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/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.  */
     43 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
     44 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
     45 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
     46 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
     47 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
     48 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
     49 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
     50 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
     51 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
     52 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
     53 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
     54 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
     55 
     56 /* D attribute handlers for user defined attributes.  */
     57 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
     58 static tree d_handle_forceinline_attribute (tree *, tree, tree, int, bool *);
     59 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
     60 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
     61 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
     62 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
     63 static tree d_handle_alias_attribute (tree *, tree, tree, int, bool *);
     64 static 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.  */
     71 static 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 
     80 static 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 
     86 static 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 
     94 static 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 
    100 static 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.  */
    114 const 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.  */
    144 const 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 
    169 tree
    170 insert_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 
    185 tree
    186 insert_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 
    202 static bool
    203 uda_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 
    234 tree
    235 build_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 
    324 static tree
    325 handle_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 
    348 static tree
    349 handle_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 
    370 static tree
    371 handle_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 
    394 tree
    395 handle_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 
    408 static tree
    409 handle_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 
    421 static tree
    422 handle_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 
    434 static bool
    435 get_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 
    447 static tree
    448 handle_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 
    499 static tree
    500 handle_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 
    511 static tree
    512 handle_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 
    527 static tree
    528 handle_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 
    541 static tree
    542 handle_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 
    557 tree
    558 handle_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 
    572 static tree
    573 d_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 
    592 static tree
    593 d_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 
    624 static tree
    625 d_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 
    642 static tree
    643 d_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 
    662 static tree
    663 d_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 
    691 static tree
    692 d_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 
    752 static tree
    753 d_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 
    811 static tree
    812 d_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 
    836