Home | History | Annotate | Line # | Download | only in d
d-attribs.cc revision 1.1.1.2
      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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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