Home | History | Annotate | Line # | Download | only in d
d-attribs.cc revision 1.1
      1  1.1  mrg /* d-attribs.c -- D attributes handling.
      2  1.1  mrg    Copyright (C) 2015-2019 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  mrg #include "dmd/declaration.h"
     26  1.1  mrg #include "dmd/mtype.h"
     27  1.1  mrg 
     28  1.1  mrg #include "tree.h"
     29  1.1  mrg #include "diagnostic.h"
     30  1.1  mrg #include "tm.h"
     31  1.1  mrg #include "cgraph.h"
     32  1.1  mrg #include "toplev.h"
     33  1.1  mrg #include "target.h"
     34  1.1  mrg #include "common/common-target.h"
     35  1.1  mrg #include "stringpool.h"
     36  1.1  mrg #include "attribs.h"
     37  1.1  mrg #include "varasm.h"
     38  1.1  mrg 
     39  1.1  mrg #include "d-tree.h"
     40  1.1  mrg 
     41  1.1  mrg 
     42  1.1  mrg /* Internal attribute handlers for built-in functions.  */
     43  1.1  mrg static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
     44  1.1  mrg static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
     45  1.1  mrg static tree handle_const_attribute (tree *, tree, tree, int, bool *);
     46  1.1  mrg static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
     47  1.1  mrg static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
     48  1.1  mrg static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
     49  1.1  mrg static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
     50  1.1  mrg static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
     51  1.1  mrg static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
     52  1.1  mrg static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *);
     53  1.1  mrg static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
     54  1.1  mrg static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
     55  1.1  mrg 
     56  1.1  mrg /* D attribute handlers for user defined attributes.  */
     57  1.1  mrg static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *);
     58  1.1  mrg static tree d_handle_forceinline_attribute (tree *, tree, tree, int, bool *);
     59  1.1  mrg static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *);
     60  1.1  mrg static tree d_handle_target_attribute (tree *, tree, tree, int, bool *);
     61  1.1  mrg static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *);
     62  1.1  mrg static tree d_handle_section_attribute (tree *, tree, tree, int, bool *);
     63  1.1  mrg static tree d_handle_alias_attribute (tree *, tree, tree, int, bool *);
     64  1.1  mrg static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ;
     65  1.1  mrg 
     66  1.1  mrg /* Helper to define attribute exclusions.  */
     67  1.1  mrg #define ATTR_EXCL(name, function, type, variable)	\
     68  1.1  mrg   { name, function, type, variable }
     69  1.1  mrg 
     70  1.1  mrg /* Define attributes that are mutually exclusive with one another.  */
     71  1.1  mrg static const struct attribute_spec::exclusions attr_noreturn_exclusions[] =
     72  1.1  mrg {
     73  1.1  mrg   ATTR_EXCL ("const", true, true, true),
     74  1.1  mrg   ATTR_EXCL ("malloc", true, true, true),
     75  1.1  mrg   ATTR_EXCL ("pure", true, true, true),
     76  1.1  mrg   ATTR_EXCL ("returns_twice", true, true, true),
     77  1.1  mrg   ATTR_EXCL (NULL, false, false, false),
     78  1.1  mrg };
     79  1.1  mrg 
     80  1.1  mrg static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] =
     81  1.1  mrg {
     82  1.1  mrg   ATTR_EXCL ("noreturn", true, true, true),
     83  1.1  mrg   ATTR_EXCL (NULL, false, false, false),
     84  1.1  mrg };
     85  1.1  mrg 
     86  1.1  mrg static const struct attribute_spec::exclusions attr_const_pure_exclusions[] =
     87  1.1  mrg {
     88  1.1  mrg   ATTR_EXCL ("const", true, true, true),
     89  1.1  mrg   ATTR_EXCL ("noreturn", true, true, true),
     90  1.1  mrg   ATTR_EXCL ("pure", true, true, true),
     91  1.1  mrg   ATTR_EXCL (NULL, false, false, false)
     92  1.1  mrg };
     93  1.1  mrg 
     94  1.1  mrg static const struct attribute_spec::exclusions attr_inline_exclusions[] =
     95  1.1  mrg {
     96  1.1  mrg   ATTR_EXCL ("noinline", true, true, true),
     97  1.1  mrg   ATTR_EXCL (NULL, false, false, false),
     98  1.1  mrg };
     99  1.1  mrg 
    100  1.1  mrg static const struct attribute_spec::exclusions attr_noinline_exclusions[] =
    101  1.1  mrg {
    102  1.1  mrg   ATTR_EXCL ("forceinline", true, true, true),
    103  1.1  mrg   ATTR_EXCL (NULL, false, false, false),
    104  1.1  mrg };
    105  1.1  mrg 
    106  1.1  mrg /* Helper to define an attribute.  */
    107  1.1  mrg #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \
    108  1.1  mrg 		  affects_type_identity, handler, exclude)		   \
    109  1.1  mrg   { name, min_len, max_len, decl_req, type_req, fn_type_req,		   \
    110  1.1  mrg     affects_type_identity, handler, exclude }
    111  1.1  mrg 
    112  1.1  mrg /* Table of machine-independent attributes.
    113  1.1  mrg    For internal use (marking of built-ins) only.  */
    114  1.1  mrg const attribute_spec d_langhook_common_attribute_table[] =
    115  1.1  mrg {
    116  1.1  mrg   ATTR_SPEC ("noreturn", 0, 0, true, false, false, false,
    117  1.1  mrg 	     handle_noreturn_attribute, attr_noreturn_exclusions),
    118  1.1  mrg   ATTR_SPEC ("leaf", 0, 0, true, false, false, false,
    119  1.1  mrg 	     handle_leaf_attribute, NULL),
    120  1.1  mrg   ATTR_SPEC ("const", 0, 0, true, false, false, false,
    121  1.1  mrg 	     handle_const_attribute, attr_const_pure_exclusions),
    122  1.1  mrg   ATTR_SPEC ("malloc", 0, 0, true, false, false, false,
    123  1.1  mrg 	     handle_malloc_attribute, NULL),
    124  1.1  mrg   ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false,
    125  1.1  mrg 	     handle_returns_twice_attribute, attr_returns_twice_exclusions),
    126  1.1  mrg   ATTR_SPEC ("pure", 0, 0, true, false, false, false,
    127  1.1  mrg 	     handle_pure_attribute, attr_const_pure_exclusions),
    128  1.1  mrg   ATTR_SPEC ("nonnull", 0, -1, false, true, true, false,
    129  1.1  mrg 	     handle_nonnull_attribute, NULL),
    130  1.1  mrg   ATTR_SPEC ("nothrow", 0, 0, true, false, false, false,
    131  1.1  mrg 	     handle_nothrow_attribute, NULL),
    132  1.1  mrg   ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false,
    133  1.1  mrg 	     handle_transaction_pure_attribute, NULL),
    134  1.1  mrg   ATTR_SPEC ("no vops", 0, 0, true, false, false, false,
    135  1.1  mrg 	     handle_novops_attribute, NULL),
    136  1.1  mrg   ATTR_SPEC ("type generic", 0, 0, false, true, true, false,
    137  1.1  mrg 	     handle_type_generic_attribute, NULL),
    138  1.1  mrg   ATTR_SPEC ("fn spec", 1, 1, false, true, true, false,
    139  1.1  mrg 	     handle_fnspec_attribute, NULL),
    140  1.1  mrg   ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
    141  1.1  mrg };
    142  1.1  mrg 
    143  1.1  mrg /* Table of D language attributes exposed by `gcc.attribute' UDAs.  */
    144  1.1  mrg const attribute_spec d_langhook_attribute_table[] =
    145  1.1  mrg {
    146  1.1  mrg   ATTR_SPEC ("noinline", 0, 0, true, false, false, false,
    147  1.1  mrg 	     d_handle_noinline_attribute, attr_noinline_exclusions),
    148  1.1  mrg   ATTR_SPEC ("forceinline", 0, 0, true, false, false, false,
    149  1.1  mrg 	     d_handle_forceinline_attribute, attr_inline_exclusions),
    150  1.1  mrg   ATTR_SPEC ("flatten", 0, 0, true, false, false, false,
    151  1.1  mrg 	     d_handle_flatten_attribute, NULL),
    152  1.1  mrg   ATTR_SPEC ("target", 1, -1, true, false, false, false,
    153  1.1  mrg 	     d_handle_target_attribute, NULL),
    154  1.1  mrg   ATTR_SPEC ("noclone", 0, 0, true, false, false, false,
    155  1.1  mrg 	     d_handle_noclone_attribute, NULL),
    156  1.1  mrg   ATTR_SPEC ("section", 1, 1, true, false, false, false,
    157  1.1  mrg 	     d_handle_section_attribute, NULL),
    158  1.1  mrg   ATTR_SPEC ("alias", 1, 1, true, false, false, false,
    159  1.1  mrg 	     d_handle_alias_attribute, NULL),
    160  1.1  mrg   ATTR_SPEC ("weak", 0, 0, true, false, false, false,
    161  1.1  mrg 	     d_handle_weak_attribute, NULL),
    162  1.1  mrg   ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL),
    163  1.1  mrg };
    164  1.1  mrg 
    165  1.1  mrg 
    166  1.1  mrg /* Insert the type attribute ATTRNAME with value VALUE into TYPE.
    167  1.1  mrg    Returns a new variant of the original type declaration.  */
    168  1.1  mrg 
    169  1.1  mrg tree
    170  1.1  mrg insert_type_attribute (tree type, const char *attrname, tree value)
    171  1.1  mrg {
    172  1.1  mrg   tree ident = get_identifier (attrname);
    173  1.1  mrg 
    174  1.1  mrg   if (value)
    175  1.1  mrg     value = tree_cons (NULL_TREE, value, NULL_TREE);
    176  1.1  mrg 
    177  1.1  mrg   tree attribs = merge_attributes (TYPE_ATTRIBUTES (type),
    178  1.1  mrg 				   tree_cons (ident, value, NULL_TREE));
    179  1.1  mrg 
    180  1.1  mrg   return build_type_attribute_variant (type, attribs);
    181  1.1  mrg }
    182  1.1  mrg 
    183  1.1  mrg /* Insert the decl attribute ATTRNAME with value VALUE into DECL.  */
    184  1.1  mrg 
    185  1.1  mrg tree
    186  1.1  mrg insert_decl_attribute (tree decl, const char *attrname, tree value)
    187  1.1  mrg {
    188  1.1  mrg   tree ident = get_identifier (attrname);
    189  1.1  mrg 
    190  1.1  mrg   if (value)
    191  1.1  mrg     value = tree_cons (NULL_TREE, value, NULL_TREE);
    192  1.1  mrg 
    193  1.1  mrg   tree attribs = merge_attributes (DECL_ATTRIBUTES (decl),
    194  1.1  mrg 				   tree_cons (ident, value, NULL_TREE));
    195  1.1  mrg 
    196  1.1  mrg   return build_decl_attribute_variant (decl, attribs);
    197  1.1  mrg }
    198  1.1  mrg 
    199  1.1  mrg /* Returns TRUE if NAME is an attribute recognized as being handled by
    200  1.1  mrg    the `gcc.attribute' module.  */
    201  1.1  mrg 
    202  1.1  mrg static bool
    203  1.1  mrg uda_attribute_p (const char *name)
    204  1.1  mrg {
    205  1.1  mrg   tree ident = get_identifier (name);
    206  1.1  mrg 
    207  1.1  mrg   /* Search both our language, and target attribute tables.
    208  1.1  mrg      Common and format attributes are kept internal.  */
    209  1.1  mrg   for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++)
    210  1.1  mrg     {
    211  1.1  mrg       if (get_identifier (p->name) == ident)
    212  1.1  mrg 	return true;
    213  1.1  mrg     }
    214  1.1  mrg 
    215  1.1  mrg   for (const attribute_spec *p = targetm.attribute_table; p->name; p++)
    216  1.1  mrg     {
    217  1.1  mrg       if (get_identifier (p->name) == ident)
    218  1.1  mrg 	return true;
    219  1.1  mrg     }
    220  1.1  mrg 
    221  1.1  mrg   return false;
    222  1.1  mrg }
    223  1.1  mrg 
    224  1.1  mrg /* [attribute/uda]
    225  1.1  mrg 
    226  1.1  mrg    User Defined Attributes (UDA) are compile time expressions that can be
    227  1.1  mrg    attached to a declaration.  These attributes can then be queried, extracted,
    228  1.1  mrg    and manipulated at compile-time.  There is no run-time component to them.
    229  1.1  mrg 
    230  1.1  mrg    Expand and merge all UDAs found in the EATTRS list that are of type
    231  1.1  mrg    `gcc.attribute.Attribute'.  This symbol is internally recognized by the
    232  1.1  mrg    compiler and maps them to their equivalent GCC attribute.  */
    233  1.1  mrg 
    234  1.1  mrg tree
    235  1.1  mrg build_attributes (Expressions *eattrs)
    236  1.1  mrg {
    237  1.1  mrg   if (!eattrs)
    238  1.1  mrg     return NULL_TREE;
    239  1.1  mrg 
    240  1.1  mrg   expandTuples (eattrs);
    241  1.1  mrg 
    242  1.1  mrg   tree attribs = NULL_TREE;
    243  1.1  mrg 
    244  1.1  mrg   for (size_t i = 0; i < eattrs->dim; i++)
    245  1.1  mrg     {
    246  1.1  mrg       Expression *attr = (*eattrs)[i];
    247  1.1  mrg       Dsymbol *sym = attr->type->toDsymbol (0);
    248  1.1  mrg 
    249  1.1  mrg       if (!sym)
    250  1.1  mrg 	continue;
    251  1.1  mrg 
    252  1.1  mrg       /* Attribute symbol must come from the `gcc.attribute' module.  */
    253  1.1  mrg       Dsymbol *mod = (Dsymbol*) sym->getModule ();
    254  1.1  mrg       if (!(strcmp (mod->toChars (), "attribute") == 0
    255  1.1  mrg 	    && mod->parent != NULL
    256  1.1  mrg 	    && strcmp (mod->parent->toChars (), "gcc") == 0
    257  1.1  mrg 	    && !mod->parent->parent))
    258  1.1  mrg 	continue;
    259  1.1  mrg 
    260  1.1  mrg       /* Get the result of the attribute if it hasn't already been folded.  */
    261  1.1  mrg       if (attr->op == TOKcall)
    262  1.1  mrg 	attr = attr->ctfeInterpret ();
    263  1.1  mrg 
    264  1.1  mrg       /* Should now have a struct `Attribute("attrib", "value", ...)'
    265  1.1  mrg 	 initializer list.  */
    266  1.1  mrg       gcc_assert (attr->op == TOKstructliteral);
    267  1.1  mrg       Expressions *elems = ((StructLiteralExp*) attr)->elements;
    268  1.1  mrg       Expression *e0 = (*elems)[0];
    269  1.1  mrg 
    270  1.1  mrg       if (e0->op != TOKstring)
    271  1.1  mrg 	{
    272  1.1  mrg 	  error ("expected string attribute, not %qs", e0->toChars ());
    273  1.1  mrg 	  return error_mark_node;
    274  1.1  mrg 	}
    275  1.1  mrg 
    276  1.1  mrg       StringExp *se = (StringExp*) e0;
    277  1.1  mrg       gcc_assert (se->sz == 1);
    278  1.1  mrg 
    279  1.1  mrg       /* Empty string attribute, just ignore it.  */
    280  1.1  mrg       if (se->len == 0)
    281  1.1  mrg 	continue;
    282  1.1  mrg 
    283  1.1  mrg       /* Check if the attribute is recognized and handled.
    284  1.1  mrg 	 Done here to report the diagnostic at the right location.  */
    285  1.1  mrg       const char *name = (const char *)(se->len ? se->string : "");
    286  1.1  mrg       if (!uda_attribute_p (name))
    287  1.1  mrg 	{
    288  1.1  mrg 	  warning_at (make_location_t (e0->loc), OPT_Wattributes,
    289  1.1  mrg 		      "unknown attribute %qs", name);
    290  1.1  mrg 	  return error_mark_node;
    291  1.1  mrg 	}
    292  1.1  mrg 
    293  1.1  mrg       /* Chain all attribute arguments together.  */
    294  1.1  mrg       tree args = NULL_TREE;
    295  1.1  mrg 
    296  1.1  mrg       for (size_t j = 1; j < elems->dim; j++)
    297  1.1  mrg 	{
    298  1.1  mrg 	  Expression *e = (*elems)[j];
    299  1.1  mrg 	  tree t;
    300  1.1  mrg 	  if (e->op == TOKstring && ((StringExp *) e)->sz == 1)
    301  1.1  mrg 	    {
    302  1.1  mrg 	      StringExp *s = (StringExp *) e;
    303  1.1  mrg 	      const char *string = (const char *)(s->len ? s->string : "");
    304  1.1  mrg 	      t = build_string (s->len, string);
    305  1.1  mrg 	    }
    306  1.1  mrg 	  else
    307  1.1  mrg 	    t = build_expr (e);
    308  1.1  mrg 
    309  1.1  mrg 	  args = chainon (args, build_tree_list (0, t));
    310  1.1  mrg 	}
    311  1.1  mrg 
    312  1.1  mrg       tree list = build_tree_list (get_identifier (name), args);
    313  1.1  mrg       attribs = chainon (attribs, list);
    314  1.1  mrg     }
    315  1.1  mrg 
    316  1.1  mrg   return attribs;
    317  1.1  mrg }
    318  1.1  mrg 
    319  1.1  mrg /* Built-in attribute handlers.  */
    320  1.1  mrg 
    321  1.1  mrg /* Handle a "noreturn" attribute; arguments as in
    322  1.1  mrg    struct attribute_spec.handler.  */
    323  1.1  mrg 
    324  1.1  mrg static tree
    325  1.1  mrg handle_noreturn_attribute (tree *node, tree ARG_UNUSED (name),
    326  1.1  mrg 			   tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    327  1.1  mrg 			   bool * ARG_UNUSED (no_add_attrs))
    328  1.1  mrg {
    329  1.1  mrg   tree type = TREE_TYPE (*node);
    330  1.1  mrg 
    331  1.1  mrg   if (TREE_CODE (*node) == FUNCTION_DECL)
    332  1.1  mrg     TREE_THIS_VOLATILE (*node) = 1;
    333  1.1  mrg   else if (TREE_CODE (type) == POINTER_TYPE
    334  1.1  mrg 	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
    335  1.1  mrg     TREE_TYPE (*node)
    336  1.1  mrg       = build_pointer_type
    337  1.1  mrg 	(build_type_variant (TREE_TYPE (type),
    338  1.1  mrg 			     TYPE_READONLY (TREE_TYPE (type)), 1));
    339  1.1  mrg   else
    340  1.1  mrg     gcc_unreachable ();
    341  1.1  mrg 
    342  1.1  mrg   return NULL_TREE;
    343  1.1  mrg }
    344  1.1  mrg 
    345  1.1  mrg /* Handle a "leaf" attribute; arguments as in
    346  1.1  mrg    struct attribute_spec.handler.  */
    347  1.1  mrg 
    348  1.1  mrg static tree
    349  1.1  mrg handle_leaf_attribute (tree *node, tree name,
    350  1.1  mrg 		       tree ARG_UNUSED (args),
    351  1.1  mrg 		       int ARG_UNUSED (flags), bool *no_add_attrs)
    352  1.1  mrg {
    353  1.1  mrg   if (TREE_CODE (*node) != FUNCTION_DECL)
    354  1.1  mrg     {
    355  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    356  1.1  mrg       *no_add_attrs = true;
    357  1.1  mrg     }
    358  1.1  mrg   if (!TREE_PUBLIC (*node))
    359  1.1  mrg     {
    360  1.1  mrg       warning (OPT_Wattributes, "%qE attribute has no effect", name);
    361  1.1  mrg       *no_add_attrs = true;
    362  1.1  mrg     }
    363  1.1  mrg 
    364  1.1  mrg   return NULL_TREE;
    365  1.1  mrg }
    366  1.1  mrg 
    367  1.1  mrg /* Handle a "const" attribute; arguments as in
    368  1.1  mrg    struct attribute_spec.handler.  */
    369  1.1  mrg 
    370  1.1  mrg static tree
    371  1.1  mrg handle_const_attribute (tree *node, tree ARG_UNUSED (name),
    372  1.1  mrg 			tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    373  1.1  mrg 			bool * ARG_UNUSED (no_add_attrs))
    374  1.1  mrg {
    375  1.1  mrg   tree type = TREE_TYPE (*node);
    376  1.1  mrg 
    377  1.1  mrg   if (TREE_CODE (*node) == FUNCTION_DECL)
    378  1.1  mrg     TREE_READONLY (*node) = 1;
    379  1.1  mrg   else if (TREE_CODE (type) == POINTER_TYPE
    380  1.1  mrg 	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
    381  1.1  mrg     TREE_TYPE (*node)
    382  1.1  mrg       = build_pointer_type
    383  1.1  mrg 	(build_type_variant (TREE_TYPE (type), 1,
    384  1.1  mrg 			     TREE_THIS_VOLATILE (TREE_TYPE (type))));
    385  1.1  mrg   else
    386  1.1  mrg     gcc_unreachable ();
    387  1.1  mrg 
    388  1.1  mrg   return NULL_TREE;
    389  1.1  mrg }
    390  1.1  mrg 
    391  1.1  mrg /* Handle a "malloc" attribute; arguments as in
    392  1.1  mrg    struct attribute_spec.handler.  */
    393  1.1  mrg 
    394  1.1  mrg tree
    395  1.1  mrg handle_malloc_attribute (tree *node, tree ARG_UNUSED (name),
    396  1.1  mrg 			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    397  1.1  mrg 			 bool * ARG_UNUSED (no_add_attrs))
    398  1.1  mrg {
    399  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL
    400  1.1  mrg 	      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))));
    401  1.1  mrg   DECL_IS_MALLOC (*node) = 1;
    402  1.1  mrg   return NULL_TREE;
    403  1.1  mrg }
    404  1.1  mrg 
    405  1.1  mrg /* Handle a "pure" attribute; arguments as in
    406  1.1  mrg    struct attribute_spec.handler.  */
    407  1.1  mrg 
    408  1.1  mrg static tree
    409  1.1  mrg handle_pure_attribute (tree *node, tree ARG_UNUSED (name),
    410  1.1  mrg 		       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    411  1.1  mrg 		       bool * ARG_UNUSED (no_add_attrs))
    412  1.1  mrg {
    413  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    414  1.1  mrg   DECL_PURE_P (*node) = 1;
    415  1.1  mrg   return NULL_TREE;
    416  1.1  mrg }
    417  1.1  mrg 
    418  1.1  mrg /* Handle a "no vops" attribute; arguments as in
    419  1.1  mrg    struct attribute_spec.handler.  */
    420  1.1  mrg 
    421  1.1  mrg static tree
    422  1.1  mrg handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
    423  1.1  mrg 			 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    424  1.1  mrg 			 bool * ARG_UNUSED (no_add_attrs))
    425  1.1  mrg {
    426  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    427  1.1  mrg   DECL_IS_NOVOPS (*node) = 1;
    428  1.1  mrg   return NULL_TREE;
    429  1.1  mrg }
    430  1.1  mrg 
    431  1.1  mrg /* Helper for nonnull attribute handling; fetch the operand number
    432  1.1  mrg    from the attribute argument list.  */
    433  1.1  mrg 
    434  1.1  mrg static bool
    435  1.1  mrg get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
    436  1.1  mrg {
    437  1.1  mrg   /* Verify the arg number is a constant.  */
    438  1.1  mrg   if (!tree_fits_uhwi_p (arg_num_expr))
    439  1.1  mrg     return false;
    440  1.1  mrg 
    441  1.1  mrg   *valp = TREE_INT_CST_LOW (arg_num_expr);
    442  1.1  mrg   return true;
    443  1.1  mrg }
    444  1.1  mrg 
    445  1.1  mrg /* Handle the "nonnull" attribute.  */
    446  1.1  mrg 
    447  1.1  mrg static tree
    448  1.1  mrg handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
    449  1.1  mrg 			  tree args, int ARG_UNUSED (flags),
    450  1.1  mrg 			  bool * ARG_UNUSED (no_add_attrs))
    451  1.1  mrg {
    452  1.1  mrg   tree type = *node;
    453  1.1  mrg 
    454  1.1  mrg   /* If no arguments are specified, all pointer arguments should be
    455  1.1  mrg      non-null.  Verify a full prototype is given so that the arguments
    456  1.1  mrg      will have the correct types when we actually check them later.
    457  1.1  mrg      Avoid diagnosing type-generic built-ins since those have no
    458  1.1  mrg      prototype.  */
    459  1.1  mrg   if (!args)
    460  1.1  mrg     {
    461  1.1  mrg       gcc_assert (prototype_p (type)
    462  1.1  mrg 		  || !TYPE_ATTRIBUTES (type)
    463  1.1  mrg 		  || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type)));
    464  1.1  mrg 
    465  1.1  mrg       return NULL_TREE;
    466  1.1  mrg     }
    467  1.1  mrg 
    468  1.1  mrg   /* Argument list specified.  Verify that each argument number references
    469  1.1  mrg      a pointer argument.  */
    470  1.1  mrg   for (; args; args = TREE_CHAIN (args))
    471  1.1  mrg     {
    472  1.1  mrg       tree argument;
    473  1.1  mrg       unsigned HOST_WIDE_INT arg_num = 0, ck_num;
    474  1.1  mrg 
    475  1.1  mrg       if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
    476  1.1  mrg 	gcc_unreachable ();
    477  1.1  mrg 
    478  1.1  mrg       argument = TYPE_ARG_TYPES (type);
    479  1.1  mrg       if (argument)
    480  1.1  mrg 	{
    481  1.1  mrg 	  for (ck_num = 1; ; ck_num++)
    482  1.1  mrg 	    {
    483  1.1  mrg 	      if (!argument || ck_num == arg_num)
    484  1.1  mrg 		break;
    485  1.1  mrg 	      argument = TREE_CHAIN (argument);
    486  1.1  mrg 	    }
    487  1.1  mrg 
    488  1.1  mrg 	  gcc_assert (argument
    489  1.1  mrg 		      && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE);
    490  1.1  mrg 	}
    491  1.1  mrg     }
    492  1.1  mrg 
    493  1.1  mrg   return NULL_TREE;
    494  1.1  mrg }
    495  1.1  mrg 
    496  1.1  mrg /* Handle a "nothrow" attribute; arguments as in
    497  1.1  mrg    struct attribute_spec.handler.  */
    498  1.1  mrg 
    499  1.1  mrg static tree
    500  1.1  mrg handle_nothrow_attribute (tree *node, tree ARG_UNUSED (name),
    501  1.1  mrg 			  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    502  1.1  mrg 			  bool * ARG_UNUSED (no_add_attrs))
    503  1.1  mrg {
    504  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    505  1.1  mrg   TREE_NOTHROW (*node) = 1;
    506  1.1  mrg   return NULL_TREE;
    507  1.1  mrg }
    508  1.1  mrg 
    509  1.1  mrg /* Handle a "type_generic" attribute.  */
    510  1.1  mrg 
    511  1.1  mrg static tree
    512  1.1  mrg handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
    513  1.1  mrg 			       tree ARG_UNUSED (args), int ARG_UNUSED (flags),
    514  1.1  mrg 			       bool * ARG_UNUSED (no_add_attrs))
    515  1.1  mrg {
    516  1.1  mrg   /* Ensure we have a function type.  */
    517  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
    518  1.1  mrg 
    519  1.1  mrg   /* Ensure we have a variadic function.  */
    520  1.1  mrg   gcc_assert (!prototype_p (*node) || stdarg_p (*node));
    521  1.1  mrg 
    522  1.1  mrg   return NULL_TREE;
    523  1.1  mrg }
    524  1.1  mrg 
    525  1.1  mrg /* Handle a "transaction_pure" attribute.  */
    526  1.1  mrg 
    527  1.1  mrg static tree
    528  1.1  mrg handle_transaction_pure_attribute (tree *node, tree ARG_UNUSED (name),
    529  1.1  mrg 				   tree ARG_UNUSED (args),
    530  1.1  mrg 				   int ARG_UNUSED (flags),
    531  1.1  mrg 				   bool * ARG_UNUSED (no_add_attrs))
    532  1.1  mrg {
    533  1.1  mrg   /* Ensure we have a function type.  */
    534  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
    535  1.1  mrg 
    536  1.1  mrg   return NULL_TREE;
    537  1.1  mrg }
    538  1.1  mrg 
    539  1.1  mrg /* Handle a "returns_twice" attribute.  */
    540  1.1  mrg 
    541  1.1  mrg static tree
    542  1.1  mrg handle_returns_twice_attribute (tree *node, tree ARG_UNUSED (name),
    543  1.1  mrg 				tree ARG_UNUSED (args),
    544  1.1  mrg 				int ARG_UNUSED (flags),
    545  1.1  mrg 				bool * ARG_UNUSED (no_add_attrs))
    546  1.1  mrg {
    547  1.1  mrg   gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
    548  1.1  mrg 
    549  1.1  mrg   DECL_IS_RETURNS_TWICE (*node) = 1;
    550  1.1  mrg 
    551  1.1  mrg   return NULL_TREE;
    552  1.1  mrg }
    553  1.1  mrg 
    554  1.1  mrg /* Handle a "fn spec" attribute; arguments as in
    555  1.1  mrg    struct attribute_spec.handler.  */
    556  1.1  mrg 
    557  1.1  mrg tree
    558  1.1  mrg handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
    559  1.1  mrg 			 tree args, int ARG_UNUSED (flags),
    560  1.1  mrg 			 bool *no_add_attrs ATTRIBUTE_UNUSED)
    561  1.1  mrg {
    562  1.1  mrg   gcc_assert (args
    563  1.1  mrg 	      && TREE_CODE (TREE_VALUE (args)) == STRING_CST
    564  1.1  mrg 	      && !TREE_CHAIN (args));
    565  1.1  mrg   return NULL_TREE;
    566  1.1  mrg }
    567  1.1  mrg 
    568  1.1  mrg /* Language specific attribute handlers.  */
    569  1.1  mrg 
    570  1.1  mrg /* Handle a "noinline" attribute.  */
    571  1.1  mrg 
    572  1.1  mrg static tree
    573  1.1  mrg d_handle_noinline_attribute (tree *node, tree name,
    574  1.1  mrg 			     tree ARG_UNUSED (args),
    575  1.1  mrg 			     int ARG_UNUSED (flags), bool *no_add_attrs)
    576  1.1  mrg {
    577  1.1  mrg   Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
    578  1.1  mrg 
    579  1.1  mrg   if (t->ty == Tfunction)
    580  1.1  mrg     DECL_UNINLINABLE (*node) = 1;
    581  1.1  mrg   else
    582  1.1  mrg     {
    583  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    584  1.1  mrg       *no_add_attrs = true;
    585  1.1  mrg     }
    586  1.1  mrg 
    587  1.1  mrg   return NULL_TREE;
    588  1.1  mrg }
    589  1.1  mrg 
    590  1.1  mrg /* Handle a "forceinline" attribute.  */
    591  1.1  mrg 
    592  1.1  mrg static tree
    593  1.1  mrg d_handle_forceinline_attribute (tree *node, tree name,
    594  1.1  mrg 				tree ARG_UNUSED (args),
    595  1.1  mrg 				int ARG_UNUSED (flags),
    596  1.1  mrg 				bool *no_add_attrs)
    597  1.1  mrg {
    598  1.1  mrg   Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
    599  1.1  mrg 
    600  1.1  mrg   if (t->ty == Tfunction)
    601  1.1  mrg     {
    602  1.1  mrg       tree attributes = DECL_ATTRIBUTES (*node);
    603  1.1  mrg 
    604  1.1  mrg       /* Push attribute always_inline.  */
    605  1.1  mrg       if (! lookup_attribute ("always_inline", attributes))
    606  1.1  mrg 	DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("always_inline"),
    607  1.1  mrg 					     NULL_TREE, attributes);
    608  1.1  mrg 
    609  1.1  mrg       DECL_DECLARED_INLINE_P (*node) = 1;
    610  1.1  mrg       DECL_NO_INLINE_WARNING_P (*node) = 1;
    611  1.1  mrg       DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
    612  1.1  mrg     }
    613  1.1  mrg   else
    614  1.1  mrg     {
    615  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    616  1.1  mrg       *no_add_attrs = true;
    617  1.1  mrg     }
    618  1.1  mrg 
    619  1.1  mrg   return NULL_TREE;
    620  1.1  mrg }
    621  1.1  mrg 
    622  1.1  mrg /* Handle a "flatten" attribute.  */
    623  1.1  mrg 
    624  1.1  mrg static tree
    625  1.1  mrg d_handle_flatten_attribute (tree *node, tree name,
    626  1.1  mrg 			    tree args ATTRIBUTE_UNUSED,
    627  1.1  mrg 			    int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
    628  1.1  mrg {
    629  1.1  mrg   Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
    630  1.1  mrg 
    631  1.1  mrg   if (t->ty != Tfunction)
    632  1.1  mrg     {
    633  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    634  1.1  mrg       *no_add_attrs = true;
    635  1.1  mrg     }
    636  1.1  mrg 
    637  1.1  mrg   return NULL_TREE;
    638  1.1  mrg }
    639  1.1  mrg 
    640  1.1  mrg /* Handle a "target" attribute.  */
    641  1.1  mrg 
    642  1.1  mrg static tree
    643  1.1  mrg d_handle_target_attribute (tree *node, tree name, tree args, int flags,
    644  1.1  mrg 			   bool *no_add_attrs)
    645  1.1  mrg {
    646  1.1  mrg   Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
    647  1.1  mrg 
    648  1.1  mrg   /* Ensure we have a function type.  */
    649  1.1  mrg   if (t->ty != Tfunction)
    650  1.1  mrg     {
    651  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    652  1.1  mrg       *no_add_attrs = true;
    653  1.1  mrg     }
    654  1.1  mrg   else if (! targetm.target_option.valid_attribute_p (*node, name, args, flags))
    655  1.1  mrg     *no_add_attrs = true;
    656  1.1  mrg 
    657  1.1  mrg   return NULL_TREE;
    658  1.1  mrg }
    659  1.1  mrg 
    660  1.1  mrg /* Handle a "noclone" attribute.  */
    661  1.1  mrg 
    662  1.1  mrg static tree
    663  1.1  mrg d_handle_noclone_attribute (tree *node, tree name,
    664  1.1  mrg 				tree ARG_UNUSED (args),
    665  1.1  mrg 				int ARG_UNUSED (flags),
    666  1.1  mrg 				bool *no_add_attrs)
    667  1.1  mrg {
    668  1.1  mrg   Type *t = TYPE_LANG_FRONTEND (TREE_TYPE (*node));
    669  1.1  mrg 
    670  1.1  mrg   if (t->ty == Tfunction)
    671  1.1  mrg     {
    672  1.1  mrg       tree attributes = DECL_ATTRIBUTES (*node);
    673  1.1  mrg 
    674  1.1  mrg       /* Push attribute noclone.  */
    675  1.1  mrg       if (! lookup_attribute ("noclone", attributes))
    676  1.1  mrg 	DECL_ATTRIBUTES (*node) = tree_cons (get_identifier ("noclone"),
    677  1.1  mrg 					     NULL_TREE, attributes);
    678  1.1  mrg     }
    679  1.1  mrg   else
    680  1.1  mrg     {
    681  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    682  1.1  mrg       *no_add_attrs = true;
    683  1.1  mrg     }
    684  1.1  mrg 
    685  1.1  mrg   return NULL_TREE;
    686  1.1  mrg }
    687  1.1  mrg 
    688  1.1  mrg /* Handle a "section" attribute; arguments as in
    689  1.1  mrg    struct attribute_spec.handler.  */
    690  1.1  mrg 
    691  1.1  mrg static tree
    692  1.1  mrg d_handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
    693  1.1  mrg 			    int ARG_UNUSED (flags), bool *no_add_attrs)
    694  1.1  mrg {
    695  1.1  mrg   tree decl = *node;
    696  1.1  mrg 
    697  1.1  mrg   if (targetm_common.have_named_sections)
    698  1.1  mrg     {
    699  1.1  mrg       if (VAR_OR_FUNCTION_DECL_P (decl)
    700  1.1  mrg 	  && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
    701  1.1  mrg 	{
    702  1.1  mrg 	  if (VAR_P (decl)
    703  1.1  mrg 	      && current_function_decl != NULL_TREE
    704  1.1  mrg 	      && !TREE_STATIC (decl))
    705  1.1  mrg 	    {
    706  1.1  mrg 	      error_at (DECL_SOURCE_LOCATION (decl),
    707  1.1  mrg 			"section attribute cannot be specified for "
    708  1.1  mrg 			"local variables");
    709  1.1  mrg 	      *no_add_attrs = true;
    710  1.1  mrg 	    }
    711  1.1  mrg 
    712  1.1  mrg 	  /* The decl may have already been given a section attribute
    713  1.1  mrg 	     from a previous declaration.  Ensure they match.  */
    714  1.1  mrg 	  else if (DECL_SECTION_NAME (decl) != NULL
    715  1.1  mrg 		   && strcmp (DECL_SECTION_NAME (decl),
    716  1.1  mrg 			      TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
    717  1.1  mrg 	    {
    718  1.1  mrg 	      error ("section of %q+D conflicts with previous declaration",
    719  1.1  mrg 		     *node);
    720  1.1  mrg 	      *no_add_attrs = true;
    721  1.1  mrg 	    }
    722  1.1  mrg 	  else if (VAR_P (decl)
    723  1.1  mrg 		   && !targetm.have_tls && targetm.emutls.tmpl_section
    724  1.1  mrg 		   && DECL_THREAD_LOCAL_P (decl))
    725  1.1  mrg 	    {
    726  1.1  mrg 	      error ("section of %q+D cannot be overridden", *node);
    727  1.1  mrg 	      *no_add_attrs = true;
    728  1.1  mrg 	    }
    729  1.1  mrg 	  else
    730  1.1  mrg 	    set_decl_section_name (decl,
    731  1.1  mrg 				   TREE_STRING_POINTER (TREE_VALUE (args)));
    732  1.1  mrg 	}
    733  1.1  mrg       else
    734  1.1  mrg 	{
    735  1.1  mrg 	  error ("section attribute not allowed for %q+D", *node);
    736  1.1  mrg 	  *no_add_attrs = true;
    737  1.1  mrg 	}
    738  1.1  mrg     }
    739  1.1  mrg   else
    740  1.1  mrg     {
    741  1.1  mrg       error_at (DECL_SOURCE_LOCATION (*node),
    742  1.1  mrg 		"section attributes are not supported for this target");
    743  1.1  mrg       *no_add_attrs = true;
    744  1.1  mrg     }
    745  1.1  mrg 
    746  1.1  mrg   return NULL_TREE;
    747  1.1  mrg }
    748  1.1  mrg 
    749  1.1  mrg /* Handle an "alias" attribute; arguments as in
    750  1.1  mrg    struct attribute_spec.handler.  */
    751  1.1  mrg 
    752  1.1  mrg static tree
    753  1.1  mrg d_handle_alias_attribute (tree *node, tree ARG_UNUSED (name),
    754  1.1  mrg 			  tree args, int ARG_UNUSED (flags),
    755  1.1  mrg 			  bool *no_add_attrs ATTRIBUTE_UNUSED)
    756  1.1  mrg {
    757  1.1  mrg   tree decl = *node;
    758  1.1  mrg 
    759  1.1  mrg   if (TREE_CODE (decl) != FUNCTION_DECL
    760  1.1  mrg       && TREE_CODE (decl) != VAR_DECL)
    761  1.1  mrg     {
    762  1.1  mrg       warning (OPT_Wattributes, "%qE attribute ignored", name);
    763  1.1  mrg       *no_add_attrs = true;
    764  1.1  mrg       return NULL_TREE;
    765  1.1  mrg     }
    766  1.1  mrg   else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
    767  1.1  mrg       || (TREE_CODE (decl) != FUNCTION_DECL
    768  1.1  mrg 	  && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
    769  1.1  mrg       /* A static variable declaration is always a tentative definition,
    770  1.1  mrg 	 but the alias is a non-tentative definition which overrides.  */
    771  1.1  mrg       || (TREE_CODE (decl) != FUNCTION_DECL
    772  1.1  mrg 	  && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
    773  1.1  mrg     {
    774  1.1  mrg       error ("%q+D defined both normally and as %qE attribute", decl, name);
    775  1.1  mrg       *no_add_attrs = true;
    776  1.1  mrg       return NULL_TREE;
    777  1.1  mrg     }
    778  1.1  mrg   else if (decl_function_context (decl))
    779  1.1  mrg     {
    780  1.1  mrg       error ("%q+D alias functions must be global", name);
    781  1.1  mrg       *no_add_attrs = true;
    782  1.1  mrg       return NULL_TREE;
    783  1.1  mrg     }
    784  1.1  mrg   else
    785  1.1  mrg     {
    786  1.1  mrg       tree id;
    787  1.1  mrg 
    788  1.1  mrg       id = TREE_VALUE (args);
    789  1.1  mrg       if (TREE_CODE (id) != STRING_CST)
    790  1.1  mrg 	{
    791  1.1  mrg 	  error ("attribute %qE argument not a string", name);
    792  1.1  mrg 	  *no_add_attrs = true;
    793  1.1  mrg 	  return NULL_TREE;
    794  1.1  mrg 	}
    795  1.1  mrg       id = get_identifier (TREE_STRING_POINTER (id));
    796  1.1  mrg       /* This counts as a use of the object pointed to.  */
    797  1.1  mrg       TREE_USED (id) = 1;
    798  1.1  mrg 
    799  1.1  mrg       if (TREE_CODE (decl) == FUNCTION_DECL)
    800  1.1  mrg 	DECL_INITIAL (decl) = error_mark_node;
    801  1.1  mrg       else
    802  1.1  mrg 	TREE_STATIC (decl) = 1;
    803  1.1  mrg 
    804  1.1  mrg       return NULL_TREE;
    805  1.1  mrg     }
    806  1.1  mrg }
    807  1.1  mrg 
    808  1.1  mrg /* Handle a "weak" attribute; arguments as in
    809  1.1  mrg    struct attribute_spec.handler.  */
    810  1.1  mrg 
    811  1.1  mrg static tree
    812  1.1  mrg d_handle_weak_attribute (tree *node, tree name,
    813  1.1  mrg 			 tree ARG_UNUSED (args),
    814  1.1  mrg 			 int ARG_UNUSED (flags),
    815  1.1  mrg 			 bool * ARG_UNUSED (no_add_attrs))
    816  1.1  mrg {
    817  1.1  mrg   if (TREE_CODE (*node) == FUNCTION_DECL
    818  1.1  mrg       && DECL_DECLARED_INLINE_P (*node))
    819  1.1  mrg     {
    820  1.1  mrg       warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
    821  1.1  mrg       *no_add_attrs = true;
    822  1.1  mrg     }
    823  1.1  mrg   else if (VAR_OR_FUNCTION_DECL_P (*node))
    824  1.1  mrg     {
    825  1.1  mrg       struct symtab_node *n = symtab_node::get (*node);
    826  1.1  mrg       if (n && n->refuse_visibility_changes)
    827  1.1  mrg 	error ("%q+D declared weak after being used", *node);
    828  1.1  mrg       declare_weak (*node);
    829  1.1  mrg     }
    830  1.1  mrg   else
    831  1.1  mrg     warning (OPT_Wattributes, "%qE attribute ignored", name);
    832  1.1  mrg 
    833  1.1  mrg   return NULL_TREE;
    834  1.1  mrg }
    835  1.1  mrg 
    836