attribs.c revision 90075
1114402Sru/* Functions dealing with attribute handling, used by most front ends.
2114402Sru   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3114402Sru   2002 Free Software Foundation, Inc.
4114402Sru
5114402SruThis file is part of GCC.
6114402Sru
7114402SruGCC is free software; you can redistribute it and/or modify it under
8114402Sruthe terms of the GNU General Public License as published by the Free
9114402SruSoftware Foundation; either version 2, or (at your option) any later
10114402Sruversion.
11114402Sru
12114402SruGCC is distributed in the hope that it will be useful, but WITHOUT ANY
13114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or
14114402SruFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15114402Srufor more details.
16114402Sru
17114402SruYou should have received a copy of the GNU General Public License
18114402Srualong with GCC; see the file COPYING.  If not, write to the Free
19151497SruSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
20114402Sru02111-1307, USA.  */
21114402Sru
22114402Sru#include "config.h"
23114402Sru#include "system.h"
24114402Sru#include "tree.h"
25114402Sru#include "flags.h"
26114402Sru#include "toplev.h"
27114402Sru#include "output.h"
28114402Sru#include "rtl.h"
29114402Sru#include "ggc.h"
30114402Sru#include "expr.h"
31114402Sru#include "tm_p.h"
32114402Sru#include "obstack.h"
33114402Sru#include "cpplib.h"
34114402Sru#include "target.h"
35114402Sru
36114402Srustatic void init_attributes		PARAMS ((void));
37114402Sru
38114402Sru/* Table of the tables of attributes (common, format, language, machine)
39114402Sru   searched.  */
40114402Srustatic const struct attribute_spec *attribute_tables[4];
41114402Sru
42114402Srustatic bool attributes_initialized = false;
43114402Sru
44114402Srustatic tree handle_packed_attribute	PARAMS ((tree *, tree, tree, int,
45114402Sru						 bool *));
46114402Srustatic tree handle_nocommon_attribute	PARAMS ((tree *, tree, tree, int,
47114402Sru						 bool *));
48114402Srustatic tree handle_common_attribute	PARAMS ((tree *, tree, tree, int,
49114402Sru						 bool *));
50114402Srustatic tree handle_noreturn_attribute	PARAMS ((tree *, tree, tree, int,
51114402Sru						 bool *));
52114402Srustatic tree handle_noinline_attribute	PARAMS ((tree *, tree, tree, int,
53114402Sru						 bool *));
54114402Srustatic tree handle_used_attribute	PARAMS ((tree *, tree, tree, int,
55114402Sru						 bool *));
56114402Srustatic tree handle_unused_attribute	PARAMS ((tree *, tree, tree, int,
57114402Sru						 bool *));
58114402Srustatic tree handle_const_attribute	PARAMS ((tree *, tree, tree, int,
59114402Sru						 bool *));
60114402Srustatic tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
61114402Sru							int, bool *));
62114402Srustatic tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
63114402Sru						  bool *));
64114402Srustatic tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
65114402Sru						 bool *));
66114402Srustatic tree handle_mode_attribute	PARAMS ((tree *, tree, tree, int,
67114402Sru						 bool *));
68114402Srustatic tree handle_section_attribute	PARAMS ((tree *, tree, tree, int,
69114402Sru						 bool *));
70114402Srustatic tree handle_aligned_attribute	PARAMS ((tree *, tree, tree, int,
71114402Sru						 bool *));
72114402Srustatic tree handle_weak_attribute	PARAMS ((tree *, tree, tree, int,
73114402Sru						 bool *));
74114402Srustatic tree handle_alias_attribute	PARAMS ((tree *, tree, tree, int,
75114402Sru						 bool *));
76114402Srustatic tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
77114402Sru							     tree, int,
78114402Sru							     bool *));
79114402Srustatic tree handle_malloc_attribute	PARAMS ((tree *, tree, tree, int,
80114402Sru						 bool *));
81114402Srustatic tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
82114402Sru						     bool *));
83114402Srustatic tree handle_pure_attribute	PARAMS ((tree *, tree, tree, int,
84114402Sru						 bool *));
85114402Srustatic tree handle_deprecated_attribute	PARAMS ((tree *, tree, tree, int,
86114402Sru						 bool *));
87114402Srustatic tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
88114402Sru						  bool *));
89114402Srustatic tree vector_size_helper PARAMS ((tree, tree));
90114402Sru
91114402Sru/* Table of machine-independent attributes common to all C-like languages.  */
92114402Srustatic const struct attribute_spec c_common_attribute_table[] =
93114402Sru{
94114402Sru  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
95114402Sru  { "packed",                 0, 0, false, false, false,
96114402Sru      			      handle_packed_attribute },
97114402Sru  { "nocommon",               0, 0, true,  false, false,
98114402Sru			      handle_nocommon_attribute },
99114402Sru  { "common",                 0, 0, true,  false, false,
100114402Sru			      handle_common_attribute },
101114402Sru  /* FIXME: logically, noreturn attributes should be listed as
102114402Sru     "false, true, true" and apply to function types.  But implementing this
103114402Sru     would require all the places in the compiler that use TREE_THIS_VOLATILE
104114402Sru     on a decl to identify non-returning functions to be located and fixed
105114402Sru     to check the function type instead.  */
106114402Sru  { "noreturn",               0, 0, true,  false, false,
107114402Sru			      handle_noreturn_attribute },
108114402Sru  { "volatile",               0, 0, true,  false, false,
109114402Sru			      handle_noreturn_attribute },
110114402Sru  { "noinline",               0, 0, true,  false, false,
111114402Sru			      handle_noinline_attribute },
112114402Sru  { "used",                   0, 0, true,  false, false,
113114402Sru			      handle_used_attribute },
114114402Sru  { "unused",                 0, 0, false, false, false,
115114402Sru			      handle_unused_attribute },
116114402Sru  /* The same comments as for noreturn attributes apply to const ones.  */
117114402Sru  { "const",                  0, 0, true,  false, false,
118114402Sru			      handle_const_attribute },
119114402Sru  { "transparent_union",      0, 0, false, false, false,
120114402Sru			      handle_transparent_union_attribute },
121114402Sru  { "constructor",            0, 0, true,  false, false,
122114402Sru			      handle_constructor_attribute },
123114402Sru  { "destructor",             0, 0, true,  false, false,
124114402Sru			      handle_destructor_attribute },
125114402Sru  { "mode",                   1, 1, false,  true, false,
126114402Sru			      handle_mode_attribute },
127114402Sru  { "section",                1, 1, true,  false, false,
128114402Sru			      handle_section_attribute },
129114402Sru  { "aligned",                0, 1, false, false, false,
130114402Sru			      handle_aligned_attribute },
131114402Sru  { "weak",                   0, 0, true,  false, false,
132114402Sru			      handle_weak_attribute },
133114402Sru  { "alias",                  1, 1, true,  false, false,
134114402Sru			      handle_alias_attribute },
135114402Sru  { "no_instrument_function", 0, 0, true,  false, false,
136114402Sru			      handle_no_instrument_function_attribute },
137114402Sru  { "malloc",                 0, 0, true,  false, false,
138114402Sru			      handle_malloc_attribute },
139114402Sru  { "no_stack_limit",         0, 0, true,  false, false,
140114402Sru			      handle_no_limit_stack_attribute },
141114402Sru  { "pure",                   0, 0, true,  false, false,
142114402Sru			      handle_pure_attribute },
143114402Sru  { "deprecated",             0, 0, false, false, false,
144114402Sru			      handle_deprecated_attribute },
145114402Sru  { "vector_size",	      1, 1, false, true, false,
146114402Sru			      handle_vector_size_attribute },
147114402Sru  { NULL,                     0, 0, false, false, false, NULL }
148114402Sru};
149114402Sru
150114402Sru/* Default empty table of attributes.  */
151114402Srustatic const struct attribute_spec empty_attribute_table[] =
152114402Sru{
153114402Sru  { NULL, 0, 0, false, false, false, NULL }
154114402Sru};
155114402Sru
156114402Sru/* Table of machine-independent attributes for checking formats, if used.  */
157114402Sruconst struct attribute_spec *format_attribute_table = empty_attribute_table;
158114402Sru
159114402Sru/* Table of machine-independent attributes for a particular language.  */
160114402Sruconst struct attribute_spec *lang_attribute_table = empty_attribute_table;
161114402Sru
162114402Sru/* Flag saying whether common language attributes are to be supported.  */
163114402Sruint lang_attribute_common = 1;
164114402Sru
165114402Sru/* Initialize attribute tables, and make some sanity checks
166114402Sru   if --enable-checking.  */
167114402Sru
168114402Srustatic void
169114402Sruinit_attributes ()
170114402Sru{
171114402Sru#ifdef ENABLE_CHECKING
172114402Sru  int i;
173114402Sru#endif
174114402Sru
175114402Sru  attribute_tables[0]
176114402Sru    = lang_attribute_common ? c_common_attribute_table : empty_attribute_table;
177114402Sru  attribute_tables[1] = lang_attribute_table;
178114402Sru  attribute_tables[2] = format_attribute_table;
179114402Sru  attribute_tables[3] = targetm.attribute_table;
180114402Sru
181114402Sru#ifdef ENABLE_CHECKING
182114402Sru  /* Make some sanity checks on the attribute tables.  */
183114402Sru  for (i = 0;
184114402Sru       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
185114402Sru       i++)
186114402Sru    {
187114402Sru      int j;
188114402Sru
189114402Sru      for (j = 0; attribute_tables[i][j].name != NULL; j++)
190114402Sru	{
191114402Sru	  /* The name must not begin and end with __.  */
192114402Sru	  const char *name = attribute_tables[i][j].name;
193114402Sru	  int len = strlen (name);
194114402Sru	  if (name[0] == '_' && name[1] == '_'
195114402Sru	      && name[len - 1] == '_' && name[len - 2] == '_')
196114402Sru	    abort ();
197114402Sru	  /* The minimum and maximum lengths must be consistent.  */
198114402Sru	  if (attribute_tables[i][j].min_length < 0)
199114402Sru	    abort ();
200114402Sru	  if (attribute_tables[i][j].max_length != -1
201114402Sru	      && (attribute_tables[i][j].max_length
202114402Sru		  < attribute_tables[i][j].min_length))
203114402Sru	    abort ();
204114402Sru	  /* An attribute cannot require both a DECL and a TYPE.  */
205114402Sru	  if (attribute_tables[i][j].decl_required
206114402Sru	      && attribute_tables[i][j].type_required)
207114402Sru	    abort ();
208114402Sru	  /* If an attribute requires a function type, in particular
209114402Sru	     it requires a type.  */
210114402Sru	  if (attribute_tables[i][j].function_type_required
211114402Sru	      && !attribute_tables[i][j].type_required)
212114402Sru	    abort ();
213114402Sru	}
214114402Sru    }
215114402Sru
216114402Sru  /* Check that each name occurs just once in each table.  */
217114402Sru  for (i = 0;
218114402Sru       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
219114402Sru       i++)
220114402Sru    {
221114402Sru      int j, k;
222114402Sru      for (j = 0; attribute_tables[i][j].name != NULL; j++)
223114402Sru	for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
224114402Sru	  if (!strcmp (attribute_tables[i][j].name,
225114402Sru		       attribute_tables[i][k].name))
226114402Sru	    abort ();
227114402Sru    }
228114402Sru  /* Check that no name occurs in more than one table.  */
229114402Sru  for (i = 0;
230114402Sru       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
231114402Sru       i++)
232114402Sru    {
233114402Sru      int j, k, l;
234114402Sru
235114402Sru      for (j = i + 1;
236114402Sru	   j < ((int) (sizeof (attribute_tables)
237114402Sru		       / sizeof (attribute_tables[0])));
238114402Sru	   j++)
239114402Sru	for (k = 0; attribute_tables[i][k].name != NULL; k++)
240114402Sru	  for (l = 0; attribute_tables[j][l].name != NULL; l++)
241114402Sru	    if (!strcmp (attribute_tables[i][k].name,
242114402Sru			 attribute_tables[j][l].name))
243114402Sru	      abort ();
244114402Sru    }
245114402Sru#endif
246114402Sru
247114402Sru  attributes_initialized = true;
248114402Sru}
249114402Sru
250114402Sru/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
251114402Sru   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
252114402Sru   it should be modified in place; if a TYPE, a copy should be created
253114402Sru   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
254114402Sru   information, in the form of a bitwise OR of flags in enum attribute_flags
255114402Sru   from tree.h.  Depending on these flags, some attributes may be
256114402Sru   returned to be applied at a later stage (for example, to apply
257114402Sru   a decl attribute to the declaration rather than to its type).  If
258114402Sru   ATTR_FLAG_BUILT_IN is not set and *NODE is a DECL, then also consider
259114402Sru   whether there might be some default attributes to apply to this DECL;
260114402Sru   if so, decl_attributes will be called recursively with those attributes
261114402Sru   and ATTR_FLAG_BUILT_IN set.  */
262114402Sru
263114402Srutree
264114402Srudecl_attributes (node, attributes, flags)
265114402Sru     tree *node, attributes;
266114402Sru     int flags;
267114402Sru{
268114402Sru  tree a;
269114402Sru  tree returned_attrs = NULL_TREE;
270114402Sru
271114402Sru  if (!attributes_initialized)
272114402Sru    init_attributes ();
273114402Sru
274114402Sru  (*targetm.insert_attributes) (*node, &attributes);
275114402Sru
276114402Sru  if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL
277114402Sru      && !(flags & (int) ATTR_FLAG_BUILT_IN))
278114402Sru    insert_default_attributes (*node);
279114402Sru
280114402Sru  for (a = attributes; a; a = TREE_CHAIN (a))
281114402Sru    {
282114402Sru      tree name = TREE_PURPOSE (a);
283114402Sru      tree args = TREE_VALUE (a);
284114402Sru      tree *anode = node;
285114402Sru      const struct attribute_spec *spec = NULL;
286114402Sru      bool no_add_attrs = 0;
287114402Sru      int i;
288114402Sru
289114402Sru      for (i = 0;
290114402Sru	   i < ((int) (sizeof (attribute_tables)
291114402Sru		       / sizeof (attribute_tables[0])));
292114402Sru	   i++)
293114402Sru	{
294114402Sru	  int j;
295114402Sru
296114402Sru	  for (j = 0; attribute_tables[i][j].name != NULL; j++)
297114402Sru	    {
298114402Sru	      if (is_attribute_p (attribute_tables[i][j].name, name))
299114402Sru		{
300114402Sru		  spec = &attribute_tables[i][j];
301114402Sru		  break;
302114402Sru		}
303114402Sru	    }
304114402Sru	  if (spec != NULL)
305114402Sru	    break;
306114402Sru	}
307114402Sru
308114402Sru      if (spec == NULL)
309114402Sru	{
310114402Sru	  warning ("`%s' attribute directive ignored",
311114402Sru		   IDENTIFIER_POINTER (name));
312114402Sru	  continue;
313114402Sru	}
314114402Sru      else if (list_length (args) < spec->min_length
315114402Sru	       || (spec->max_length >= 0
316114402Sru		   && list_length (args) > spec->max_length))
317114402Sru	{
318114402Sru	  error ("wrong number of arguments specified for `%s' attribute",
319114402Sru		 IDENTIFIER_POINTER (name));
320114402Sru	  continue;
321114402Sru	}
322114402Sru
323114402Sru      if (spec->decl_required && !DECL_P (*anode))
324114402Sru	{
325114402Sru	  if (flags & ((int) ATTR_FLAG_DECL_NEXT
326114402Sru		       | (int) ATTR_FLAG_FUNCTION_NEXT
327114402Sru		       | (int) ATTR_FLAG_ARRAY_NEXT))
328114402Sru	    {
329114402Sru	      /* Pass on this attribute to be tried again.  */
330114402Sru	      returned_attrs = tree_cons (name, args, returned_attrs);
331114402Sru	      continue;
332114402Sru	    }
333114402Sru	  else
334114402Sru	    {
335114402Sru	      warning ("`%s' attribute does not apply to types",
336114402Sru		       IDENTIFIER_POINTER (name));
337114402Sru	      continue;
338114402Sru	    }
339114402Sru	}
340114402Sru
341114402Sru      /* If we require a type, but were passed a decl, set up to make a
342114402Sru	 new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
343114402Sru	 would have applied if we'd been passed a type, but we cannot modify
344114402Sru	 the decl's type in place here.  */
345114402Sru      if (spec->type_required && DECL_P (*anode))
346114402Sru	{
347114402Sru	  anode = &TREE_TYPE (*anode);
348114402Sru	  flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
349114402Sru	}
350114402Sru
351114402Sru      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
352114402Sru	  && TREE_CODE (*anode) != METHOD_TYPE)
353114402Sru	{
354114402Sru	  if (TREE_CODE (*anode) == POINTER_TYPE
355114402Sru	      && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
356114402Sru		  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
357114402Sru	    {
358114402Sru	      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
359114402Sru		*anode = build_type_copy (*anode);
360114402Sru	      anode = &TREE_TYPE (*anode);
361114402Sru	    }
362114402Sru	  else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
363114402Sru	    {
364114402Sru	      /* Pass on this attribute to be tried again.  */
365114402Sru	      returned_attrs = tree_cons (name, args, returned_attrs);
366114402Sru	      continue;
367114402Sru	    }
368114402Sru
369114402Sru	  if (TREE_CODE (*anode) != FUNCTION_TYPE
370114402Sru	      && TREE_CODE (*anode) != METHOD_TYPE)
371114402Sru	    {
372114402Sru	      warning ("`%s' attribute only applies to function types",
373114402Sru		       IDENTIFIER_POINTER (name));
374114402Sru	      continue;
375114402Sru	    }
376114402Sru	}
377114402Sru
378114402Sru      if (spec->handler != NULL)
379114402Sru	returned_attrs = chainon ((*spec->handler) (anode, name, args,
380114402Sru						    flags, &no_add_attrs),
381114402Sru				  returned_attrs);
382114402Sru
383114402Sru      /* Layout the decl in case anything changed.  */
384114402Sru      if (spec->type_required && DECL_P (*node)
385114402Sru	  && TREE_CODE (*node) == VAR_DECL)
386114402Sru	{
387114402Sru	  /* Force a recalculation of mode and size.  */
388114402Sru	  DECL_MODE (*node) = VOIDmode;
389114402Sru	  DECL_SIZE (*node) = 0;
390114402Sru
391114402Sru	  layout_decl (*node, 0);
392114402Sru	}
393114402Sru
394114402Sru      if (!no_add_attrs)
395114402Sru	{
396114402Sru	  tree old_attrs;
397114402Sru	  tree a;
398114402Sru
399114402Sru	  if (DECL_P (*anode))
400114402Sru	    old_attrs = DECL_ATTRIBUTES (*anode);
401114402Sru	  else
402114402Sru	    old_attrs = TYPE_ATTRIBUTES (*anode);
403114402Sru
404114402Sru	  for (a = lookup_attribute (spec->name, old_attrs);
405114402Sru	       a != NULL_TREE;
406114402Sru	       a = lookup_attribute (spec->name, TREE_CHAIN (a)))
407114402Sru	    {
408114402Sru	      if (simple_cst_equal (TREE_VALUE (a), args) == 1)
409114402Sru		break;
410114402Sru	    }
411114402Sru
412114402Sru	  if (a == NULL_TREE)
413114402Sru	    {
414114402Sru	      /* This attribute isn't already in the list.  */
415114402Sru	      if (DECL_P (*anode))
416114402Sru		DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
417114402Sru	      else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
418114402Sru		TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
419114402Sru	      else
420114402Sru		*anode = build_type_attribute_variant (*anode,
421114402Sru						       tree_cons (name, args,
422114402Sru								  old_attrs));
423114402Sru	    }
424114402Sru	}
425114402Sru    }
426114402Sru
427114402Sru  return returned_attrs;
428114402Sru}
429114402Sru
430114402Sru/* Handle a "packed" attribute; arguments as in
431114402Sru   struct attribute_spec.handler.  */
432114402Sru
433114402Srustatic tree
434114402Sruhandle_packed_attribute (node, name, args, flags, no_add_attrs)
435114402Sru     tree *node;
436114402Sru     tree name;
437114402Sru     tree args ATTRIBUTE_UNUSED;
438114402Sru     int flags;
439114402Sru     bool *no_add_attrs;
440114402Sru{
441114402Sru  tree *type = NULL;
442114402Sru  if (DECL_P (*node))
443114402Sru    {
444114402Sru      if (TREE_CODE (*node) == TYPE_DECL)
445114402Sru	type = &TREE_TYPE (*node);
446114402Sru    }
447114402Sru  else
448114402Sru    type = node;
449114402Sru
450114402Sru  if (type)
451114402Sru    {
452114402Sru      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
453114402Sru	*type = build_type_copy (*type);
454114402Sru      TYPE_PACKED (*type) = 1;
455114402Sru    }
456114402Sru  else if (TREE_CODE (*node) == FIELD_DECL)
457114402Sru    DECL_PACKED (*node) = 1;
458114402Sru  /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
459114402Sru     used for DECL_REGISTER.  It wouldn't mean anything anyway.  */
460114402Sru  else
461114402Sru    {
462114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
463114402Sru      *no_add_attrs = true;
464114402Sru    }
465114402Sru
466114402Sru  return NULL_TREE;
467114402Sru}
468114402Sru
469114402Sru/* Handle a "nocommon" attribute; arguments as in
470114402Sru   struct attribute_spec.handler.  */
471114402Sru
472114402Srustatic tree
473114402Sruhandle_nocommon_attribute (node, name, args, flags, no_add_attrs)
474114402Sru     tree *node;
475114402Sru     tree name;
476114402Sru     tree args ATTRIBUTE_UNUSED;
477114402Sru     int flags ATTRIBUTE_UNUSED;
478114402Sru     bool *no_add_attrs;
479114402Sru{
480114402Sru  if (TREE_CODE (*node) == VAR_DECL)
481114402Sru    DECL_COMMON (*node) = 0;
482114402Sru  else
483114402Sru    {
484114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
485114402Sru      *no_add_attrs = true;
486114402Sru    }
487114402Sru
488114402Sru  return NULL_TREE;
489114402Sru}
490114402Sru
491114402Sru/* Handle a "common" attribute; arguments as in
492114402Sru   struct attribute_spec.handler.  */
493114402Sru
494114402Srustatic tree
495114402Sruhandle_common_attribute (node, name, args, flags, no_add_attrs)
496114402Sru     tree *node;
497114402Sru     tree name;
498114402Sru     tree args ATTRIBUTE_UNUSED;
499114402Sru     int flags ATTRIBUTE_UNUSED;
500114402Sru     bool *no_add_attrs;
501114402Sru{
502114402Sru  if (TREE_CODE (*node) == VAR_DECL)
503114402Sru    DECL_COMMON (*node) = 1;
504114402Sru  else
505114402Sru    {
506114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
507114402Sru      *no_add_attrs = true;
508114402Sru    }
509114402Sru
510114402Sru  return NULL_TREE;
511114402Sru}
512114402Sru
513114402Sru/* Handle a "noreturn" attribute; arguments as in
514114402Sru   struct attribute_spec.handler.  */
515114402Sru
516114402Srustatic tree
517114402Sruhandle_noreturn_attribute (node, name, args, flags, no_add_attrs)
518114402Sru     tree *node;
519114402Sru     tree name;
520114402Sru     tree args ATTRIBUTE_UNUSED;
521114402Sru     int flags ATTRIBUTE_UNUSED;
522114402Sru     bool *no_add_attrs;
523114402Sru{
524114402Sru  tree type = TREE_TYPE (*node);
525114402Sru
526114402Sru  /* See FIXME comment in c_common_attribute_table.  */
527114402Sru  if (TREE_CODE (*node) == FUNCTION_DECL)
528114402Sru    TREE_THIS_VOLATILE (*node) = 1;
529114402Sru  else if (TREE_CODE (type) == POINTER_TYPE
530114402Sru	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
531114402Sru    TREE_TYPE (*node)
532114402Sru      = build_pointer_type
533114402Sru	(build_type_variant (TREE_TYPE (type),
534114402Sru			     TREE_READONLY (TREE_TYPE (type)), 1));
535114402Sru  else
536114402Sru    {
537114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
538114402Sru      *no_add_attrs = true;
539114402Sru    }
540114402Sru
541114402Sru  return NULL_TREE;
542114402Sru}
543114402Sru
544114402Sru/* Handle a "noinline" attribute; arguments as in
545114402Sru   struct attribute_spec.handler.  */
546114402Sru
547114402Srustatic tree
548114402Sruhandle_noinline_attribute (node, name, args, flags, no_add_attrs)
549114402Sru     tree *node;
550114402Sru     tree name;
551114402Sru     tree args ATTRIBUTE_UNUSED;
552114402Sru     int flags ATTRIBUTE_UNUSED;
553114402Sru     bool *no_add_attrs;
554114402Sru{
555114402Sru  if (TREE_CODE (*node) == FUNCTION_DECL)
556114402Sru    DECL_UNINLINABLE (*node) = 1;
557114402Sru  else
558114402Sru    {
559114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
560114402Sru      *no_add_attrs = true;
561114402Sru    }
562114402Sru
563114402Sru  return NULL_TREE;
564114402Sru}
565114402Sru
566114402Sru/* Handle a "used" attribute; arguments as in
567114402Sru   struct attribute_spec.handler.  */
568114402Sru
569114402Srustatic tree
570114402Sruhandle_used_attribute (node, name, args, flags, no_add_attrs)
571114402Sru     tree *node;
572114402Sru     tree name;
573114402Sru     tree args ATTRIBUTE_UNUSED;
574114402Sru     int flags ATTRIBUTE_UNUSED;
575114402Sru     bool *no_add_attrs;
576114402Sru{
577114402Sru  if (TREE_CODE (*node) == FUNCTION_DECL)
578114402Sru    TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
579114402Sru      = TREE_USED (*node) = 1;
580114402Sru  else
581114402Sru    {
582114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
583114402Sru      *no_add_attrs = true;
584114402Sru    }
585114402Sru
586114402Sru  return NULL_TREE;
587114402Sru}
588114402Sru
589114402Sru/* Handle a "unused" attribute; arguments as in
590114402Sru   struct attribute_spec.handler.  */
591114402Sru
592114402Srustatic tree
593114402Sruhandle_unused_attribute (node, name, args, flags, no_add_attrs)
594114402Sru     tree *node;
595114402Sru     tree name;
596114402Sru     tree args ATTRIBUTE_UNUSED;
597114402Sru     int flags;
598114402Sru     bool *no_add_attrs;
599114402Sru{
600114402Sru  if (DECL_P (*node))
601114402Sru    {
602114402Sru      tree decl = *node;
603114402Sru
604114402Sru      if (TREE_CODE (decl) == PARM_DECL
605114402Sru	  || TREE_CODE (decl) == VAR_DECL
606114402Sru	  || TREE_CODE (decl) == FUNCTION_DECL
607114402Sru	  || TREE_CODE (decl) == LABEL_DECL
608114402Sru	  || TREE_CODE (decl) == TYPE_DECL)
609114402Sru	TREE_USED (decl) = 1;
610114402Sru      else
611114402Sru	{
612114402Sru	  warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
613114402Sru	  *no_add_attrs = true;
614114402Sru	}
615114402Sru    }
616114402Sru  else
617114402Sru    {
618114402Sru      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
619114402Sru	*node = build_type_copy (*node);
620114402Sru      TREE_USED (*node) = 1;
621114402Sru    }
622114402Sru
623114402Sru  return NULL_TREE;
624114402Sru}
625114402Sru
626114402Sru/* Handle a "const" attribute; arguments as in
627114402Sru   struct attribute_spec.handler.  */
628114402Sru
629114402Srustatic tree
630114402Sruhandle_const_attribute (node, name, args, flags, no_add_attrs)
631114402Sru     tree *node;
632114402Sru     tree name;
633114402Sru     tree args ATTRIBUTE_UNUSED;
634114402Sru     int flags ATTRIBUTE_UNUSED;
635114402Sru     bool *no_add_attrs;
636114402Sru{
637114402Sru  tree type = TREE_TYPE (*node);
638114402Sru
639114402Sru  /* See FIXME comment on noreturn in c_common_attribute_table.  */
640114402Sru  if (TREE_CODE (*node) == FUNCTION_DECL)
641114402Sru    TREE_READONLY (*node) = 1;
642114402Sru  else if (TREE_CODE (type) == POINTER_TYPE
643114402Sru	   && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
644114402Sru    TREE_TYPE (*node)
645114402Sru      = build_pointer_type
646114402Sru	(build_type_variant (TREE_TYPE (type), 1,
647114402Sru			     TREE_THIS_VOLATILE (TREE_TYPE (type))));
648114402Sru  else
649114402Sru    {
650114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
651114402Sru      *no_add_attrs = true;
652114402Sru    }
653114402Sru
654114402Sru  return NULL_TREE;
655114402Sru}
656114402Sru
657114402Sru/* Handle a "transparent_union" attribute; arguments as in
658114402Sru   struct attribute_spec.handler.  */
659114402Sru
660114402Srustatic tree
661114402Sruhandle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
662114402Sru     tree *node;
663114402Sru     tree name;
664114402Sru     tree args ATTRIBUTE_UNUSED;
665114402Sru     int flags;
666114402Sru     bool *no_add_attrs;
667114402Sru{
668114402Sru  tree decl = NULL_TREE;
669151497Sru  tree *type = NULL;
670114402Sru  int is_type = 0;
671114402Sru
672114402Sru  if (DECL_P (*node))
673114402Sru    {
674114402Sru      decl = *node;
675114402Sru      type = &TREE_TYPE (decl);
676114402Sru      is_type = TREE_CODE (*node) == TYPE_DECL;
677114402Sru    }
678114402Sru  else if (TYPE_P (*node))
679114402Sru    type = node, is_type = 1;
680114402Sru
681114402Sru  if (is_type
682114402Sru      && TREE_CODE (*type) == UNION_TYPE
683114402Sru      && (decl == 0
684114402Sru	  || (TYPE_FIELDS (*type) != 0
685114402Sru	      && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
686114402Sru    {
687114402Sru      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
688114402Sru	*type = build_type_copy (*type);
689114402Sru      TYPE_TRANSPARENT_UNION (*type) = 1;
690114402Sru    }
691114402Sru  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
692114402Sru	   && TREE_CODE (*type) == UNION_TYPE
693114402Sru	   && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
694114402Sru    DECL_TRANSPARENT_UNION (decl) = 1;
695114402Sru  else
696114402Sru    {
697114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
698114402Sru      *no_add_attrs = true;
699114402Sru    }
700114402Sru
701114402Sru  return NULL_TREE;
702114402Sru}
703114402Sru
704114402Sru/* Handle a "constructor" attribute; arguments as in
705114402Sru   struct attribute_spec.handler.  */
706114402Sru
707114402Srustatic tree
708114402Sruhandle_constructor_attribute (node, name, args, flags, no_add_attrs)
709114402Sru     tree *node;
710114402Sru     tree name;
711114402Sru     tree args ATTRIBUTE_UNUSED;
712114402Sru     int flags ATTRIBUTE_UNUSED;
713114402Sru     bool *no_add_attrs;
714114402Sru{
715114402Sru  tree decl = *node;
716114402Sru  tree type = TREE_TYPE (decl);
717114402Sru
718114402Sru  if (TREE_CODE (decl) == FUNCTION_DECL
719114402Sru      && TREE_CODE (type) == FUNCTION_TYPE
720114402Sru      && decl_function_context (decl) == 0)
721114402Sru    {
722114402Sru      DECL_STATIC_CONSTRUCTOR (decl) = 1;
723114402Sru      TREE_USED (decl) = 1;
724114402Sru    }
725114402Sru  else
726114402Sru    {
727114402Sru      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
728114402Sru      *no_add_attrs = true;
729114402Sru    }
730114402Sru
731114402Sru  return NULL_TREE;
732114402Sru}
733
734/* Handle a "destructor" attribute; arguments as in
735   struct attribute_spec.handler.  */
736
737static tree
738handle_destructor_attribute (node, name, args, flags, no_add_attrs)
739     tree *node;
740     tree name;
741     tree args ATTRIBUTE_UNUSED;
742     int flags ATTRIBUTE_UNUSED;
743     bool *no_add_attrs;
744{
745  tree decl = *node;
746  tree type = TREE_TYPE (decl);
747
748  if (TREE_CODE (decl) == FUNCTION_DECL
749      && TREE_CODE (type) == FUNCTION_TYPE
750      && decl_function_context (decl) == 0)
751    {
752      DECL_STATIC_DESTRUCTOR (decl) = 1;
753      TREE_USED (decl) = 1;
754    }
755  else
756    {
757      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
758      *no_add_attrs = true;
759    }
760
761  return NULL_TREE;
762}
763
764/* Handle a "mode" attribute; arguments as in
765   struct attribute_spec.handler.  */
766
767static tree
768handle_mode_attribute (node, name, args, flags, no_add_attrs)
769     tree *node;
770     tree name;
771     tree args;
772     int flags ATTRIBUTE_UNUSED;
773     bool *no_add_attrs;
774{
775  tree type = *node;
776
777  *no_add_attrs = true;
778
779  if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
780    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
781  else
782    {
783      int j;
784      const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
785      int len = strlen (p);
786      enum machine_mode mode = VOIDmode;
787      tree typefm;
788
789      if (len > 4 && p[0] == '_' && p[1] == '_'
790	  && p[len - 1] == '_' && p[len - 2] == '_')
791	{
792	  char *newp = (char *) alloca (len - 1);
793
794	  strcpy (newp, &p[2]);
795	  newp[len - 4] = '\0';
796	  p = newp;
797	}
798
799      /* Change this type to have a type with the specified mode.
800	 First check for the special modes.  */
801      if (! strcmp (p, "byte"))
802	mode = byte_mode;
803      else if (!strcmp (p, "word"))
804	mode = word_mode;
805      else if (! strcmp (p, "pointer"))
806	mode = ptr_mode;
807      else
808	for (j = 0; j < NUM_MACHINE_MODES; j++)
809	  if (!strcmp (p, GET_MODE_NAME (j)))
810	    mode = (enum machine_mode) j;
811
812      if (mode == VOIDmode)
813	error ("unknown machine mode `%s'", p);
814      else if (0 == (typefm = type_for_mode (mode,
815					     TREE_UNSIGNED (type))))
816	error ("no data type for mode `%s'", p);
817      else
818	*node = typefm;
819        /* No need to layout the type here.  The caller should do this.  */
820    }
821
822  return NULL_TREE;
823}
824
825/* Handle a "section" attribute; arguments as in
826   struct attribute_spec.handler.  */
827
828static tree
829handle_section_attribute (node, name, args, flags, no_add_attrs)
830     tree *node;
831     tree name ATTRIBUTE_UNUSED;
832     tree args;
833     int flags ATTRIBUTE_UNUSED;
834     bool *no_add_attrs;
835{
836  tree decl = *node;
837
838  if (targetm.have_named_sections)
839    {
840      if ((TREE_CODE (decl) == FUNCTION_DECL
841	   || TREE_CODE (decl) == VAR_DECL)
842	  && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
843	{
844	  if (TREE_CODE (decl) == VAR_DECL
845	      && current_function_decl != NULL_TREE
846	      && ! TREE_STATIC (decl))
847	    {
848	      error_with_decl (decl,
849			       "section attribute cannot be specified for local variables");
850	      *no_add_attrs = true;
851	    }
852
853	  /* The decl may have already been given a section attribute
854	     from a previous declaration.  Ensure they match.  */
855	  else if (DECL_SECTION_NAME (decl) != NULL_TREE
856		   && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
857			      TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
858	    {
859	      error_with_decl (*node,
860			       "section of `%s' conflicts with previous declaration");
861	      *no_add_attrs = true;
862	    }
863	  else
864	    DECL_SECTION_NAME (decl) = TREE_VALUE (args);
865	}
866      else
867	{
868	  error_with_decl (*node,
869			   "section attribute not allowed for `%s'");
870	  *no_add_attrs = true;
871	}
872    }
873  else
874    {
875      error_with_decl (*node,
876		       "section attributes are not supported for this target");
877      *no_add_attrs = true;
878    }
879
880  return NULL_TREE;
881}
882
883/* Handle a "aligned" attribute; arguments as in
884   struct attribute_spec.handler.  */
885
886static tree
887handle_aligned_attribute (node, name, args, flags, no_add_attrs)
888     tree *node;
889     tree name ATTRIBUTE_UNUSED;
890     tree args;
891     int flags;
892     bool *no_add_attrs;
893{
894  tree decl = NULL_TREE;
895  tree *type = NULL;
896  int is_type = 0;
897  tree align_expr = (args ? TREE_VALUE (args)
898		     : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
899  int i;
900
901  if (DECL_P (*node))
902    {
903      decl = *node;
904      type = &TREE_TYPE (decl);
905      is_type = TREE_CODE (*node) == TYPE_DECL;
906    }
907  else if (TYPE_P (*node))
908    type = node, is_type = 1;
909
910  /* Strip any NOPs of any kind.  */
911  while (TREE_CODE (align_expr) == NOP_EXPR
912	 || TREE_CODE (align_expr) == CONVERT_EXPR
913	 || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
914    align_expr = TREE_OPERAND (align_expr, 0);
915
916  if (TREE_CODE (align_expr) != INTEGER_CST)
917    {
918      error ("requested alignment is not a constant");
919      *no_add_attrs = true;
920    }
921  else if ((i = tree_log2 (align_expr)) == -1)
922    {
923      error ("requested alignment is not a power of 2");
924      *no_add_attrs = true;
925    }
926  else if (i > HOST_BITS_PER_INT - 2)
927    {
928      error ("requested alignment is too large");
929      *no_add_attrs = true;
930    }
931  else if (is_type)
932    {
933      /* If we have a TYPE_DECL, then copy the type, so that we
934	 don't accidentally modify a builtin type.  See pushdecl.  */
935      if (decl && TREE_TYPE (decl) != error_mark_node
936	  && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
937	{
938	  tree tt = TREE_TYPE (decl);
939	  *type = build_type_copy (*type);
940	  DECL_ORIGINAL_TYPE (decl) = tt;
941	  TYPE_NAME (*type) = decl;
942	  TREE_USED (*type) = TREE_USED (decl);
943	  TREE_TYPE (decl) = *type;
944	}
945      else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
946	*type = build_type_copy (*type);
947
948      TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
949      TYPE_USER_ALIGN (*type) = 1;
950    }
951  else if (TREE_CODE (decl) != VAR_DECL
952	   && TREE_CODE (decl) != FIELD_DECL)
953    {
954      error_with_decl (decl,
955		       "alignment may not be specified for `%s'");
956      *no_add_attrs = true;
957    }
958  else
959    {
960      DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
961      DECL_USER_ALIGN (decl) = 1;
962    }
963
964  return NULL_TREE;
965}
966
967/* Handle a "weak" attribute; arguments as in
968   struct attribute_spec.handler.  */
969
970static tree
971handle_weak_attribute (node, name, args, flags, no_add_attrs)
972     tree *node;
973     tree name ATTRIBUTE_UNUSED;
974     tree args ATTRIBUTE_UNUSED;
975     int flags ATTRIBUTE_UNUSED;
976     bool *no_add_attrs ATTRIBUTE_UNUSED;
977{
978  declare_weak (*node);
979
980  return NULL_TREE;
981}
982
983/* Handle an "alias" attribute; arguments as in
984   struct attribute_spec.handler.  */
985
986static tree
987handle_alias_attribute (node, name, args, flags, no_add_attrs)
988     tree *node;
989     tree name;
990     tree args;
991     int flags ATTRIBUTE_UNUSED;
992     bool *no_add_attrs;
993{
994  tree decl = *node;
995
996  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
997      || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
998    {
999      error_with_decl (decl,
1000		       "`%s' defined both normally and as an alias");
1001      *no_add_attrs = true;
1002    }
1003  else if (decl_function_context (decl) == 0)
1004    {
1005      tree id;
1006
1007      id = TREE_VALUE (args);
1008      if (TREE_CODE (id) != STRING_CST)
1009	{
1010	  error ("alias arg not a string");
1011	  *no_add_attrs = true;
1012	  return NULL_TREE;
1013	}
1014      id = get_identifier (TREE_STRING_POINTER (id));
1015      /* This counts as a use of the object pointed to.  */
1016      TREE_USED (id) = 1;
1017
1018      if (TREE_CODE (decl) == FUNCTION_DECL)
1019	DECL_INITIAL (decl) = error_mark_node;
1020      else
1021	DECL_EXTERNAL (decl) = 0;
1022      assemble_alias (decl, id);
1023    }
1024  else
1025    {
1026      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1027      *no_add_attrs = true;
1028    }
1029
1030  return NULL_TREE;
1031}
1032
1033/* Handle a "no_instrument_function" attribute; arguments as in
1034   struct attribute_spec.handler.  */
1035
1036static tree
1037handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
1038     tree *node;
1039     tree name;
1040     tree args ATTRIBUTE_UNUSED;
1041     int flags ATTRIBUTE_UNUSED;
1042     bool *no_add_attrs;
1043{
1044  tree decl = *node;
1045
1046  if (TREE_CODE (decl) != FUNCTION_DECL)
1047    {
1048      error_with_decl (decl,
1049		       "`%s' attribute applies only to functions",
1050		       IDENTIFIER_POINTER (name));
1051      *no_add_attrs = true;
1052    }
1053  else if (DECL_INITIAL (decl))
1054    {
1055      error_with_decl (decl,
1056		       "can't set `%s' attribute after definition",
1057		       IDENTIFIER_POINTER (name));
1058      *no_add_attrs = true;
1059    }
1060  else
1061    DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1062
1063  return NULL_TREE;
1064}
1065
1066/* Handle a "malloc" attribute; arguments as in
1067   struct attribute_spec.handler.  */
1068
1069static tree
1070handle_malloc_attribute (node, name, args, flags, no_add_attrs)
1071     tree *node;
1072     tree name;
1073     tree args ATTRIBUTE_UNUSED;
1074     int flags ATTRIBUTE_UNUSED;
1075     bool *no_add_attrs;
1076{
1077  if (TREE_CODE (*node) == FUNCTION_DECL)
1078    DECL_IS_MALLOC (*node) = 1;
1079  /* ??? TODO: Support types.  */
1080  else
1081    {
1082      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1083      *no_add_attrs = true;
1084    }
1085
1086  return NULL_TREE;
1087}
1088
1089/* Handle a "no_limit_stack" attribute; arguments as in
1090   struct attribute_spec.handler.  */
1091
1092static tree
1093handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
1094     tree *node;
1095     tree name;
1096     tree args ATTRIBUTE_UNUSED;
1097     int flags ATTRIBUTE_UNUSED;
1098     bool *no_add_attrs;
1099{
1100  tree decl = *node;
1101
1102  if (TREE_CODE (decl) != FUNCTION_DECL)
1103    {
1104      error_with_decl (decl,
1105		       "`%s' attribute applies only to functions",
1106		       IDENTIFIER_POINTER (name));
1107      *no_add_attrs = true;
1108    }
1109  else if (DECL_INITIAL (decl))
1110    {
1111      error_with_decl (decl,
1112		       "can't set `%s' attribute after definition",
1113		       IDENTIFIER_POINTER (name));
1114      *no_add_attrs = true;
1115    }
1116  else
1117    DECL_NO_LIMIT_STACK (decl) = 1;
1118
1119  return NULL_TREE;
1120}
1121
1122/* Handle a "pure" attribute; arguments as in
1123   struct attribute_spec.handler.  */
1124
1125static tree
1126handle_pure_attribute (node, name, args, flags, no_add_attrs)
1127     tree *node;
1128     tree name;
1129     tree args ATTRIBUTE_UNUSED;
1130     int flags ATTRIBUTE_UNUSED;
1131     bool *no_add_attrs;
1132{
1133  if (TREE_CODE (*node) == FUNCTION_DECL)
1134    DECL_IS_PURE (*node) = 1;
1135  /* ??? TODO: Support types.  */
1136  else
1137    {
1138      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1139      *no_add_attrs = true;
1140    }
1141
1142  return NULL_TREE;
1143}
1144
1145/* Handle a "deprecated" attribute; arguments as in
1146   struct attribute_spec.handler.  */
1147
1148static tree
1149handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
1150     tree *node;
1151     tree name;
1152     tree args ATTRIBUTE_UNUSED;
1153     int flags;
1154     bool *no_add_attrs;
1155{
1156  tree type = NULL_TREE;
1157  int warn = 0;
1158  const char *what = NULL;
1159
1160  if (DECL_P (*node))
1161    {
1162      tree decl = *node;
1163      type = TREE_TYPE (decl);
1164
1165      if (TREE_CODE (decl) == TYPE_DECL
1166	  || TREE_CODE (decl) == PARM_DECL
1167	  || TREE_CODE (decl) == VAR_DECL
1168	  || TREE_CODE (decl) == FUNCTION_DECL
1169	  || TREE_CODE (decl) == FIELD_DECL)
1170	TREE_DEPRECATED (decl) = 1;
1171      else
1172	warn = 1;
1173    }
1174  else if (TYPE_P (*node))
1175    {
1176      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1177	*node = build_type_copy (*node);
1178      TREE_DEPRECATED (*node) = 1;
1179      type = *node;
1180    }
1181  else
1182    warn = 1;
1183
1184  if (warn)
1185    {
1186      *no_add_attrs = true;
1187      if (type && TYPE_NAME (type))
1188	{
1189	  if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
1190	    what = IDENTIFIER_POINTER (TYPE_NAME (*node));
1191	  else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
1192		   && DECL_NAME (TYPE_NAME (type)))
1193	    what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
1194	}
1195      if (what)
1196	warning ("`%s' attribute ignored for `%s'",
1197		  IDENTIFIER_POINTER (name), what);
1198      else
1199	warning ("`%s' attribute ignored",
1200		      IDENTIFIER_POINTER (name));
1201    }
1202
1203  return NULL_TREE;
1204}
1205
1206/* Handle a "vector_size" attribute; arguments as in
1207   struct attribute_spec.handler.  */
1208
1209static tree
1210handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
1211     tree *node;
1212     tree name;
1213     tree args;
1214     int flags ATTRIBUTE_UNUSED;
1215     bool *no_add_attrs;
1216{
1217  unsigned HOST_WIDE_INT vecsize, nunits;
1218  enum machine_mode mode, orig_mode, new_mode;
1219  tree type = *node, new_type;
1220
1221  *no_add_attrs = true;
1222
1223  if (! host_integerp (TREE_VALUE (args), 1))
1224    {
1225      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1226      return NULL_TREE;
1227    }
1228
1229  /* Get the vector size (in bytes).  */
1230  vecsize = tree_low_cst (TREE_VALUE (args), 1);
1231
1232  /* We need to provide for vector pointers, vector arrays, and
1233     functions returning vectors.  For example:
1234
1235       __attribute__((vector_size(16))) short *foo;
1236
1237     In this case, the mode is SI, but the type being modified is
1238     HI, so we need to look further.  */
1239
1240  while (POINTER_TYPE_P (type)
1241	 || TREE_CODE (type) == FUNCTION_TYPE
1242	 || TREE_CODE (type) == ARRAY_TYPE)
1243    type = TREE_TYPE (type);
1244
1245  /* Get the mode of the type being modified.  */
1246  orig_mode = TYPE_MODE (type);
1247
1248  if (TREE_CODE (type) == RECORD_TYPE
1249      || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
1250	  && GET_MODE_CLASS (orig_mode) != MODE_INT)
1251      || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1252    {
1253      error ("invalid vector type for attribute `%s'",
1254	     IDENTIFIER_POINTER (name));
1255      return NULL_TREE;
1256    }
1257
1258  /* Calculate how many units fit in the vector.  */
1259  nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
1260
1261  /* Find a suitably sized vector.  */
1262  new_mode = VOIDmode;
1263  for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
1264					? MODE_VECTOR_INT
1265					: MODE_VECTOR_FLOAT);
1266       mode != VOIDmode;
1267       mode = GET_MODE_WIDER_MODE (mode))
1268    if (vecsize == GET_MODE_SIZE (mode)
1269	&& nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
1270      {
1271	new_mode = mode;
1272	break;
1273      }
1274
1275  if (new_mode == VOIDmode)
1276    error ("no vector mode with the size and type specified could be found");
1277  else
1278    {
1279      new_type = type_for_mode (new_mode, TREE_UNSIGNED (type));
1280      if (!new_type)
1281	error ("no vector mode with the size and type specified could be found");
1282      else
1283	/* Build back pointers if needed.  */
1284	*node = vector_size_helper (*node, new_type);
1285    }
1286
1287  return NULL_TREE;
1288}
1289
1290/* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
1291   better way.
1292
1293   If we requested a pointer to a vector, build up the pointers that
1294   we stripped off while looking for the inner type.  Similarly for
1295   return values from functions.
1296
1297   The argument "type" is the top of the chain, and "bottom" is the
1298   new type which we will point to.  */
1299
1300static tree
1301vector_size_helper (type, bottom)
1302     tree type, bottom;
1303{
1304  tree inner, outer;
1305
1306  if (POINTER_TYPE_P (type))
1307    {
1308      inner = vector_size_helper (TREE_TYPE (type), bottom);
1309      outer = build_pointer_type (inner);
1310    }
1311  else if (TREE_CODE (type) == ARRAY_TYPE)
1312    {
1313      inner = vector_size_helper (TREE_TYPE (type), bottom);
1314      outer = build_array_type (inner, TYPE_VALUES (type));
1315    }
1316  else if (TREE_CODE (type) == FUNCTION_TYPE)
1317    {
1318      inner = vector_size_helper (TREE_TYPE (type), bottom);
1319      outer = build_function_type (inner, TYPE_VALUES (type));
1320    }
1321  else
1322    return bottom;
1323
1324  TREE_READONLY (outer) = TREE_READONLY (type);
1325  TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
1326
1327  return outer;
1328}
1329
1330/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
1331   lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
1332
1333   The head of the declspec list is stored in DECLSPECS.
1334   The head of the attribute list is stored in PREFIX_ATTRIBUTES.
1335
1336   Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
1337   the list elements.  We drop the containing TREE_LIST nodes and link the
1338   resulting attributes together the way decl_attributes expects them.  */
1339
1340void
1341split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
1342     tree specs_attrs;
1343     tree *declspecs, *prefix_attributes;
1344{
1345  tree t, s, a, next, specs, attrs;
1346
1347  /* This can happen after an __extension__ in pedantic mode.  */
1348  if (specs_attrs != NULL_TREE
1349      && TREE_CODE (specs_attrs) == INTEGER_CST)
1350    {
1351      *declspecs = NULL_TREE;
1352      *prefix_attributes = NULL_TREE;
1353      return;
1354    }
1355
1356  /* This can happen in c++ (eg: decl: typespec initdecls ';').  */
1357  if (specs_attrs != NULL_TREE
1358      && TREE_CODE (specs_attrs) != TREE_LIST)
1359    {
1360      *declspecs = specs_attrs;
1361      *prefix_attributes = NULL_TREE;
1362      return;
1363    }
1364
1365  /* Remember to keep the lists in the same order, element-wise.  */
1366
1367  specs = s = NULL_TREE;
1368  attrs = a = NULL_TREE;
1369  for (t = specs_attrs; t; t = next)
1370    {
1371      next = TREE_CHAIN (t);
1372      /* Declspecs have a non-NULL TREE_VALUE.  */
1373      if (TREE_VALUE (t) != NULL_TREE)
1374	{
1375	  if (specs == NULL_TREE)
1376	    specs = s = t;
1377	  else
1378	    {
1379	      TREE_CHAIN (s) = t;
1380	      s = t;
1381	    }
1382	}
1383      /* The TREE_PURPOSE may also be empty in the case of
1384	 __attribute__(()).  */
1385      else if (TREE_PURPOSE (t) != NULL_TREE)
1386	{
1387	  if (attrs == NULL_TREE)
1388	    attrs = a = TREE_PURPOSE (t);
1389	  else
1390	    {
1391	      TREE_CHAIN (a) = TREE_PURPOSE (t);
1392	      a = TREE_PURPOSE (t);
1393	    }
1394	  /* More attrs can be linked here, move A to the end.  */
1395	  while (TREE_CHAIN (a) != NULL_TREE)
1396	    a = TREE_CHAIN (a);
1397	}
1398    }
1399
1400  /* Terminate the lists.  */
1401  if (s != NULL_TREE)
1402    TREE_CHAIN (s) = NULL_TREE;
1403  if (a != NULL_TREE)
1404    TREE_CHAIN (a) = NULL_TREE;
1405
1406  /* All done.  */
1407  *declspecs = specs;
1408  *prefix_attributes = attrs;
1409}
1410
1411/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes.
1412   This function is used by the parser when a rule will accept attributes
1413   in a particular position, but we don't want to support that just yet.
1414
1415   A warning is issued for every ignored attribute.  */
1416
1417tree
1418strip_attrs (specs_attrs)
1419     tree specs_attrs;
1420{
1421  tree specs, attrs;
1422
1423  split_specs_attrs (specs_attrs, &specs, &attrs);
1424
1425  while (attrs)
1426    {
1427      warning ("`%s' attribute ignored",
1428	       IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
1429      attrs = TREE_CHAIN (attrs);
1430    }
1431
1432  return specs;
1433}
1434