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