Home | History | Annotate | Line # | Download | only in d
      1 /* d-attribs.c -- D attributes handling.
      2    Copyright (C) 2015-2022 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/expression.h"
     28 #include "dmd/module.h"
     29 #include "dmd/mtype.h"
     30 #include "dmd/template.h"
     31 
     32 #include "tree.h"
     33 #include "diagnostic.h"
     34 #include "tm.h"
     35 #include "cgraph.h"
     36 #include "toplev.h"
     37 #include "target.h"
     38 #include "common/common-target.h"
     39 #include "stringpool.h"
     40 #include "attribs.h"
     41 #include "varasm.h"
     42 #include "fold-const.h"
     43 #include "opts.h"
     44 
     45 #include "d-tree.h"
     46 
     47 
     48 /* Internal attribute handlers for built-in functions.  */
     49 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
     50 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
     51 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
     52 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
     53 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
     54 static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
     55 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
     56 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
     57 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
     58 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
     59 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
     60 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
     61 
     62 /* D attribute handlers for user defined attributes.  */
     63 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
     64 static tree d_handle_always_inline_attribute (tree *, tree, tree, int, bool *);
     65 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
     66 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
     67 static tree d_handle_target_clones_attribute (tree *, tree, tree, int, bool *);
     68 static tree d_handle_optimize_attribute (tree *, tree, tree, int, bool *);
     69 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
     70 static tree d_handle_noicf_attribute (tree *, tree, tree, int, bool *);
     71 static tree d_handle_noipa_attribute (tree *, tree, tree, int, bool *);
     72 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
     73 static tree d_handle_symver_attribute (tree *, tree, tree, int, bool *);
     74 static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ;
     75 static tree d_handle_noplt_attribute (tree *, tree, tree, int, bool *) ;
     76 static tree d_handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
     77 static tree d_handle_cold_attribute (tree *, tree, tree, int, bool *);
     78 static tree d_handle_restrict_attribute (tree *, tree, tree, int, bool *);
     79 static tree d_handle_used_attribute (tree *, tree, tree, int, bool *);
     80 
     81 /* Helper to define attribute exclusions.  */
     82 #define ATTR_EXCL(name, function, type, variable)	\
     83   { name, function, type, variable }
     84 
     85 /* Define attributes that are mutually exclusive with one another.  */
     86 static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
     87 {
     88   ATTR_EXCL ("alloc_size", true, true, true),
     89   ATTR_EXCL ("const", true, true, true),
     90   ATTR_EXCL ("malloc", true, true, true),
     91   ATTR_EXCL ("pure", true, true, true),
     92   ATTR_EXCL ("returns_twice", true, true, true),
     93   ATTR_EXCL (NULL, false, false, false),
     94 };
     95 
     96 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
     97 {
     98   ATTR_EXCL ("noreturn", true, true, true),
     99   ATTR_EXCL (NULL, false, false, false),
    100 };
    101 
    102 static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
    103 {
    104   ATTR_EXCL ("alloc_size", true, true, true),
    105   ATTR_EXCL ("const", true, true, true),
    106   ATTR_EXCL ("noreturn", true, true, true),
    107   ATTR_EXCL ("pure", true, true, true),
    108   ATTR_EXCL (NULL, false, false, false)
    109 };
    110 
    111 static const struct attribute_spec::exclusions attr_inline_exclusions[] =
    112 {
    113   ATTR_EXCL ("noinline", true, true, true),
    114   ATTR_EXCL ("target_clones", true, true, true),
    115   ATTR_EXCL (NULL, false, false, false),
    116 };
    117 
    118 static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
    119 {
    120   ATTR_EXCL ("always_inline", true, true, true),
    121   ATTR_EXCL (NULL, false, false, false),
    122 };
    123 
    124 static const struct attribute_spec::exclusions attr_target_exclusions[] =
    125 {
    126   ATTR_EXCL ("target_clones", true, true, true),
    127   ATTR_EXCL (NULL, false, false, false),
    128 };
    129 
    130 static const struct attribute_spec::exclusions attr_target_clones_exclusions[] =
    131 {
    132   ATTR_EXCL ("always_inline", true, true, true),
    133   ATTR_EXCL ("target", true, true, true),
    134   ATTR_EXCL (NULL, false, false, false),
    135 };
    136 
    137 static const struct attribute_spec::exclusions attr_alloc_exclusions[] =
    138 {
    139   ATTR_EXCL ("const", true, true, true),
    140   ATTR_EXCL ("noreturn", true, true, true),
    141   ATTR_EXCL ("pure", true, true, true),
    142   ATTR_EXCL (NULL, false, false, false),
    143 };
    144 
    145 extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] =
    146 {
    147   ATTR_EXCL ("cold", true, true, true),
    148   ATTR_EXCL ("hot", true, true, true),
    149   ATTR_EXCL (NULL, false, false, false)
    150 };
    151 
    152 /* Helper to define an attribute.  */
    153 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
    154 		  affects_type_identity, handler, exclude)		   \
    155   { name, min_len, max_len, decl_req, type_req, fn_type_req,		   \
    156     affects_type_identity, handler, exclude }
    157 
    158 /* Table of machine-independent attributes.
    159    For internal use (marking of built-ins) only.  */
    160 const attribute_spec d_langhook_common_attribute_table[] =
    161 {
    162   ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
    163 	     handle_noreturn_attribute, attr_noreturn_exclusions),
    164   ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
    165 	     handle_leaf_attribute, NULL),
    166   ATTR_SPEC ("const", 0, 0, true, false, false, false,
    167 	     handle_const_attribute, attr_const_pure_exclusions),
    168   ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
    169 	     handle_malloc_attribute, NULL),
    170   ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
    171 	     handle_returns_twice_attribute, attr_returns_twice_exclusions),
    172   ATTR_SPEC ("pure", 0, 0, true, false, false, false,
    173 	     handle_pure_attribute, attr_const_pure_exclusions),
    174   ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
    175 	     handle_nonnull_attribute, NULL),
    176   ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
    177 	     handle_nothrow_attribute, NULL),
    178   ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
    179 	     handle_transaction_pure_attribute, NULL),
    180   ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
    181 	     handle_novops_attribute, NULL),
    182   ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
    183 	     handle_type_generic_attribute, NULL),
    184   ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
    185 	     handle_fnspec_attribute, NULL),
    186   ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
    187 };
    188 
    189 /* Table of D language attributes exposed by `gcc.attribute' UDAs.  */
    190 const attribute_spec d_langhook_attribute_table[] =
    191 {
    192   ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
    193 	     d_handle_noinline_attribute, attr_noinline_exclusions),
    194   ATTR_SPEC ("always_inline", 0, 0, true,  false, false, false,
    195 	     d_handle_always_inline_attribute, attr_inline_exclusions),
    196   ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
    197 	     d_handle_flatten_attribute, NULL),
    198   ATTR_SPEC ("target", 1, -1, true, false, false, false,
    199 	     d_handle_target_attribute, attr_target_exclusions),
    200   ATTR_SPEC ("target_clones", 1, -1, true, false, false, false,
    201 	     d_handle_target_clones_attribute, attr_target_clones_exclusions),
    202   ATTR_SPEC ("optimize", 1, -1, true, false, false, false,
    203 	     d_handle_optimize_attribute, NULL),
    204   ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
    205 	     d_handle_noclone_attribute, NULL),
    206   ATTR_SPEC ("no_icf", 0, 0, true, false, false, false,
    207 	     d_handle_noicf_attribute, NULL),
    208   ATTR_SPEC ("noipa", 0, 0, true, false, false, false,
    209 	     d_handle_noipa_attribute, NULL),
    210   ATTR_SPEC ("section", 1, 1, true, false, false, false,
    211 	     d_handle_section_attribute, NULL),
    212   ATTR_SPEC ("symver", 1, -1, true, false, false, false,
    213 	     d_handle_symver_attribute, NULL),
    214   ATTR_SPEC ("weak", 0, 0, true, false, false, false,
    215 	     d_handle_weak_attribute, NULL),
    216   ATTR_SPEC ("noplt", 0, 0, true, false, false, false,
    217 	     d_handle_noplt_attribute, NULL),
    218   ATTR_SPEC ("alloc_size", 1, 3, false, true, true, false,
    219 	     d_handle_alloc_size_attribute, attr_alloc_exclusions),
    220   ATTR_SPEC ("cold", 0, 0, true, false, false, false,
    221 	     d_handle_cold_attribute, attr_cold_hot_exclusions),
    222   ATTR_SPEC ("restrict", 0, 0, true, false, false, false,
    223 	     d_handle_restrict_attribute, NULL),
    224   ATTR_SPEC ("used", 0, 0, true, false, false, false,
    225 	     d_handle_used_attribute, NULL),
    226   ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
    227 };
    228 
    229 
    230 /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
    231    Returns a new variant of the original type declaration.  */
    232 
    233 tree
    234 insert_type_attribute (tree type, const char *attrname, tree value)
    235 {
    236   tree ident = get_identifier (attrname);
    237 
    238   if (value)
    239     value = tree_cons (NULL_TREE, value, NULL_TREE);
    240 
    241   tree attribs = merge_attributes (TYPE_ATTRIBUTES (type),
    242 				   tree_cons (ident, value, NULL_TREE));
    243 
    244   return build_type_attribute_variant (type, attribs);
    245 }
    246 
    247 /* Insert the decl attribute ATTRNAME with value VALUE into DECL.  */
    248 
    249 tree
    250 insert_decl_attribute (tree decl, const char *attrname, tree value)
    251 {
    252   tree ident = get_identifier (attrname);
    253 
    254   if (value)
    255     value = tree_cons (NULL_TREE, value, NULL_TREE);
    256 
    257   tree attribs = merge_attributes (DECL_ATTRIBUTES (decl),
    258 				   tree_cons (ident, value, NULL_TREE));
    259 
    260   return build_decl_attribute_variant (decl, attribs);
    261 }
    262 
    263 /* Returns TRUE if NAME is an attribute recognized as being handled by
    264    the `gcc.attribute' module.  */
    265 
    266 static bool
    267 uda_attribute_p (const char *name)
    268 {
    269   tree ident = get_identifier (name);
    270 
    271   /* Search both our language, and target attribute tables.
    272      Common and format attributes are kept internal.  */
    273   for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
    274     {
    275       if (get_identifier (p->name) == ident)
    276 	return true;
    277     }
    278 
    279   if (targetm.attribute_table)
    280     {
    281       for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
    282 	{
    283 	  if (get_identifier (p->name) == ident)
    284 	    return true;
    285 	}
    286     }
    287 
    288   return false;
    289 }
    290 
    291 /* [attribute/uda]
    292 
    293    User Defined Attributes (UDA) are compile time expressions that can be
    294    attached to a declaration.  These attributes can then be queried, extracted,
    295    and manipulated at compile-time.  There is no run-time component to them.
    296 
    297    Expand and merge all UDAs found in the EATTRS list that are of type
    298    `gcc.attribute.Attribute'.  This symbol is internally recognized by the
    299    compiler and maps them to their equivalent GCC attribute.  */
    300 
    301 static tree
    302 build_attributes (Expressions *eattrs)
    303 {
    304   if (!eattrs)
    305     return NULL_TREE;
    306 
    307   expandTuples (eattrs);
    308 
    309   tree attribs = NULL_TREE;
    310 
    311   for (size_t i = 0; i < eattrs->length; i++)
    312     {
    313       Expression *attr = (*eattrs)[i];
    314       Dsymbol *sym = attr->type->toDsymbol (0);
    315 
    316       if (!sym)
    317 	{
    318 	  /* If attribute is a template symbol, perhaps arguments were not
    319 	     supplied, so warn about attribute having no effect.  */
    320 	  if (TemplateExp *te = attr->isTemplateExp ())
    321 	    {
    322 	      if (!te->td || !te->td->onemember)
    323 		continue;
    324 
    325 	      sym = te->td->onemember;
    326 	    }
    327 	  else
    328 	    continue;
    329 	}
    330 
    331       /* Attribute symbol must come from the `gcc.attribute' module.  */
    332       Dsymbol *mod = sym->getModule ();
    333       if (!(strcmp (mod->toChars (), "attributes") == 0
    334 	    && mod->parent != NULL
    335 	    && strcmp (mod->parent->toChars (), "gcc") == 0
    336 	    && !mod->parent->parent))
    337 	continue;
    338 
    339       /* Get the result of the attribute if it hasn't already been folded.  */
    340       if (attr->op == EXP::call)
    341 	attr = attr->ctfeInterpret ();
    342 
    343       if (attr->op != EXP::structLiteral)
    344 	{
    345 	  warning_at (make_location_t (attr->loc), OPT_Wattributes,
    346 		      "%qE attribute has no effect",
    347 		      get_identifier (sym->toChars ()));
    348 	  continue;
    349 	}
    350 
    351       /* Should now have a struct `Attribute("attrib", "value", ...)'
    352 	 initializer list.  */
    353       Expressions *elems = attr->isStructLiteralExp ()->elements;
    354       Expression *e0 = (*elems)[0];
    355 
    356       if (e0->op != EXP::string_)
    357 	{
    358 	  warning_at (make_location_t (attr->loc), OPT_Wattributes,
    359 		      "unknown attribute %qs", e0->toChars());
    360 	  continue;
    361 	}
    362 
    363       StringExp *se = e0->toStringExp ();
    364       gcc_assert (se->sz == 1);
    365 
    366       /* Empty string attribute, just ignore it.  */
    367       if (se->len == 0)
    368 	continue;
    369 
    370       /* Check if the attribute is recognized and handled.
    371 	 Done here to report the diagnostic at the right location.  */
    372       const char *name = (const char *)(se->len ? se->string : "");
    373       if (!uda_attribute_p (name))
    374 	{
    375 	  warning_at (make_location_t (attr->loc), OPT_Wattributes,
    376 		      "unknown attribute %qs", name);
    377 	  continue;
    378 	}
    379 
    380       /* Chain all attribute arguments together.  */
    381       tree args = NULL_TREE;
    382 
    383       for (size_t j = 1; j < elems->length; j++)
    384 	{
    385 	  Expression *e = (*elems)[j];
    386 	  /* Stop after the first `void' argument.  */
    387 	  if (e == NULL)
    388 	    break;
    389 
    390 	  StringExp *s = e->isStringExp ();
    391 	  tree t;
    392 	  if (s != NULL && s->sz == 1)
    393 	    {
    394 	      const char *string = (const char *)(s->len ? s->string : "");
    395 	      t = build_string (s->len, string);
    396 	    }
    397 	  else
    398 	    t = build_expr (e);
    399 
    400 	  args = chainon (args, build_tree_list (0, t));
    401 	}
    402 
    403       tree list = build_tree_list (get_identifier (name), args);
    404       attribs = chainon (attribs, list);
    405     }
    406 
    407   return attribs;
    408 }
    409 
    410 /* If any GCC attributes are found in the declaration SYM, apply them to the
    411    type or decl NODE.  */
    412 
    413 void
    414 apply_user_attributes (Dsymbol *sym, tree node)
    415 {
    416   if (!sym->userAttribDecl)
    417     {
    418       if (DECL_P (node) && DECL_ATTRIBUTES (node) != NULL)
    419 	decl_attributes (&node, DECL_ATTRIBUTES (node), 0);
    420 
    421       return;
    422     }
    423 
    424   location_t saved_location = input_location;
    425   input_location = make_location_t (sym->loc);
    426 
    427   Expressions *attrs = sym->userAttribDecl->getAttributes ();
    428   decl_attributes (&node, build_attributes (attrs),
    429 		   TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0);
    430 
    431   input_location = saved_location;
    432 }
    433 
    434 /* Built-in attribute handlers.
    435    These functions take the arguments:
    436    (tree *node, tree name, tree args, int flags, bool *no_add_attrs)  */
    437 
    438 /* Handle a "noreturn" attribute; arguments as in
    439    struct attribute_spec.handler.  */
    440 
    441 static tree
    442 handle_noreturn_attribute (tree *node, tree, tree, int, bool *)
    443 {
    444   tree type = TREE_TYPE (*node);
    445 
    446   if (TREE_CODE (*node) == FUNCTION_DECL)
    447     TREE_THIS_VOLATILE (*node) = 1;
    448   else if (TREE_CODE (type) == POINTER_TYPE
    449 	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
    450     TREE_TYPE (*node)
    451       = build_pointer_type
    452 	(build_type_variant (TREE_TYPE (type),
    453 			     TYPE_READONLY (TREE_TYPE (type)), 1));
    454   else
    455     gcc_unreachable ();
    456 
    457   return NULL_TREE;
    458 }
    459 
    460 /* Handle a "leaf" attribute; arguments as in
    461    struct attribute_spec.handler.  */
    462 
    463 static tree
    464 handle_leaf_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
    465 {
    466   if (TREE_CODE (*node) != FUNCTION_DECL)
    467     {
    468       warning (OPT_Wattributes, "%qE attribute ignored", name);
    469       *no_add_attrs = true;
    470     }
    471   if (!TREE_PUBLIC (*node))
    472     {
    473       warning (OPT_Wattributes, "%qE attribute has no effect", name);
    474       *no_add_attrs = true;
    475     }
    476 
    477   return NULL_TREE;
    478 }
    479 
    480 /* Handle a "const" attribute; arguments as in
    481    struct attribute_spec.handler.  */
    482 
    483 static tree
    484 handle_const_attribute (tree *node, tree, tree, int, bool *)
    485 {
    486   tree type = TREE_TYPE (*node);
    487 
    488   if (TREE_CODE (*node) == FUNCTION_DECL)
    489     TREE_READONLY (*node) = 1;
    490   else if (TREE_CODE (type) == POINTER_TYPE
    491 	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
    492     TREE_TYPE (*node)
    493       = build_pointer_type
    494 	(build_type_variant (TREE_TYPE (type), 1,
    495 			     TREE_THIS_VOLATILE (TREE_TYPE (type))));
    496   else
    497     gcc_unreachable ();
    498 
    499   return NULL_TREE;
    500 }
    501 
    502 /* Handle a "malloc" attribute; arguments as in
    503    struct attribute_spec.handler.  */
    504 
    505 tree
    506 handle_malloc_attribute (tree *node, tree, tree, int, bool *)
    507 {
    508   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
    509 	      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
    510   DECL_IS_MALLOC (*node) = 1;
    511   return NULL_TREE;
    512 }
    513 
    514 /* Handle a "pure" attribute; arguments as in
    515    struct attribute_spec.handler.  */
    516 
    517 static tree
    518 handle_pure_attribute (tree *node, tree, tree, int, bool *)
    519 {
    520   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    521   DECL_PURE_P (*node) = 1;
    522   return NULL_TREE;
    523 }
    524 
    525 /* Handle a "no vops" attribute; arguments as in
    526    struct attribute_spec.handler.  */
    527 
    528 static tree
    529 handle_novops_attribute (tree *node, tree, tree, int, bool *)
    530 {
    531   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    532   DECL_IS_NOVOPS (*node) = 1;
    533   return NULL_TREE;
    534 }
    535 
    536 /* Helper for nonnull attribute handling; fetch the operand number
    537    from the attribute argument list.  */
    538 
    539 static bool
    540 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
    541 {
    542   /* Verify the arg number is a constant.  */
    543   if (!tree_fits_uhwi_p (arg_num_expr))
    544     return false;
    545 
    546   *valp = TREE_INT_CST_LOW (arg_num_expr);
    547   return true;
    548 }
    549 
    550 /* Handle the "nonnull" attribute.  */
    551 
    552 static tree
    553 handle_nonnull_attribute (tree *node, tree, tree args, int, bool *)
    554 {
    555   tree type = *node;
    556 
    557   /* If no arguments are specified, all pointer arguments should be
    558      non-null.  Verify a full prototype is given so that the arguments
    559      will have the correct types when we actually check them later.
    560      Avoid diagnosing type-generic built-ins since those have no
    561      prototype.  */
    562   if (!args)
    563     {
    564       gcc_assert (prototype_p (type)
    565 		  || !TYPE_ATTRIBUTES (type)
    566 		  || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
    567 
    568       return NULL_TREE;
    569     }
    570 
    571   /* Argument list specified.  Verify that each argument number references
    572      a pointer argument.  */
    573   for (; args; args = TREE_CHAIN (args))
    574     {
    575       tree argument;
    576       unsigned HOST_WIDE_INT arg_num = 0, ck_num;
    577 
    578       if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
    579 	gcc_unreachable ();
    580 
    581       argument = TYPE_ARG_TYPES (type);
    582       if (argument)
    583 	{
    584 	  for (ck_num = 1; ; ck_num++)
    585 	    {
    586 	      if (!argument || ck_num == arg_num)
    587 		break;
    588 	      argument = TREE_CHAIN (argument);
    589 	    }
    590 
    591 	  gcc_assert (argument
    592 		      && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
    593 	}
    594     }
    595 
    596   return NULL_TREE;
    597 }
    598 
    599 /* Handle a "nothrow" attribute; arguments as in
    600    struct attribute_spec.handler.  */
    601 
    602 static tree
    603 handle_nothrow_attribute (tree *node, tree, tree, int, bool *)
    604 {
    605   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    606   TREE_NOTHROW (*node) = 1;
    607   return NULL_TREE;
    608 }
    609 
    610 /* Handle a "type generic" attribute; arguments as in
    611    struct attribute_spec.handler.  */
    612 
    613 static tree
    614 handle_type_generic_attribute (tree *node, tree, tree, int, bool *)
    615 {
    616   /* Ensure we have a function type.  */
    617   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
    618 
    619   /* Ensure we have a variadic function.  */
    620   gcc_assert (!prototype_p (*node) || stdarg_p (*node));
    621 
    622   return NULL_TREE;
    623 }
    624 
    625 /* Handle a "transaction_pure" attribute; arguments as in
    626    struct attribute_spec.handler.  */
    627 
    628 static tree
    629 handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *)
    630 {
    631   /* Ensure we have a function type.  */
    632   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
    633 
    634   return NULL_TREE;
    635 }
    636 
    637 /* Handle a "returns_twice" attribute; arguments as in
    638    struct attribute_spec.handler.  */
    639 
    640 static tree
    641 handle_returns_twice_attribute (tree *node, tree, tree, int, bool *)
    642 {
    643   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    644 
    645   DECL_IS_RETURNS_TWICE (*node) = 1;
    646 
    647   return NULL_TREE;
    648 }
    649 
    650 /* Handle a "fn spec" attribute; arguments as in
    651    struct attribute_spec.handler.  */
    652 
    653 tree
    654 handle_fnspec_attribute (tree *, tree, tree args, int, bool *)
    655 {
    656   gcc_assert (args
    657 	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
    658 	      && !TREE_CHAIN (args));
    659   return NULL_TREE;
    660 }
    661 
    662 /* Language specific attribute handlers.
    663    These functions take the arguments:
    664    (tree *node, tree name, tree args, int flags, bool *no_add_attrs)  */
    665 
    666 /* Handle a "noinline" attribute; arguments as in
    667    struct attribute_spec.handler.  */
    668 
    669 static tree
    670 d_handle_noinline_attribute (tree *node, tree name, tree, int,
    671 			     bool *no_add_attrs)
    672 {
    673   if (TREE_CODE (*node) == FUNCTION_DECL)
    674     DECL_UNINLINABLE (*node) = 1;
    675   else
    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 "always_inline" attribute; arguments as in
    685    struct attribute_spec.handler.  */
    686 
    687 static tree
    688 d_handle_always_inline_attribute (tree *node, tree name, tree, int,
    689 				  bool *no_add_attrs)
    690 {
    691   if (TREE_CODE (*node) == FUNCTION_DECL)
    692     {
    693       DECL_DECLARED_INLINE_P (*node) = 1;
    694       DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
    695     }
    696   else
    697     {
    698       warning (OPT_Wattributes, "%qE attribute ignored", name);
    699       *no_add_attrs = true;
    700     }
    701 
    702   return NULL_TREE;
    703 }
    704 
    705 /* Handle a "flatten" attribute; arguments as in
    706    struct attribute_spec.handler.  */
    707 
    708 static tree
    709 d_handle_flatten_attribute (tree *node, tree name, tree, int,
    710 			    bool *no_add_attrs)
    711 {
    712   if (TREE_CODE (*node) != FUNCTION_DECL)
    713     {
    714       warning (OPT_Wattributes, "%qE attribute ignored", name);
    715       *no_add_attrs = true;
    716     }
    717 
    718   return NULL_TREE;
    719 }
    720 
    721 /* Handle a "target" attribute; arguments as in
    722    struct attribute_spec.handler.  */
    723 
    724 static tree
    725 d_handle_target_attribute (tree *node, tree name, tree args, int flags,
    726 			   bool *no_add_attrs)
    727 {
    728   /* Ensure we have a function type.  */
    729   if (TREE_CODE (*node) != FUNCTION_DECL)
    730     {
    731       warning (OPT_Wattributes, "%qE attribute ignored", name);
    732       *no_add_attrs = true;
    733     }
    734   else if (!targetm.target_option.valid_attribute_p (*node, name, args, flags))
    735     *no_add_attrs = true;
    736 
    737   /* Check that there's no empty string in values of the attribute.  */
    738   for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t))
    739     {
    740       tree value = TREE_VALUE (t);
    741       if (TREE_CODE (value) != STRING_CST
    742 	  || (TREE_STRING_LENGTH (value) != 0
    743 	      && TREE_STRING_POINTER (value)[0] != '\0'))
    744 	continue;
    745 
    746       warning (OPT_Wattributes, "empty string in attribute %<target%>");
    747       *no_add_attrs = true;
    748     }
    749 
    750   return NULL_TREE;
    751 }
    752 
    753 /* Handle a "target_clones" attribute; arguments as in
    754    struct attribute_spec.handler.  */
    755 
    756 static tree
    757 d_handle_target_clones_attribute (tree *node, tree name, tree, int,
    758 				  bool *no_add_attrs)
    759 {
    760   /* Ensure we have a function type.  */
    761   if (TREE_CODE (*node) != FUNCTION_DECL)
    762     {
    763       warning (OPT_Wattributes, "%qE attribute ignored", name);
    764       *no_add_attrs = true;
    765     }
    766   else
    767     {
    768       /* Do not inline functions with multiple clone targets.  */
    769       DECL_UNINLINABLE (*node) = 1;
    770     }
    771 
    772   return NULL_TREE;
    773 }
    774 
    775 /* Arguments being collected for optimization.  */
    776 static GTY(()) vec <const char *, va_gc> *optimize_args;
    777 
    778 /* Inner function to convert a TREE_LIST to argv string to parse the optimize
    779    options in ARGS.  */
    780 
    781 static bool
    782 parse_optimize_options (tree args)
    783 {
    784   bool ret = true;
    785 
    786   /* Build up argv vector.  Just in case the string is stored away, use garbage
    787      collected strings.  */
    788   vec_safe_truncate (optimize_args, 0);
    789   vec_safe_push (optimize_args, (const char *) NULL);
    790 
    791   for (tree ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
    792     {
    793       tree value = TREE_VALUE (ap);
    794 
    795       if (TREE_CODE (value) == INTEGER_CST)
    796 	{
    797 	  char buffer[20];
    798 	  sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
    799 	  vec_safe_push (optimize_args, ggc_strdup (buffer));
    800 	}
    801       else if (TREE_CODE (value) == STRING_CST)
    802 	{
    803 	  size_t len = TREE_STRING_LENGTH (value);
    804 	  const char *p = TREE_STRING_POINTER (value);
    805 
    806 	  /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
    807 	     options.  */
    808 	  if (*p == '-' && p[1] != 'O' && p[1] != 'f')
    809 	    {
    810 	      ret = false;
    811 	      warning (OPT_Wattributes,
    812 		       "bad option %qs to attribute %<optimize%>", p);
    813 	      continue;
    814 	    }
    815 
    816 	  /* Can't use GC memory here.  */
    817 	  char *q = XOBNEWVEC (&opts_obstack, char, len + 3);
    818 	  char *r = q;
    819 
    820 	  if (*p != '-')
    821 	    {
    822 	      *r++ = '-';
    823 
    824 	      /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
    825 		 itself is -Os, and any other switch begins with a -f.  */
    826 	      if ((*p >= '0' && *p <= '9') || (p[0] == 's' && p[1] == '\0'))
    827 		*r++ = 'O';
    828 	      else if (*p != 'O')
    829 		*r++ = 'f';
    830 	    }
    831 
    832 	  memcpy (r, p, len);
    833 	  r[len] = '\0';
    834 	  vec_safe_push (optimize_args, (const char *) q);
    835 	}
    836     }
    837 
    838   unsigned opt_argc = optimize_args->length ();
    839   const char **opt_argv
    840     = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
    841 
    842   for (unsigned i = 1; i < opt_argc; i++)
    843     opt_argv[i] = (*optimize_args)[i];
    844 
    845   /* Now parse the options.  */
    846   struct cl_decoded_option *decoded_options;
    847   unsigned int decoded_options_count;
    848 
    849   decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
    850 						&decoded_options,
    851 						&decoded_options_count);
    852   /* Drop non-Optimization options.  */
    853   unsigned j = 1;
    854   for (unsigned i = 1; i < decoded_options_count; ++i)
    855     {
    856       unsigned opt_index = decoded_options[i].opt_index;
    857       if (opt_index >= cl_options_count
    858 	  || ! (cl_options[opt_index].flags & CL_OPTIMIZATION))
    859 	{
    860 	  ret = false;
    861 	  warning (OPT_Wattributes,
    862 		   "bad option %qs to attribute %<optimize%>",
    863 		   decoded_options[i].orig_option_with_args_text);
    864 	  continue;
    865 	}
    866       if (i != j)
    867 	decoded_options[j] = decoded_options[i];
    868       j++;
    869     }
    870   decoded_options_count = j;
    871   /* And apply them.  */
    872   decode_options (&global_options, &global_options_set,
    873 		  decoded_options, decoded_options_count,
    874 		  input_location, global_dc, NULL);
    875 
    876   targetm.override_options_after_change();
    877 
    878   optimize_args->truncate (0);
    879   return ret;
    880 }
    881 
    882 /* Handle a "optimize" attribute; arguments as in
    883    struct attribute_spec.handler.  */
    884 
    885 static tree
    886 d_handle_optimize_attribute (tree *node, tree name, tree args, int,
    887 			     bool *no_add_attrs)
    888 {
    889   /* Ensure we have a function type.  */
    890   if (TREE_CODE (*node) != FUNCTION_DECL)
    891     {
    892       warning (OPT_Wattributes, "%qE attribute ignored", name);
    893       *no_add_attrs = true;
    894     }
    895   else
    896     {
    897       struct cl_optimization cur_opts;
    898       tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
    899 
    900       /* Save current options.  */
    901       cl_optimization_save (&cur_opts, &global_options, &global_options_set);
    902       tree prev_target_node = build_target_option_node (&global_options,
    903 							&global_options_set);
    904 
    905       /* If we previously had some optimization options, use them as the
    906 	 default.  */
    907       gcc_options *saved_global_options = NULL;
    908       if (flag_checking)
    909 	{
    910 	  saved_global_options = XNEW (gcc_options);
    911 	  *saved_global_options = global_options;
    912 	}
    913 
    914       if (old_opts)
    915 	cl_optimization_restore (&global_options, &global_options_set,
    916 				 TREE_OPTIMIZATION (old_opts));
    917 
    918       /* Parse options, and update the vector.  */
    919       parse_optimize_options (args);
    920       DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
    921 	= build_optimization_node (&global_options, &global_options_set);
    922       tree target_node = build_target_option_node (&global_options,
    923 						   &global_options_set);
    924       if (prev_target_node != target_node)
    925 	DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node;
    926 
    927       /* Restore current options.  */
    928       cl_optimization_restore (&global_options, &global_options_set,
    929 			       &cur_opts);
    930       cl_target_option_restore (&global_options, &global_options_set,
    931 				TREE_TARGET_OPTION (prev_target_node));
    932       if (saved_global_options != NULL)
    933 	{
    934 	  cl_optimization_compare (saved_global_options, &global_options);
    935 	  free (saved_global_options);
    936 	}
    937     }
    938 
    939   return NULL_TREE;
    940 }
    941 
    942 /* Handle a "noclone" attribute; arguments as in
    943    struct attribute_spec.handler.  */
    944 
    945 static tree
    946 d_handle_noclone_attribute (tree *node, tree name, tree, int,
    947 			    bool *no_add_attrs)
    948 {
    949   if (TREE_CODE (*node) != FUNCTION_DECL)
    950     {
    951       warning (OPT_Wattributes, "%qE attribute ignored", name);
    952       *no_add_attrs = true;
    953     }
    954 
    955   return NULL_TREE;
    956 }
    957 
    958 /* Handle a "no_icf" attribute; arguments as in
    959    struct attribute_spec.handler.  */
    960 
    961 static tree
    962 d_handle_noicf_attribute (tree *node, tree name, tree, int,
    963 			  bool *no_add_attrs)
    964 {
    965   if (TREE_CODE (*node) != FUNCTION_DECL)
    966     {
    967       warning (OPT_Wattributes, "%qE attribute ignored", name);
    968       *no_add_attrs = true;
    969     }
    970 
    971   return NULL_TREE;
    972 }
    973 
    974 /* Handle a "noipa" attribute; arguments as in
    975    struct attribute_spec.handler.  */
    976 
    977 static tree
    978 d_handle_noipa_attribute (tree *node, tree name, tree, int,
    979 			  bool *no_add_attrs)
    980 {
    981   if (TREE_CODE (*node) != FUNCTION_DECL)
    982     {
    983       warning (OPT_Wattributes, "%qE attribute ignored", name);
    984       *no_add_attrs = true;
    985     }
    986 
    987   return NULL_TREE;
    988 }
    989 
    990 /* Handle a "section" attribute; arguments as in
    991    struct attribute_spec.handler.  */
    992 
    993 static tree
    994 d_handle_section_attribute (tree *node, tree name, tree args, int flags,
    995 			    bool *no_add_attrs)
    996 {
    997   if (!targetm_common.have_named_sections)
    998     {
    999       error ("section attributes are not supported for this target");
   1000       *no_add_attrs = true;
   1001       return NULL_TREE;
   1002     }
   1003 
   1004   if (!VAR_OR_FUNCTION_DECL_P (*node))
   1005     {
   1006       error ("section attribute not allowed for %q+D", *node);
   1007       *no_add_attrs = true;
   1008       return NULL_TREE;
   1009     }
   1010 
   1011   if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
   1012     {
   1013       error ("section attribute argument not a string constant");
   1014       *no_add_attrs = true;
   1015       return NULL_TREE;
   1016     }
   1017 
   1018   if (VAR_P (*node)
   1019       && current_function_decl != NULL_TREE
   1020       && !TREE_STATIC (*node))
   1021     {
   1022       error ("section attribute cannot be specified for local variables");
   1023       *no_add_attrs = true;
   1024       return NULL_TREE;
   1025     }
   1026 
   1027   /* The decl may have already been given a section attribute
   1028      from a previous declaration.  Ensure they match.  */
   1029   if (DECL_SECTION_NAME (*node) != NULL
   1030       && strcmp (DECL_SECTION_NAME (*node),
   1031 		 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
   1032     {
   1033       error ("section of %q+D conflicts with previous declaration", *node);
   1034       *no_add_attrs = true;
   1035       return NULL_TREE;
   1036     }
   1037 
   1038   if (VAR_P (*node)
   1039       && !targetm.have_tls && targetm.emutls.tmpl_section
   1040       && DECL_THREAD_LOCAL_P (*node))
   1041     {
   1042       error ("section of %q+D cannot be overridden", *node);
   1043       *no_add_attrs = true;
   1044       return NULL_TREE;
   1045     }
   1046 
   1047   tree res = targetm.handle_generic_attribute (node, name, args, flags,
   1048 					       no_add_attrs);
   1049 
   1050   /* If the back end confirms the attribute can be added then continue onto
   1051      final processing.  */
   1052   if (*no_add_attrs)
   1053     return NULL_TREE;
   1054 
   1055   set_decl_section_name (*node, TREE_STRING_POINTER (TREE_VALUE (args)));
   1056   return res;
   1057 }
   1058 
   1059 /* Handle a "symver" and attribute; arguments as in
   1060    struct attribute_spec.handler.  */
   1061 
   1062 static tree
   1063 d_handle_symver_attribute (tree *node, tree, tree args, int, bool *no_add_attrs)
   1064 {
   1065   if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
   1066     {
   1067       warning (OPT_Wattributes,
   1068 	       "%<symver%> attribute only applies to functions and variables");
   1069       *no_add_attrs = true;
   1070       return NULL_TREE;
   1071     }
   1072 
   1073   if (!decl_in_symtab_p (*node))
   1074     {
   1075       warning (OPT_Wattributes,
   1076 	       "%<symver%> attribute is only applicable to symbols");
   1077       *no_add_attrs = true;
   1078       return NULL_TREE;
   1079     }
   1080 
   1081   for (; args; args = TREE_CHAIN (args))
   1082     {
   1083       tree symver = TREE_VALUE (args);
   1084       if (TREE_CODE (symver) != STRING_CST)
   1085 	{
   1086 	  error ("%<symver%> attribute argument not a string constant");
   1087 	  *no_add_attrs = true;
   1088 	  return NULL_TREE;
   1089 	}
   1090 
   1091       const char *symver_str = TREE_STRING_POINTER (symver);
   1092 
   1093       int ats = 0;
   1094       for (int n = 0; (int)n < TREE_STRING_LENGTH (symver); n++)
   1095 	if (symver_str[n] == '@')
   1096 	  ats++;
   1097 
   1098       if (ats != 1 && ats != 2)
   1099 	{
   1100 	  error ("symver attribute argument must have format %<name@nodename%>");
   1101 	  error ("%<symver%> attribute argument %qs must contain one or two "
   1102 		 "%<@%>", symver_str);
   1103 	  *no_add_attrs = true;
   1104 	  return NULL_TREE;
   1105 	}
   1106     }
   1107 
   1108   return NULL_TREE;
   1109 }
   1110 
   1111 /* Handle a "weak" attribute; arguments as in
   1112    struct attribute_spec.handler.  */
   1113 
   1114 static tree
   1115 d_handle_weak_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
   1116 {
   1117   if (TREE_CODE (*node) == FUNCTION_DECL
   1118       && DECL_DECLARED_INLINE_P (*node))
   1119     {
   1120       warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
   1121       *no_add_attrs = true;
   1122     }
   1123   else if (VAR_OR_FUNCTION_DECL_P (*node))
   1124     {
   1125       struct symtab_node *n = symtab_node::get (*node);
   1126       if (n && n->refuse_visibility_changes)
   1127 	error ("%q+D declared weak after being used", *node);
   1128       declare_weak (*node);
   1129     }
   1130   else
   1131     warning (OPT_Wattributes, "%qE attribute ignored", name);
   1132 
   1133   return NULL_TREE;
   1134 }
   1135 
   1136 /* Handle a "noplt" attribute; arguments as in
   1137    struct attribute_spec.handler.  */
   1138 
   1139 static tree
   1140 d_handle_noplt_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
   1141 {
   1142   if (TREE_CODE (*node) != FUNCTION_DECL)
   1143     {
   1144       warning (OPT_Wattributes, "%qE attribute ignored", name);
   1145       *no_add_attrs = true;
   1146     }
   1147 
   1148   return NULL_TREE;
   1149 }
   1150 
   1151 /* Verify that argument value POS at position ARGNO to attribute ATNAME applied
   1152    to function FNTYPE refers to a function parameter at position POS and is a
   1153    valid integer type.  When ZERO_BASED is true, POS is adjusted to be 1-based.
   1154    If successful, POS is returned.  Otherwise, issue appropriate warnings and
   1155    return null.  A non-zero 1-based ARGNO should be passed in by callers only
   1156    for attributes with more than one argument.  */
   1157 
   1158 static tree
   1159 positional_argument (const_tree fntype, const_tree atname, tree pos,
   1160 		     int argno, bool zero_based)
   1161 {
   1162   tree postype = TREE_TYPE (pos);
   1163 
   1164   if (pos == error_mark_node || !postype)
   1165     {
   1166       /* Only mention the positional argument number when it's non-zero.  */
   1167       if (argno < 1)
   1168 	warning (OPT_Wattributes,
   1169 		 "%qE attribute argument is invalid", atname);
   1170       else
   1171 	warning (OPT_Wattributes,
   1172 		 "%qE attribute argument %i is invalid", atname, argno);
   1173 
   1174       return NULL_TREE;
   1175     }
   1176 
   1177   if (!INTEGRAL_TYPE_P (postype))
   1178     {
   1179       /* Handle this case specially to avoid mentioning the value
   1180 	 of pointer constants in diagnostics.  Only mention
   1181 	 the positional argument number when it's non-zero.  */
   1182       if (argno < 1)
   1183 	warning (OPT_Wattributes,
   1184 		 "%qE attribute argument has type %qT",
   1185 		 atname, postype);
   1186       else
   1187 	warning (OPT_Wattributes,
   1188 		 "%qE attribute argument %i has type %qT",
   1189 		 atname, argno, postype);
   1190 
   1191       return NULL_TREE;
   1192     }
   1193 
   1194   if (TREE_CODE (pos) != INTEGER_CST)
   1195     {
   1196       /* Only mention the argument number when it's non-zero.  */
   1197       if (argno < 1)
   1198 	warning (OPT_Wattributes,
   1199 		 "%qE attribute argument value %qE is not an integer "
   1200 		 "constant",
   1201 		 atname, pos);
   1202       else
   1203 	warning (OPT_Wattributes,
   1204 		 "%qE attribute argument %i value %qE is not an integer "
   1205 		 "constant",
   1206 		 atname, argno, pos);
   1207 
   1208       return NULL_TREE;
   1209     }
   1210 
   1211   /* Validate the value of the position argument.  If 0-based, then it should
   1212      not be negative.  If 1-based, it should be greater than zero.  */
   1213   if ((zero_based && tree_int_cst_sgn (pos) < 0)
   1214       || (!zero_based && tree_int_cst_sgn (pos) < 1))
   1215     {
   1216       if (argno < 1)
   1217 	warning (OPT_Wattributes,
   1218 		 "%qE attribute argument value %qE does not refer to "
   1219 		 "a function parameter",
   1220 		 atname, pos);
   1221       else
   1222 	warning (OPT_Wattributes,
   1223 		 "%qE attribute argument %i value %qE does not refer to "
   1224 		 "a function parameter",
   1225 		 atname, argno, pos);
   1226 
   1227       return NULL_TREE;
   1228     }
   1229 
   1230   /* Adjust the value of pos to be 1-based.  */
   1231   tree adjusted_pos = (zero_based)
   1232     ? int_const_binop (PLUS_EXPR, pos, integer_one_node) : pos;
   1233 
   1234   if (!prototype_p (fntype))
   1235     return adjusted_pos;
   1236 
   1237   /* Verify that the argument position does not exceed the number
   1238      of formal arguments to the function.  */
   1239   unsigned nargs = type_num_arguments (fntype);
   1240   if (!nargs
   1241       || !tree_fits_uhwi_p (adjusted_pos)
   1242       || !IN_RANGE (tree_to_uhwi (adjusted_pos), 1, nargs))
   1243     {
   1244       if (argno < 1)
   1245 	warning (OPT_Wattributes,
   1246 		 "%qE attribute argument value %qE exceeds the number "
   1247 		 "of function parameters %u",
   1248 		 atname, pos, nargs);
   1249       else
   1250 	warning (OPT_Wattributes,
   1251 		 "%qE attribute argument %i value %qE exceeds the number "
   1252 		 "of function parameters %u",
   1253 		 atname, argno, pos, nargs);
   1254 
   1255       return NULL_TREE;
   1256     }
   1257 
   1258   /* Verify that the type of the referenced formal argument matches
   1259      the expected type.  */
   1260   unsigned HOST_WIDE_INT ipos = tree_to_uhwi (adjusted_pos);
   1261 
   1262   /* Zero was handled above.  */
   1263   gcc_assert (ipos != 0);
   1264 
   1265   if (tree argtype = type_argument_type (fntype, ipos))
   1266     {
   1267       /* Accept types that match INTEGRAL_TYPE_P except for bool.  */
   1268       if (!INTEGRAL_TYPE_P (argtype) || TREE_CODE (argtype) == BOOLEAN_TYPE)
   1269 	{
   1270 	  if (argno < 1)
   1271 	    warning (OPT_Wattributes,
   1272 		     "%qE attribute argument value %qE refers to "
   1273 		     "parameter type %qT",
   1274 		     atname, pos, argtype);
   1275 	  else
   1276 	    warning (OPT_Wattributes,
   1277 		     "%qE attribute argument %i value %qE refers to "
   1278 		     "parameter type %qT",
   1279 		     atname, argno, pos, argtype);
   1280 
   1281 	  return NULL_TREE;
   1282 	}
   1283 
   1284       return adjusted_pos;
   1285     }
   1286 
   1287   /* Argument position exceeding number of parameters was handled above.  */
   1288   gcc_unreachable ();
   1289 }
   1290 
   1291 /* Handle a "alloc_size" attribute; arguments as in
   1292    struct attribute_spec.handler.  */
   1293 
   1294 static tree
   1295 d_handle_alloc_size_attribute (tree *node, tree name, tree args, int,
   1296 			       bool *no_add_attrs)
   1297 {
   1298   tree fntype = *node;
   1299   tree rettype = TREE_TYPE (fntype);
   1300   if (!POINTER_TYPE_P (rettype))
   1301     {
   1302       warning (OPT_Wattributes,
   1303 	       "%qE attribute ignored on a function returning %qT",
   1304 	       name, rettype);
   1305       *no_add_attrs = true;
   1306       return NULL_TREE;
   1307     }
   1308 
   1309   /* The first argument SIZE_ARG is never null.  */
   1310   tree size_arg = TREE_VALUE (args);
   1311   tree next = TREE_CHAIN (args);
   1312 
   1313   /* NUM_ARG is null when the attribute includes just one argument, or is
   1314      explictly set to null if it has been left uninitialized by the caller.  */
   1315   tree num_arg = NULL_TREE;
   1316   if (next != NULL_TREE)
   1317     {
   1318       if (TREE_VALUE (next) != TYPE_MIN_VALUE (d_int_type))
   1319 	num_arg = TREE_VALUE (next);
   1320 
   1321       next = TREE_CHAIN (next);
   1322     }
   1323 
   1324   /* If ZERO_ARG is set and true, arguments positions are treated as 0-based.
   1325      Otherwise the default is 1-based.  */
   1326   bool zero_based = false;
   1327   if (next != NULL_TREE)
   1328     zero_based = integer_truep (TREE_VALUE (next));
   1329 
   1330   /* Update the argument values with the real argument position.  */
   1331   if (tree val = positional_argument (fntype, name, size_arg, num_arg ? 1 : 0,
   1332 				      zero_based))
   1333     TREE_VALUE (args) = val;
   1334   else
   1335     *no_add_attrs = true;
   1336 
   1337   if (num_arg != NULL_TREE)
   1338     {
   1339       args = TREE_CHAIN (args);
   1340       if (tree val = positional_argument (fntype, name, num_arg, 2, zero_based))
   1341 	TREE_VALUE (args) = val;
   1342       else
   1343 	*no_add_attrs = true;
   1344     }
   1345 
   1346   /* Terminate the original TREE_CHAIN in `args' to remove any remaining
   1347      D-specific `alloc_size` arguments.  */
   1348   TREE_CHAIN (args) = NULL_TREE;
   1349 
   1350   return NULL_TREE;
   1351 }
   1352 
   1353 /* Handle a "cold" and attribute; arguments as in
   1354    struct attribute_spec.handler.  */
   1355 
   1356 static tree
   1357 d_handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
   1358 {
   1359   if (TREE_CODE (*node) != FUNCTION_DECL)
   1360     {
   1361       warning (OPT_Wattributes, "%qE attribute ignored", name);
   1362       *no_add_attrs = true;
   1363     }
   1364 
   1365   return NULL_TREE;
   1366 }
   1367 
   1368 /* Handle a "restrict" attribute; arguments as in
   1369    struct attribute_spec.handler.  */
   1370 
   1371 static tree
   1372 d_handle_restrict_attribute (tree *node, tree name, tree, int,
   1373 			     bool *no_add_attrs)
   1374 {
   1375   if (TREE_CODE (*node) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (*node)))
   1376     {
   1377       TREE_TYPE (*node) = build_qualified_type (TREE_TYPE (*node),
   1378 						TYPE_QUAL_RESTRICT);
   1379     }
   1380   else
   1381     {
   1382       warning (OPT_Wattributes, "%qE attribute ignored", name);
   1383       *no_add_attrs = true;
   1384     }
   1385 
   1386   return NULL_TREE;
   1387 }
   1388 
   1389 /* Handle a "used" attribute; arguments as in
   1390    struct attribute_spec.handler.  */
   1391 
   1392 static tree
   1393 d_handle_used_attribute (tree *node, tree name, tree, int, bool *no_add_attrs)
   1394 {
   1395   if (TREE_CODE (*node) == FUNCTION_DECL
   1396       || (VAR_P (*node) && TREE_STATIC (*node))
   1397       || (TREE_CODE (*node) == TYPE_DECL))
   1398     {
   1399       TREE_USED (*node) = 1;
   1400       DECL_PRESERVE_P (*node) = 1;
   1401       if (VAR_P (*node))
   1402 	DECL_READ_P (*node) = 1;
   1403     }
   1404   else
   1405     {
   1406       warning (OPT_Wattributes, "%qE attribute ignored", name);
   1407       *no_add_attrs = true;
   1408     }
   1409 
   1410   return NULL_TREE;
   1411 }
   1412