OSDN Git Service

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