OSDN Git Service

2002-03-03 Aldy Hernandez <aldyh@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / attribs.c
1 /* Functions dealing with attribute handling, used by most front ends.
2    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
3    2002 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "flags.h"
26 #include "toplev.h"
27 #include "output.h"
28 #include "rtl.h"
29 #include "ggc.h"
30 #include "expr.h"
31 #include "tm_p.h"
32 #include "obstack.h"
33 #include "cpplib.h"
34 #include "target.h"
35
36 static void init_attributes             PARAMS ((void));
37
38 /* Table of the tables of attributes (common, format, language, machine)
39    searched.  */
40 static const struct attribute_spec *attribute_tables[4];
41
42 static bool attributes_initialized = false;
43
44 static tree handle_packed_attribute     PARAMS ((tree *, tree, tree, int,
45                                                  bool *));
46 static tree handle_nocommon_attribute   PARAMS ((tree *, tree, tree, int,
47                                                  bool *));
48 static tree handle_common_attribute     PARAMS ((tree *, tree, tree, int,
49                                                  bool *));
50 static tree handle_noreturn_attribute   PARAMS ((tree *, tree, tree, int,
51                                                  bool *));
52 static tree handle_noinline_attribute   PARAMS ((tree *, tree, tree, int,
53                                                  bool *));
54 static tree handle_always_inline_attribute PARAMS ((tree *, tree, tree, int,
55                                                     bool *));
56 static tree handle_used_attribute       PARAMS ((tree *, tree, tree, int,
57                                                  bool *));
58 static tree handle_unused_attribute     PARAMS ((tree *, tree, tree, int,
59                                                  bool *));
60 static tree handle_const_attribute      PARAMS ((tree *, tree, tree, int,
61                                                  bool *));
62 static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree,
63                                                         int, bool *));
64 static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int,
65                                                   bool *));
66 static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int,
67                                                  bool *));
68 static tree handle_mode_attribute       PARAMS ((tree *, tree, tree, int,
69                                                  bool *));
70 static tree handle_section_attribute    PARAMS ((tree *, tree, tree, int,
71                                                  bool *));
72 static tree handle_aligned_attribute    PARAMS ((tree *, tree, tree, int,
73                                                  bool *));
74 static tree handle_weak_attribute       PARAMS ((tree *, tree, tree, int,
75                                                  bool *));
76 static tree handle_alias_attribute      PARAMS ((tree *, tree, tree, int,
77                                                  bool *));
78 static tree handle_visibility_attribute PARAMS ((tree *, tree, tree, int,
79                                                  bool *));
80 static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree,
81                                                              tree, int,
82                                                              bool *));
83 static tree handle_malloc_attribute     PARAMS ((tree *, tree, tree, int,
84                                                  bool *));
85 static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int,
86                                                      bool *));
87 static tree handle_pure_attribute       PARAMS ((tree *, tree, tree, int,
88                                                  bool *));
89 static tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int,
90                                                  bool *));
91 static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
92                                                   bool *));
93 static tree vector_size_helper PARAMS ((tree, tree));
94
95 /* Table of machine-independent attributes common to all C-like languages.  */
96 static const struct attribute_spec c_common_attribute_table[] =
97 {
98   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
99   { "packed",                 0, 0, false, false, false,
100                               handle_packed_attribute },
101   { "nocommon",               0, 0, true,  false, false,
102                               handle_nocommon_attribute },
103   { "common",                 0, 0, true,  false, false,
104                               handle_common_attribute },
105   /* FIXME: logically, noreturn attributes should be listed as
106      "false, true, true" and apply to function types.  But implementing this
107      would require all the places in the compiler that use TREE_THIS_VOLATILE
108      on a decl to identify non-returning functions to be located and fixed
109      to check the function type instead.  */
110   { "noreturn",               0, 0, true,  false, false,
111                               handle_noreturn_attribute },
112   { "volatile",               0, 0, true,  false, false,
113                               handle_noreturn_attribute },
114   { "noinline",               0, 0, true,  false, false,
115                               handle_noinline_attribute },
116   { "always_inline",          0, 0, true,  false, false,
117                               handle_always_inline_attribute },
118   { "used",                   0, 0, true,  false, false,
119                               handle_used_attribute },
120   { "unused",                 0, 0, false, false, false,
121                               handle_unused_attribute },
122   /* The same comments as for noreturn attributes apply to const ones.  */
123   { "const",                  0, 0, true,  false, false,
124                               handle_const_attribute },
125   { "transparent_union",      0, 0, false, false, false,
126                               handle_transparent_union_attribute },
127   { "constructor",            0, 0, true,  false, false,
128                               handle_constructor_attribute },
129   { "destructor",             0, 0, true,  false, false,
130                               handle_destructor_attribute },
131   { "mode",                   1, 1, false,  true, false,
132                               handle_mode_attribute },
133   { "section",                1, 1, true,  false, false,
134                               handle_section_attribute },
135   { "aligned",                0, 1, false, false, false,
136                               handle_aligned_attribute },
137   { "weak",                   0, 0, true,  false, false,
138                               handle_weak_attribute },
139   { "alias",                  1, 1, true,  false, false,
140                               handle_alias_attribute },
141   { "no_instrument_function", 0, 0, true,  false, false,
142                               handle_no_instrument_function_attribute },
143   { "malloc",                 0, 0, true,  false, false,
144                               handle_malloc_attribute },
145   { "no_stack_limit",         0, 0, true,  false, false,
146                               handle_no_limit_stack_attribute },
147   { "pure",                   0, 0, true,  false, false,
148                               handle_pure_attribute },
149   { "deprecated",             0, 0, false, false, false,
150                               handle_deprecated_attribute },
151   { "vector_size",            1, 1, false, true, false,
152                               handle_vector_size_attribute },
153   { "visibility",             1, 1, true,  false, false,
154                               handle_visibility_attribute },
155   { NULL,                     0, 0, false, false, false, NULL }
156 };
157
158 /* Default empty table of attributes.  */
159 static const struct attribute_spec empty_attribute_table[] =
160 {
161   { NULL, 0, 0, false, false, false, NULL }
162 };
163
164 /* Table of machine-independent attributes for checking formats, if used.  */
165 const struct attribute_spec *format_attribute_table = empty_attribute_table;
166
167 /* Table of machine-independent attributes for a particular language.  */
168 const struct attribute_spec *lang_attribute_table = empty_attribute_table;
169
170 /* Flag saying whether common language attributes are to be supported.  */
171 int lang_attribute_common = 1;
172
173 /* Initialize attribute tables, and make some sanity checks
174    if --enable-checking.  */
175
176 static void
177 init_attributes ()
178 {
179 #ifdef ENABLE_CHECKING
180   size_t i;
181 #endif
182
183   attribute_tables[0]
184     = lang_attribute_common ? c_common_attribute_table : empty_attribute_table;
185   attribute_tables[1] = lang_attribute_table;
186   attribute_tables[2] = format_attribute_table;
187   attribute_tables[3] = targetm.attribute_table;
188
189 #ifdef ENABLE_CHECKING
190   /* Make some sanity checks on the attribute tables.  */
191   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
192     {
193       int j;
194
195       for (j = 0; attribute_tables[i][j].name != NULL; j++)
196         {
197           /* The name must not begin and end with __.  */
198           const char *name = attribute_tables[i][j].name;
199           int len = strlen (name);
200           if (name[0] == '_' && name[1] == '_'
201               && name[len - 1] == '_' && name[len - 2] == '_')
202             abort ();
203           /* The minimum and maximum lengths must be consistent.  */
204           if (attribute_tables[i][j].min_length < 0)
205             abort ();
206           if (attribute_tables[i][j].max_length != -1
207               && (attribute_tables[i][j].max_length
208                   < attribute_tables[i][j].min_length))
209             abort ();
210           /* An attribute cannot require both a DECL and a TYPE.  */
211           if (attribute_tables[i][j].decl_required
212               && attribute_tables[i][j].type_required)
213             abort ();
214           /* If an attribute requires a function type, in particular
215              it requires a type.  */
216           if (attribute_tables[i][j].function_type_required
217               && !attribute_tables[i][j].type_required)
218             abort ();
219         }
220     }
221
222   /* Check that each name occurs just once in each table.  */
223   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
224     {
225       int j, k;
226       for (j = 0; attribute_tables[i][j].name != NULL; j++)
227         for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
228           if (!strcmp (attribute_tables[i][j].name,
229                        attribute_tables[i][k].name))
230             abort ();
231     }
232   /* Check that no name occurs in more than one table.  */
233   for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
234     {
235       size_t j, k, l;
236
237       for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
238         for (k = 0; attribute_tables[i][k].name != NULL; k++)
239           for (l = 0; attribute_tables[j][l].name != NULL; l++)
240             if (!strcmp (attribute_tables[i][k].name,
241                          attribute_tables[j][l].name))
242               abort ();
243     }
244 #endif
245
246   attributes_initialized = true;
247 }
248 \f
249 /* Process the attributes listed in ATTRIBUTES and install them in *NODE,
250    which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
251    it should be modified in place; if a TYPE, a copy should be created
252    unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
253    information, in the form of a bitwise OR of flags in enum attribute_flags
254    from tree.h.  Depending on these flags, some attributes may be
255    returned to be applied at a later stage (for example, to apply
256    a decl attribute to the declaration rather than to its type).  If
257    ATTR_FLAG_BUILT_IN is not set and *NODE is a DECL, then also consider
258    whether there might be some default attributes to apply to this DECL;
259    if so, decl_attributes will be called recursively with those attributes
260    and ATTR_FLAG_BUILT_IN set.  */
261
262 tree
263 decl_attributes (node, attributes, flags)
264      tree *node, attributes;
265      int flags;
266 {
267   tree a;
268   tree returned_attrs = NULL_TREE;
269
270   if (!attributes_initialized)
271     init_attributes ();
272
273   (*targetm.insert_attributes) (*node, &attributes);
274
275   if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL
276       && !(flags & (int) ATTR_FLAG_BUILT_IN))
277     insert_default_attributes (*node);
278
279   for (a = attributes; a; a = TREE_CHAIN (a))
280     {
281       tree name = TREE_PURPOSE (a);
282       tree args = TREE_VALUE (a);
283       tree *anode = node;
284       const struct attribute_spec *spec = NULL;
285       bool no_add_attrs = 0;
286       int i;
287
288       for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
289         {
290           int j;
291
292           for (j = 0; attribute_tables[i][j].name != NULL; j++)
293             {
294               if (is_attribute_p (attribute_tables[i][j].name, name))
295                 {
296                   spec = &attribute_tables[i][j];
297                   break;
298                 }
299             }
300           if (spec != NULL)
301             break;
302         }
303
304       if (spec == NULL)
305         {
306           warning ("`%s' attribute directive ignored",
307                    IDENTIFIER_POINTER (name));
308           continue;
309         }
310       else if (list_length (args) < spec->min_length
311                || (spec->max_length >= 0
312                    && list_length (args) > spec->max_length))
313         {
314           error ("wrong number of arguments specified for `%s' attribute",
315                  IDENTIFIER_POINTER (name));
316           continue;
317         }
318
319       if (spec->decl_required && !DECL_P (*anode))
320         {
321           if (flags & ((int) ATTR_FLAG_DECL_NEXT
322                        | (int) ATTR_FLAG_FUNCTION_NEXT
323                        | (int) ATTR_FLAG_ARRAY_NEXT))
324             {
325               /* Pass on this attribute to be tried again.  */
326               returned_attrs = tree_cons (name, args, returned_attrs);
327               continue;
328             }
329           else
330             {
331               warning ("`%s' attribute does not apply to types",
332                        IDENTIFIER_POINTER (name));
333               continue;
334             }
335         }
336
337       /* If we require a type, but were passed a decl, set up to make a
338          new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
339          would have applied if we'd been passed a type, but we cannot modify
340          the decl's type in place here.  */
341       if (spec->type_required && DECL_P (*anode))
342         {
343           anode = &TREE_TYPE (*anode);
344           flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
345         }
346
347       if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
348           && TREE_CODE (*anode) != METHOD_TYPE)
349         {
350           if (TREE_CODE (*anode) == POINTER_TYPE
351               && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
352                   || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
353             {
354               if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
355                 *anode = build_type_copy (*anode);
356               anode = &TREE_TYPE (*anode);
357             }
358           else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
359             {
360               /* Pass on this attribute to be tried again.  */
361               returned_attrs = tree_cons (name, args, returned_attrs);
362               continue;
363             }
364
365           if (TREE_CODE (*anode) != FUNCTION_TYPE
366               && TREE_CODE (*anode) != METHOD_TYPE)
367             {
368               warning ("`%s' attribute only applies to function types",
369                        IDENTIFIER_POINTER (name));
370               continue;
371             }
372         }
373
374       if (spec->handler != NULL)
375         returned_attrs = chainon ((*spec->handler) (anode, name, args,
376                                                     flags, &no_add_attrs),
377                                   returned_attrs);
378
379       /* Layout the decl in case anything changed.  */
380       if (spec->type_required && DECL_P (*node)
381           && (TREE_CODE (*node) == VAR_DECL
382               || TREE_CODE (*node) == PARM_DECL
383               || TREE_CODE (*node) == RESULT_DECL))
384         {
385           /* Force a recalculation of mode and size.  */
386           DECL_MODE (*node) = VOIDmode;
387           DECL_SIZE (*node) = 0;
388
389           layout_decl (*node, 0);
390         }
391
392       if (!no_add_attrs)
393         {
394           tree old_attrs;
395           tree a;
396
397           if (DECL_P (*anode))
398             old_attrs = DECL_ATTRIBUTES (*anode);
399           else
400             old_attrs = TYPE_ATTRIBUTES (*anode);
401
402           for (a = lookup_attribute (spec->name, old_attrs);
403                a != NULL_TREE;
404                a = lookup_attribute (spec->name, TREE_CHAIN (a)))
405             {
406               if (simple_cst_equal (TREE_VALUE (a), args) == 1)
407                 break;
408             }
409
410           if (a == NULL_TREE)
411             {
412               /* This attribute isn't already in the list.  */
413               if (DECL_P (*anode))
414                 DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
415               else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
416                 TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
417               else
418                 *anode = build_type_attribute_variant (*anode,
419                                                        tree_cons (name, args,
420                                                                   old_attrs));
421             }
422         }
423     }
424
425   return returned_attrs;
426 }
427
428 /* Handle a "packed" attribute; arguments as in
429    struct attribute_spec.handler.  */
430
431 static tree
432 handle_packed_attribute (node, name, args, flags, no_add_attrs)
433      tree *node;
434      tree name;
435      tree args ATTRIBUTE_UNUSED;
436      int flags;
437      bool *no_add_attrs;
438 {
439   tree *type = NULL;
440   if (DECL_P (*node))
441     {
442       if (TREE_CODE (*node) == TYPE_DECL)
443         type = &TREE_TYPE (*node);
444     }
445   else
446     type = node;
447
448   if (type)
449     {
450       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
451         *type = build_type_copy (*type);
452       TYPE_PACKED (*type) = 1;
453     }
454   else if (TREE_CODE (*node) == FIELD_DECL)
455     DECL_PACKED (*node) = 1;
456   /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
457      used for DECL_REGISTER.  It wouldn't mean anything anyway.  */
458   else
459     {
460       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
461       *no_add_attrs = true;
462     }
463
464   return NULL_TREE;
465 }
466
467 /* Handle a "nocommon" attribute; arguments as in
468    struct attribute_spec.handler.  */
469
470 static tree
471 handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
472      tree *node;
473      tree name;
474      tree args ATTRIBUTE_UNUSED;
475      int flags ATTRIBUTE_UNUSED;
476      bool *no_add_attrs;
477 {
478   if (TREE_CODE (*node) == VAR_DECL)
479     DECL_COMMON (*node) = 0;
480   else
481     {
482       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
483       *no_add_attrs = true;
484     }
485
486   return NULL_TREE;
487 }
488
489 /* Handle a "common" attribute; arguments as in
490    struct attribute_spec.handler.  */
491
492 static tree
493 handle_common_attribute (node, name, args, flags, no_add_attrs)
494      tree *node;
495      tree name;
496      tree args ATTRIBUTE_UNUSED;
497      int flags ATTRIBUTE_UNUSED;
498      bool *no_add_attrs;
499 {
500   if (TREE_CODE (*node) == VAR_DECL)
501     DECL_COMMON (*node) = 1;
502   else
503     {
504       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
505       *no_add_attrs = true;
506     }
507
508   return NULL_TREE;
509 }
510
511 /* Handle a "noreturn" attribute; arguments as in
512    struct attribute_spec.handler.  */
513
514 static tree
515 handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
516      tree *node;
517      tree name;
518      tree args ATTRIBUTE_UNUSED;
519      int flags ATTRIBUTE_UNUSED;
520      bool *no_add_attrs;
521 {
522   tree type = TREE_TYPE (*node);
523
524   /* See FIXME comment in c_common_attribute_table.  */
525   if (TREE_CODE (*node) == FUNCTION_DECL)
526     TREE_THIS_VOLATILE (*node) = 1;
527   else if (TREE_CODE (type) == POINTER_TYPE
528            && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
529     TREE_TYPE (*node)
530       = build_pointer_type
531         (build_type_variant (TREE_TYPE (type),
532                              TREE_READONLY (TREE_TYPE (type)), 1));
533   else
534     {
535       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
536       *no_add_attrs = true;
537     }
538
539   return NULL_TREE;
540 }
541
542 /* Handle a "noinline" attribute; arguments as in
543    struct attribute_spec.handler.  */
544
545 static tree
546 handle_noinline_attribute (node, name, args, flags, no_add_attrs)
547      tree *node;
548      tree name;
549      tree args ATTRIBUTE_UNUSED;
550      int flags ATTRIBUTE_UNUSED;
551      bool *no_add_attrs;
552 {
553   if (TREE_CODE (*node) == FUNCTION_DECL)
554     DECL_UNINLINABLE (*node) = 1;
555   else
556     {
557       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
558       *no_add_attrs = true;
559     }
560
561   return NULL_TREE;
562 }
563
564 /* Handle a "always_inline" attribute; arguments as in
565    struct attribute_spec.handler.  */
566
567 static tree
568 handle_always_inline_attribute (node, name, args, flags, no_add_attrs)
569      tree *node;
570      tree name;
571      tree args ATTRIBUTE_UNUSED;
572      int flags ATTRIBUTE_UNUSED;
573      bool *no_add_attrs;
574 {
575   if (TREE_CODE (*node) == FUNCTION_DECL)
576     {
577       /* Do nothing else, just set the attribute.  We'll get at
578          it later with lookup_attribute.  */
579     }
580   else
581     {
582       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
583       *no_add_attrs = true;
584     }
585
586   return NULL_TREE;
587 }
588
589 /* Handle a "used" attribute; arguments as in
590    struct attribute_spec.handler.  */
591
592 static tree
593 handle_used_attribute (node, name, args, flags, no_add_attrs)
594      tree *node;
595      tree name;
596      tree args ATTRIBUTE_UNUSED;
597      int flags ATTRIBUTE_UNUSED;
598      bool *no_add_attrs;
599 {
600   if (TREE_CODE (*node) == FUNCTION_DECL)
601     TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node))
602       = TREE_USED (*node) = 1;
603   else
604     {
605       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
606       *no_add_attrs = true;
607     }
608
609   return NULL_TREE;
610 }
611
612 /* Handle a "unused" attribute; arguments as in
613    struct attribute_spec.handler.  */
614
615 static tree
616 handle_unused_attribute (node, name, args, flags, no_add_attrs)
617      tree *node;
618      tree name;
619      tree args ATTRIBUTE_UNUSED;
620      int flags;
621      bool *no_add_attrs;
622 {
623   if (DECL_P (*node))
624     {
625       tree decl = *node;
626
627       if (TREE_CODE (decl) == PARM_DECL
628           || TREE_CODE (decl) == VAR_DECL
629           || TREE_CODE (decl) == FUNCTION_DECL
630           || TREE_CODE (decl) == LABEL_DECL
631           || TREE_CODE (decl) == TYPE_DECL)
632         TREE_USED (decl) = 1;
633       else
634         {
635           warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
636           *no_add_attrs = true;
637         }
638     }
639   else
640     {
641       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
642         *node = build_type_copy (*node);
643       TREE_USED (*node) = 1;
644     }
645
646   return NULL_TREE;
647 }
648
649 /* Handle a "const" attribute; arguments as in
650    struct attribute_spec.handler.  */
651
652 static tree
653 handle_const_attribute (node, name, args, flags, no_add_attrs)
654      tree *node;
655      tree name;
656      tree args ATTRIBUTE_UNUSED;
657      int flags ATTRIBUTE_UNUSED;
658      bool *no_add_attrs;
659 {
660   tree type = TREE_TYPE (*node);
661
662   /* See FIXME comment on noreturn in c_common_attribute_table.  */
663   if (TREE_CODE (*node) == FUNCTION_DECL)
664     TREE_READONLY (*node) = 1;
665   else if (TREE_CODE (type) == POINTER_TYPE
666            && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
667     TREE_TYPE (*node)
668       = build_pointer_type
669         (build_type_variant (TREE_TYPE (type), 1,
670                              TREE_THIS_VOLATILE (TREE_TYPE (type))));
671   else
672     {
673       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
674       *no_add_attrs = true;
675     }
676
677   return NULL_TREE;
678 }
679
680 /* Handle a "transparent_union" attribute; arguments as in
681    struct attribute_spec.handler.  */
682
683 static tree
684 handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
685      tree *node;
686      tree name;
687      tree args ATTRIBUTE_UNUSED;
688      int flags;
689      bool *no_add_attrs;
690 {
691   tree decl = NULL_TREE;
692   tree *type = NULL;
693   int is_type = 0;
694
695   if (DECL_P (*node))
696     {
697       decl = *node;
698       type = &TREE_TYPE (decl);
699       is_type = TREE_CODE (*node) == TYPE_DECL;
700     }
701   else if (TYPE_P (*node))
702     type = node, is_type = 1;
703
704   if (is_type
705       && TREE_CODE (*type) == UNION_TYPE
706       && (decl == 0
707           || (TYPE_FIELDS (*type) != 0
708               && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
709     {
710       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
711         *type = build_type_copy (*type);
712       TYPE_TRANSPARENT_UNION (*type) = 1;
713     }
714   else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
715            && TREE_CODE (*type) == UNION_TYPE
716            && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
717     DECL_TRANSPARENT_UNION (decl) = 1;
718   else
719     {
720       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
721       *no_add_attrs = true;
722     }
723
724   return NULL_TREE;
725 }
726
727 /* Handle a "constructor" attribute; arguments as in
728    struct attribute_spec.handler.  */
729
730 static tree
731 handle_constructor_attribute (node, name, args, flags, no_add_attrs)
732      tree *node;
733      tree name;
734      tree args ATTRIBUTE_UNUSED;
735      int flags ATTRIBUTE_UNUSED;
736      bool *no_add_attrs;
737 {
738   tree decl = *node;
739   tree type = TREE_TYPE (decl);
740
741   if (TREE_CODE (decl) == FUNCTION_DECL
742       && TREE_CODE (type) == FUNCTION_TYPE
743       && decl_function_context (decl) == 0)
744     {
745       DECL_STATIC_CONSTRUCTOR (decl) = 1;
746       TREE_USED (decl) = 1;
747     }
748   else
749     {
750       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
751       *no_add_attrs = true;
752     }
753
754   return NULL_TREE;
755 }
756
757 /* Handle a "destructor" attribute; arguments as in
758    struct attribute_spec.handler.  */
759
760 static tree
761 handle_destructor_attribute (node, name, args, flags, no_add_attrs)
762      tree *node;
763      tree name;
764      tree args ATTRIBUTE_UNUSED;
765      int flags ATTRIBUTE_UNUSED;
766      bool *no_add_attrs;
767 {
768   tree decl = *node;
769   tree type = TREE_TYPE (decl);
770
771   if (TREE_CODE (decl) == FUNCTION_DECL
772       && TREE_CODE (type) == FUNCTION_TYPE
773       && decl_function_context (decl) == 0)
774     {
775       DECL_STATIC_DESTRUCTOR (decl) = 1;
776       TREE_USED (decl) = 1;
777     }
778   else
779     {
780       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
781       *no_add_attrs = true;
782     }
783
784   return NULL_TREE;
785 }
786
787 /* Handle a "mode" attribute; arguments as in
788    struct attribute_spec.handler.  */
789
790 static tree
791 handle_mode_attribute (node, name, args, flags, no_add_attrs)
792      tree *node;
793      tree name;
794      tree args;
795      int flags ATTRIBUTE_UNUSED;
796      bool *no_add_attrs;
797 {
798   tree type = *node;
799
800   *no_add_attrs = true;
801
802   if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
803     warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
804   else
805     {
806       int j;
807       const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
808       int len = strlen (p);
809       enum machine_mode mode = VOIDmode;
810       tree typefm;
811
812       if (len > 4 && p[0] == '_' && p[1] == '_'
813           && p[len - 1] == '_' && p[len - 2] == '_')
814         {
815           char *newp = (char *) alloca (len - 1);
816
817           strcpy (newp, &p[2]);
818           newp[len - 4] = '\0';
819           p = newp;
820         }
821
822       /* Change this type to have a type with the specified mode.
823          First check for the special modes.  */
824       if (! strcmp (p, "byte"))
825         mode = byte_mode;
826       else if (!strcmp (p, "word"))
827         mode = word_mode;
828       else if (! strcmp (p, "pointer"))
829         mode = ptr_mode;
830       else
831         for (j = 0; j < NUM_MACHINE_MODES; j++)
832           if (!strcmp (p, GET_MODE_NAME (j)))
833             mode = (enum machine_mode) j;
834
835       if (mode == VOIDmode)
836         error ("unknown machine mode `%s'", p);
837       else if (0 == (typefm = type_for_mode (mode,
838                                              TREE_UNSIGNED (type))))
839         error ("no data type for mode `%s'", p);
840       else
841         *node = typefm;
842         /* No need to layout the type here.  The caller should do this.  */
843     }
844
845   return NULL_TREE;
846 }
847
848 /* Handle a "section" attribute; arguments as in
849    struct attribute_spec.handler.  */
850
851 static tree
852 handle_section_attribute (node, name, args, flags, no_add_attrs)
853      tree *node;
854      tree name ATTRIBUTE_UNUSED;
855      tree args;
856      int flags ATTRIBUTE_UNUSED;
857      bool *no_add_attrs;
858 {
859   tree decl = *node;
860
861   if (targetm.have_named_sections)
862     {
863       if ((TREE_CODE (decl) == FUNCTION_DECL
864            || TREE_CODE (decl) == VAR_DECL)
865           && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
866         {
867           if (TREE_CODE (decl) == VAR_DECL
868               && current_function_decl != NULL_TREE
869               && ! TREE_STATIC (decl))
870             {
871               error_with_decl (decl,
872                                "section attribute cannot be specified for local variables");
873               *no_add_attrs = true;
874             }
875
876           /* The decl may have already been given a section attribute
877              from a previous declaration.  Ensure they match.  */
878           else if (DECL_SECTION_NAME (decl) != NULL_TREE
879                    && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
880                               TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
881             {
882               error_with_decl (*node,
883                                "section of `%s' conflicts with previous declaration");
884               *no_add_attrs = true;
885             }
886           else
887             DECL_SECTION_NAME (decl) = TREE_VALUE (args);
888         }
889       else
890         {
891           error_with_decl (*node,
892                            "section attribute not allowed for `%s'");
893           *no_add_attrs = true;
894         }
895     }
896   else
897     {
898       error_with_decl (*node,
899                        "section attributes are not supported for this target");
900       *no_add_attrs = true;
901     }
902
903   return NULL_TREE;
904 }
905
906 /* Handle a "aligned" attribute; arguments as in
907    struct attribute_spec.handler.  */
908
909 static tree
910 handle_aligned_attribute (node, name, args, flags, no_add_attrs)
911      tree *node;
912      tree name ATTRIBUTE_UNUSED;
913      tree args;
914      int flags;
915      bool *no_add_attrs;
916 {
917   tree decl = NULL_TREE;
918   tree *type = NULL;
919   int is_type = 0;
920   tree align_expr = (args ? TREE_VALUE (args)
921                      : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
922   int i;
923
924   if (DECL_P (*node))
925     {
926       decl = *node;
927       type = &TREE_TYPE (decl);
928       is_type = TREE_CODE (*node) == TYPE_DECL;
929     }
930   else if (TYPE_P (*node))
931     type = node, is_type = 1;
932
933   /* Strip any NOPs of any kind.  */
934   while (TREE_CODE (align_expr) == NOP_EXPR
935          || TREE_CODE (align_expr) == CONVERT_EXPR
936          || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
937     align_expr = TREE_OPERAND (align_expr, 0);
938
939   if (TREE_CODE (align_expr) != INTEGER_CST)
940     {
941       error ("requested alignment is not a constant");
942       *no_add_attrs = true;
943     }
944   else if ((i = tree_log2 (align_expr)) == -1)
945     {
946       error ("requested alignment is not a power of 2");
947       *no_add_attrs = true;
948     }
949   else if (i > HOST_BITS_PER_INT - 2)
950     {
951       error ("requested alignment is too large");
952       *no_add_attrs = true;
953     }
954   else if (is_type)
955     {
956       /* If we have a TYPE_DECL, then copy the type, so that we
957          don't accidentally modify a builtin type.  See pushdecl.  */
958       if (decl && TREE_TYPE (decl) != error_mark_node
959           && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
960         {
961           tree tt = TREE_TYPE (decl);
962           *type = build_type_copy (*type);
963           DECL_ORIGINAL_TYPE (decl) = tt;
964           TYPE_NAME (*type) = decl;
965           TREE_USED (*type) = TREE_USED (decl);
966           TREE_TYPE (decl) = *type;
967         }
968       else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
969         *type = build_type_copy (*type);
970
971       TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
972       TYPE_USER_ALIGN (*type) = 1;
973     }
974   else if (TREE_CODE (decl) != VAR_DECL
975            && TREE_CODE (decl) != FIELD_DECL)
976     {
977       error_with_decl (decl,
978                        "alignment may not be specified for `%s'");
979       *no_add_attrs = true;
980     }
981   else
982     {
983       DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
984       DECL_USER_ALIGN (decl) = 1;
985     }
986
987   return NULL_TREE;
988 }
989
990 /* Handle a "weak" attribute; arguments as in
991    struct attribute_spec.handler.  */
992
993 static tree
994 handle_weak_attribute (node, name, args, flags, no_add_attrs)
995      tree *node;
996      tree name ATTRIBUTE_UNUSED;
997      tree args ATTRIBUTE_UNUSED;
998      int flags ATTRIBUTE_UNUSED;
999      bool *no_add_attrs ATTRIBUTE_UNUSED;
1000 {
1001   declare_weak (*node);
1002
1003   return NULL_TREE;
1004 }
1005
1006 /* Handle an "alias" attribute; arguments as in
1007    struct attribute_spec.handler.  */
1008
1009 static tree
1010 handle_alias_attribute (node, name, args, flags, no_add_attrs)
1011      tree *node;
1012      tree name;
1013      tree args;
1014      int flags ATTRIBUTE_UNUSED;
1015      bool *no_add_attrs;
1016 {
1017   tree decl = *node;
1018
1019   if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
1020       || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
1021     {
1022       error_with_decl (decl,
1023                        "`%s' defined both normally and as an alias");
1024       *no_add_attrs = true;
1025     }
1026   else if (decl_function_context (decl) == 0)
1027     {
1028       tree id;
1029
1030       id = TREE_VALUE (args);
1031       if (TREE_CODE (id) != STRING_CST)
1032         {
1033           error ("alias arg not a string");
1034           *no_add_attrs = true;
1035           return NULL_TREE;
1036         }
1037       id = get_identifier (TREE_STRING_POINTER (id));
1038       /* This counts as a use of the object pointed to.  */
1039       TREE_USED (id) = 1;
1040
1041       if (TREE_CODE (decl) == FUNCTION_DECL)
1042         DECL_INITIAL (decl) = error_mark_node;
1043       else
1044         DECL_EXTERNAL (decl) = 0;
1045     }
1046   else
1047     {
1048       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1049       *no_add_attrs = true;
1050     }
1051
1052   return NULL_TREE;
1053 }
1054
1055 /* Handle an "visibility" attribute; arguments as in
1056    struct attribute_spec.handler.  */
1057
1058 static tree
1059 handle_visibility_attribute (node, name, args, flags, no_add_attrs)
1060      tree *node;
1061      tree name;
1062      tree args;
1063      int flags ATTRIBUTE_UNUSED;
1064      bool *no_add_attrs;
1065 {
1066   tree decl = *node;
1067
1068   if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
1069     {
1070       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1071       *no_add_attrs = true;
1072     }
1073   else
1074     {
1075       tree id;
1076
1077       id = TREE_VALUE (args);
1078       if (TREE_CODE (id) != STRING_CST)
1079         {
1080           error ("visibility arg not a string");
1081           *no_add_attrs = true;
1082           return NULL_TREE;
1083         }
1084       if (strcmp (TREE_STRING_POINTER (id), "hidden")
1085           && strcmp (TREE_STRING_POINTER (id), "protected")
1086           && strcmp (TREE_STRING_POINTER (id), "internal"))
1087         {
1088           error ("visibility arg must be one of \"hidden\", \"protected\" or \"internal\"");
1089           *no_add_attrs = true;
1090           return NULL_TREE;
1091         }
1092     }
1093
1094   return NULL_TREE;
1095 }
1096
1097 /* Handle a "no_instrument_function" attribute; arguments as in
1098    struct attribute_spec.handler.  */
1099
1100 static tree
1101 handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
1102      tree *node;
1103      tree name;
1104      tree args ATTRIBUTE_UNUSED;
1105      int flags ATTRIBUTE_UNUSED;
1106      bool *no_add_attrs;
1107 {
1108   tree decl = *node;
1109
1110   if (TREE_CODE (decl) != FUNCTION_DECL)
1111     {
1112       error_with_decl (decl,
1113                        "`%s' attribute applies only to functions",
1114                        IDENTIFIER_POINTER (name));
1115       *no_add_attrs = true;
1116     }
1117   else if (DECL_INITIAL (decl))
1118     {
1119       error_with_decl (decl,
1120                        "can't set `%s' attribute after definition",
1121                        IDENTIFIER_POINTER (name));
1122       *no_add_attrs = true;
1123     }
1124   else
1125     DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
1126
1127   return NULL_TREE;
1128 }
1129
1130 /* Handle a "malloc" attribute; arguments as in
1131    struct attribute_spec.handler.  */
1132
1133 static tree
1134 handle_malloc_attribute (node, name, args, flags, no_add_attrs)
1135      tree *node;
1136      tree name;
1137      tree args ATTRIBUTE_UNUSED;
1138      int flags ATTRIBUTE_UNUSED;
1139      bool *no_add_attrs;
1140 {
1141   if (TREE_CODE (*node) == FUNCTION_DECL)
1142     DECL_IS_MALLOC (*node) = 1;
1143   /* ??? TODO: Support types.  */
1144   else
1145     {
1146       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1147       *no_add_attrs = true;
1148     }
1149
1150   return NULL_TREE;
1151 }
1152
1153 /* Handle a "no_limit_stack" attribute; arguments as in
1154    struct attribute_spec.handler.  */
1155
1156 static tree
1157 handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
1158      tree *node;
1159      tree name;
1160      tree args ATTRIBUTE_UNUSED;
1161      int flags ATTRIBUTE_UNUSED;
1162      bool *no_add_attrs;
1163 {
1164   tree decl = *node;
1165
1166   if (TREE_CODE (decl) != FUNCTION_DECL)
1167     {
1168       error_with_decl (decl,
1169                        "`%s' attribute applies only to functions",
1170                        IDENTIFIER_POINTER (name));
1171       *no_add_attrs = true;
1172     }
1173   else if (DECL_INITIAL (decl))
1174     {
1175       error_with_decl (decl,
1176                        "can't set `%s' attribute after definition",
1177                        IDENTIFIER_POINTER (name));
1178       *no_add_attrs = true;
1179     }
1180   else
1181     DECL_NO_LIMIT_STACK (decl) = 1;
1182
1183   return NULL_TREE;
1184 }
1185
1186 /* Handle a "pure" attribute; arguments as in
1187    struct attribute_spec.handler.  */
1188
1189 static tree
1190 handle_pure_attribute (node, name, args, flags, no_add_attrs)
1191      tree *node;
1192      tree name;
1193      tree args ATTRIBUTE_UNUSED;
1194      int flags ATTRIBUTE_UNUSED;
1195      bool *no_add_attrs;
1196 {
1197   if (TREE_CODE (*node) == FUNCTION_DECL)
1198     DECL_IS_PURE (*node) = 1;
1199   /* ??? TODO: Support types.  */
1200   else
1201     {
1202       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1203       *no_add_attrs = true;
1204     }
1205
1206   return NULL_TREE;
1207 }
1208
1209 /* Handle a "deprecated" attribute; arguments as in
1210    struct attribute_spec.handler.  */
1211    
1212 static tree
1213 handle_deprecated_attribute (node, name, args, flags, no_add_attrs)
1214      tree *node;
1215      tree name;
1216      tree args ATTRIBUTE_UNUSED;
1217      int flags;
1218      bool *no_add_attrs;
1219 {
1220   tree type = NULL_TREE;
1221   int warn = 0;
1222   const char *what = NULL;
1223   
1224   if (DECL_P (*node))
1225     {
1226       tree decl = *node;
1227       type = TREE_TYPE (decl);
1228       
1229       if (TREE_CODE (decl) == TYPE_DECL
1230           || TREE_CODE (decl) == PARM_DECL
1231           || TREE_CODE (decl) == VAR_DECL
1232           || TREE_CODE (decl) == FUNCTION_DECL
1233           || TREE_CODE (decl) == FIELD_DECL)
1234         TREE_DEPRECATED (decl) = 1;
1235       else
1236         warn = 1;
1237     }
1238   else if (TYPE_P (*node))
1239     {
1240       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1241         *node = build_type_copy (*node);
1242       TREE_DEPRECATED (*node) = 1;
1243       type = *node;
1244     }
1245   else
1246     warn = 1;
1247   
1248   if (warn)
1249     {
1250       *no_add_attrs = true;
1251       if (type && TYPE_NAME (type))
1252         {
1253           if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
1254             what = IDENTIFIER_POINTER (TYPE_NAME (*node));
1255           else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
1256                    && DECL_NAME (TYPE_NAME (type)))
1257             what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
1258         }
1259       if (what)
1260         warning ("`%s' attribute ignored for `%s'",
1261                   IDENTIFIER_POINTER (name), what);
1262       else
1263         warning ("`%s' attribute ignored", 
1264                       IDENTIFIER_POINTER (name));
1265     }
1266
1267   return NULL_TREE;
1268 }
1269
1270 /* Handle a "vector_size" attribute; arguments as in
1271    struct attribute_spec.handler.  */
1272
1273 static tree
1274 handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
1275      tree *node;
1276      tree name;
1277      tree args;
1278      int flags ATTRIBUTE_UNUSED;
1279      bool *no_add_attrs;
1280 {
1281   unsigned HOST_WIDE_INT vecsize, nunits;
1282   enum machine_mode mode, orig_mode, new_mode;
1283   tree type = *node, new_type;
1284
1285   *no_add_attrs = true;
1286
1287   if (! host_integerp (TREE_VALUE (args), 1))
1288     {
1289       warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1290       return NULL_TREE;
1291     }
1292
1293   /* Get the vector size (in bytes).  */
1294   vecsize = tree_low_cst (TREE_VALUE (args), 1);
1295
1296   /* We need to provide for vector pointers, vector arrays, and
1297      functions returning vectors.  For example:
1298
1299        __attribute__((vector_size(16))) short *foo;
1300
1301      In this case, the mode is SI, but the type being modified is
1302      HI, so we need to look further.  */
1303
1304   while (POINTER_TYPE_P (type)
1305          || TREE_CODE (type) == FUNCTION_TYPE
1306          || TREE_CODE (type) == ARRAY_TYPE)
1307     type = TREE_TYPE (type);
1308
1309   /* Get the mode of the type being modified.  */
1310   orig_mode = TYPE_MODE (type);
1311
1312   if (TREE_CODE (type) == RECORD_TYPE
1313       || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
1314           && GET_MODE_CLASS (orig_mode) != MODE_INT)
1315       || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1316     {
1317       error ("invalid vector type for attribute `%s'",
1318              IDENTIFIER_POINTER (name));
1319       return NULL_TREE;
1320     }
1321
1322   /* Calculate how many units fit in the vector.  */
1323   nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
1324
1325   /* Find a suitably sized vector.  */
1326   new_mode = VOIDmode;
1327   for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
1328                                         ? MODE_VECTOR_INT
1329                                         : MODE_VECTOR_FLOAT);
1330        mode != VOIDmode;
1331        mode = GET_MODE_WIDER_MODE (mode))
1332     if (vecsize == GET_MODE_SIZE (mode)
1333         && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
1334       {
1335         new_mode = mode;
1336         break;
1337       }
1338
1339   if (new_mode == VOIDmode)
1340     error ("no vector mode with the size and type specified could be found");
1341   else
1342     {
1343       tree index, array, rt;
1344
1345       new_type = type_for_mode (new_mode, TREE_UNSIGNED (type));
1346
1347       if (!new_type)
1348         {
1349           error ("no vector mode with the size and type specified could be found");
1350           return NULL_TREE;
1351         }
1352
1353       new_type = build_type_copy (new_type);
1354
1355       /* Set the debug information here, because this is the only
1356          place where we know the underlying type for a vector made
1357          with vector_size.  For debugging purposes we pretend a vector
1358          is an array within a structure.  */
1359       index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
1360       array = build_array_type (type, build_index_type (index));
1361       rt = make_node (RECORD_TYPE);
1362
1363       TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
1364       DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
1365       layout_type (rt);
1366       TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
1367
1368       /* Build back pointers if needed.  */
1369       *node = vector_size_helper (*node, new_type);
1370     }
1371     
1372   return NULL_TREE;
1373 }
1374
1375 /* HACK.  GROSS.  This is absolutely disgusting.  I wish there was a
1376    better way.
1377
1378    If we requested a pointer to a vector, build up the pointers that
1379    we stripped off while looking for the inner type.  Similarly for
1380    return values from functions.
1381
1382    The argument "type" is the top of the chain, and "bottom" is the
1383    new type which we will point to.  */
1384
1385 static tree
1386 vector_size_helper (type, bottom)
1387      tree type, bottom;
1388 {
1389   tree inner, outer;
1390
1391   if (POINTER_TYPE_P (type))
1392     {
1393       inner = vector_size_helper (TREE_TYPE (type), bottom);
1394       outer = build_pointer_type (inner);
1395     }
1396   else if (TREE_CODE (type) == ARRAY_TYPE)
1397     {
1398       inner = vector_size_helper (TREE_TYPE (type), bottom);
1399       outer = build_array_type (inner, TYPE_VALUES (type));
1400     }
1401   else if (TREE_CODE (type) == FUNCTION_TYPE)
1402     {
1403       inner = vector_size_helper (TREE_TYPE (type), bottom);
1404       outer = build_function_type (inner, TYPE_VALUES (type));
1405     }
1406   else
1407     return bottom;
1408   
1409   TREE_READONLY (outer) = TREE_READONLY (type);
1410   TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
1411
1412   return outer;
1413 }
1414
1415 /* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
1416    lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
1417
1418    The head of the declspec list is stored in DECLSPECS.
1419    The head of the attribute list is stored in PREFIX_ATTRIBUTES.
1420
1421    Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
1422    the list elements.  We drop the containing TREE_LIST nodes and link the
1423    resulting attributes together the way decl_attributes expects them.  */
1424
1425 void
1426 split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
1427      tree specs_attrs;
1428      tree *declspecs, *prefix_attributes;
1429 {
1430   tree t, s, a, next, specs, attrs;
1431
1432   /* This can happen after an __extension__ in pedantic mode.  */
1433   if (specs_attrs != NULL_TREE 
1434       && TREE_CODE (specs_attrs) == INTEGER_CST)
1435     {
1436       *declspecs = NULL_TREE;
1437       *prefix_attributes = NULL_TREE;
1438       return;
1439     }
1440
1441   /* This can happen in c++ (eg: decl: typespec initdecls ';').  */
1442   if (specs_attrs != NULL_TREE
1443       && TREE_CODE (specs_attrs) != TREE_LIST)
1444     {
1445       *declspecs = specs_attrs;
1446       *prefix_attributes = NULL_TREE;
1447       return;
1448     }
1449
1450   /* Remember to keep the lists in the same order, element-wise.  */
1451
1452   specs = s = NULL_TREE;
1453   attrs = a = NULL_TREE;
1454   for (t = specs_attrs; t; t = next)
1455     {
1456       next = TREE_CHAIN (t);
1457       /* Declspecs have a non-NULL TREE_VALUE.  */
1458       if (TREE_VALUE (t) != NULL_TREE)
1459         {
1460           if (specs == NULL_TREE)
1461             specs = s = t;
1462           else
1463             {
1464               TREE_CHAIN (s) = t;
1465               s = t;
1466             }
1467         }
1468       /* The TREE_PURPOSE may also be empty in the case of
1469          __attribute__(()).  */
1470       else if (TREE_PURPOSE (t) != NULL_TREE)
1471         {
1472           if (attrs == NULL_TREE)
1473             attrs = a = TREE_PURPOSE (t);
1474           else
1475             {
1476               TREE_CHAIN (a) = TREE_PURPOSE (t);
1477               a = TREE_PURPOSE (t);
1478             }
1479           /* More attrs can be linked here, move A to the end.  */
1480           while (TREE_CHAIN (a) != NULL_TREE)
1481             a = TREE_CHAIN (a);
1482         }
1483     }
1484
1485   /* Terminate the lists.  */
1486   if (s != NULL_TREE)
1487     TREE_CHAIN (s) = NULL_TREE;
1488   if (a != NULL_TREE)
1489     TREE_CHAIN (a) = NULL_TREE;
1490
1491   /* All done.  */
1492   *declspecs = specs;
1493   *prefix_attributes = attrs;
1494 }
1495
1496 /* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes.
1497    This function is used by the parser when a rule will accept attributes
1498    in a particular position, but we don't want to support that just yet.
1499
1500    A warning is issued for every ignored attribute.  */
1501
1502 tree
1503 strip_attrs (specs_attrs)
1504      tree specs_attrs;
1505 {
1506   tree specs, attrs;
1507
1508   split_specs_attrs (specs_attrs, &specs, &attrs);
1509
1510   while (attrs)
1511     {
1512       warning ("`%s' attribute ignored",
1513                IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
1514       attrs = TREE_CHAIN (attrs);
1515     }
1516
1517   return specs;
1518 }
1519