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