OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [attribs.c] - Blame information for rev 20

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* 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, 2003, 2004, 2005 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, 51 Franklin Street, Fifth Floor, Boston, MA
20
02110-1301, USA.  */
21
 
22
#include "config.h"
23
#include "system.h"
24
#include "coretypes.h"
25
#include "tm.h"
26
#include "tree.h"
27
#include "flags.h"
28
#include "toplev.h"
29
#include "output.h"
30
#include "rtl.h"
31
#include "ggc.h"
32
#include "tm_p.h"
33
#include "cpplib.h"
34
#include "target.h"
35
#include "langhooks.h"
36
 
37
static void init_attributes (void);
38
 
39
/* Table of the tables of attributes (common, language, format, machine)
40
   searched.  */
41
static const struct attribute_spec *attribute_tables[4];
42
 
43
static bool attributes_initialized = false;
44
 
45
/* Default empty table of attributes.  */
46
static const struct attribute_spec empty_attribute_table[] =
47
{
48
  { NULL, 0, 0, false, false, false, NULL }
49
};
50
 
51
/* Initialize attribute tables, and make some sanity checks
52
   if --enable-checking.  */
53
 
54
static void
55
init_attributes (void)
56
{
57
  size_t i;
58
 
59
  attribute_tables[0] = lang_hooks.common_attribute_table;
60
  attribute_tables[1] = lang_hooks.attribute_table;
61
  attribute_tables[2] = lang_hooks.format_attribute_table;
62
  attribute_tables[3] = targetm.attribute_table;
63
 
64
  /* Translate NULL pointers to pointers to the empty table.  */
65
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
66
    if (attribute_tables[i] == NULL)
67
      attribute_tables[i] = empty_attribute_table;
68
 
69
#ifdef ENABLE_CHECKING
70
  /* Make some sanity checks on the attribute tables.  */
71
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
72
    {
73
      int j;
74
 
75
      for (j = 0; attribute_tables[i][j].name != NULL; j++)
76
        {
77
          /* The name must not begin and end with __.  */
78
          const char *name = attribute_tables[i][j].name;
79
          int len = strlen (name);
80
 
81
          gcc_assert (!(name[0] == '_' && name[1] == '_'
82
                        && name[len - 1] == '_' && name[len - 2] == '_'));
83
 
84
          /* The minimum and maximum lengths must be consistent.  */
85
          gcc_assert (attribute_tables[i][j].min_length >= 0);
86
 
87
          gcc_assert (attribute_tables[i][j].max_length == -1
88
                      || (attribute_tables[i][j].max_length
89
                          >= attribute_tables[i][j].min_length));
90
 
91
          /* An attribute cannot require both a DECL and a TYPE.  */
92
          gcc_assert (!attribute_tables[i][j].decl_required
93
                      || !attribute_tables[i][j].type_required);
94
 
95
          /* If an attribute requires a function type, in particular
96
             it requires a type.  */
97
          gcc_assert (!attribute_tables[i][j].function_type_required
98
                      || attribute_tables[i][j].type_required);
99
        }
100
    }
101
 
102
  /* Check that each name occurs just once in each table.  */
103
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
104
    {
105
      int j, k;
106
      for (j = 0; attribute_tables[i][j].name != NULL; j++)
107
        for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
108
          gcc_assert (strcmp (attribute_tables[i][j].name,
109
                              attribute_tables[i][k].name));
110
    }
111
  /* Check that no name occurs in more than one table.  */
112
  for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
113
    {
114
      size_t j, k, l;
115
 
116
      for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
117
        for (k = 0; attribute_tables[i][k].name != NULL; k++)
118
          for (l = 0; attribute_tables[j][l].name != NULL; l++)
119
            gcc_assert (strcmp (attribute_tables[i][k].name,
120
                                attribute_tables[j][l].name));
121
    }
122
#endif
123
 
124
  attributes_initialized = true;
125
}
126
 
127
/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
128
   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
129
   it should be modified in place; if a TYPE, a copy should be created
130
   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
131
   information, in the form of a bitwise OR of flags in enum attribute_flags
132
   from tree.h.  Depending on these flags, some attributes may be
133
   returned to be applied at a later stage (for example, to apply
134
   a decl attribute to the declaration rather than to its type).  */
135
 
136
tree
137
decl_attributes (tree *node, tree attributes, int flags)
138
{
139
  tree a;
140
  tree returned_attrs = NULL_TREE;
141
 
142
  if (!attributes_initialized)
143
    init_attributes ();
144
 
145
  targetm.insert_attributes (*node, &attributes);
146
 
147
  for (a = attributes; a; a = TREE_CHAIN (a))
148
    {
149
      tree name = TREE_PURPOSE (a);
150
      tree args = TREE_VALUE (a);
151
      tree *anode = node;
152
      const struct attribute_spec *spec = NULL;
153
      bool no_add_attrs = 0;
154
      tree fn_ptr_tmp = NULL_TREE;
155
      size_t i;
156
 
157
      for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
158
        {
159
          int j;
160
 
161
          for (j = 0; attribute_tables[i][j].name != NULL; j++)
162
            {
163
              if (is_attribute_p (attribute_tables[i][j].name, name))
164
                {
165
                  spec = &attribute_tables[i][j];
166
                  break;
167
                }
168
            }
169
          if (spec != NULL)
170
            break;
171
        }
172
 
173
      if (spec == NULL)
174
        {
175
          warning (OPT_Wattributes, "%qs attribute directive ignored",
176
                   IDENTIFIER_POINTER (name));
177
          continue;
178
        }
179
      else if (list_length (args) < spec->min_length
180
               || (spec->max_length >= 0
181
                   && list_length (args) > spec->max_length))
182
        {
183
          error ("wrong number of arguments specified for %qs attribute",
184
                 IDENTIFIER_POINTER (name));
185
          continue;
186
        }
187
 
188
      if (spec->decl_required && !DECL_P (*anode))
189
        {
190
          if (flags & ((int) ATTR_FLAG_DECL_NEXT
191
                       | (int) ATTR_FLAG_FUNCTION_NEXT
192
                       | (int) ATTR_FLAG_ARRAY_NEXT))
193
            {
194
              /* Pass on this attribute to be tried again.  */
195
              returned_attrs = tree_cons (name, args, returned_attrs);
196
              continue;
197
            }
198
          else
199
            {
200
              warning (OPT_Wattributes, "%qs attribute does not apply to types",
201
                       IDENTIFIER_POINTER (name));
202
              continue;
203
            }
204
        }
205
 
206
      /* If we require a type, but were passed a decl, set up to make a
207
         new type and update the one in the decl.  ATTR_FLAG_TYPE_IN_PLACE
208
         would have applied if we'd been passed a type, but we cannot modify
209
         the decl's type in place here.  */
210
      if (spec->type_required && DECL_P (*anode))
211
        {
212
          anode = &TREE_TYPE (*anode);
213
          flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
214
        }
215
 
216
      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
217
          && TREE_CODE (*anode) != METHOD_TYPE)
218
        {
219
          if (TREE_CODE (*anode) == POINTER_TYPE
220
              && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
221
                  || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
222
            {
223
              /* OK, this is a bit convoluted.  We can't just make a copy
224
                 of the pointer type and modify its TREE_TYPE, because if
225
                 we change the attributes of the target type the pointer
226
                 type needs to have a different TYPE_MAIN_VARIANT.  So we
227
                 pull out the target type now, frob it as appropriate, and
228
                 rebuild the pointer type later.
229
 
230
                 This would all be simpler if attributes were part of the
231
                 declarator, grumble grumble.  */
232
              fn_ptr_tmp = TREE_TYPE (*anode);
233
              anode = &fn_ptr_tmp;
234
              flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
235
            }
236
          else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
237
            {
238
              /* Pass on this attribute to be tried again.  */
239
              returned_attrs = tree_cons (name, args, returned_attrs);
240
              continue;
241
            }
242
 
243
          if (TREE_CODE (*anode) != FUNCTION_TYPE
244
              && TREE_CODE (*anode) != METHOD_TYPE)
245
            {
246
              warning (OPT_Wattributes,
247
                       "%qs attribute only applies to function types",
248
                       IDENTIFIER_POINTER (name));
249
              continue;
250
            }
251
        }
252
 
253
      if (spec->handler != NULL)
254
        returned_attrs = chainon ((*spec->handler) (anode, name, args,
255
                                                    flags, &no_add_attrs),
256
                                  returned_attrs);
257
 
258
      /* Layout the decl in case anything changed.  */
259
      if (spec->type_required && DECL_P (*node)
260
          && (TREE_CODE (*node) == VAR_DECL
261
              || TREE_CODE (*node) == PARM_DECL
262
              || TREE_CODE (*node) == RESULT_DECL))
263
        relayout_decl (*node);
264
 
265
      if (!no_add_attrs)
266
        {
267
          tree old_attrs;
268
          tree a;
269
 
270
          if (DECL_P (*anode))
271
            old_attrs = DECL_ATTRIBUTES (*anode);
272
          else
273
            old_attrs = TYPE_ATTRIBUTES (*anode);
274
 
275
          for (a = lookup_attribute (spec->name, old_attrs);
276
               a != NULL_TREE;
277
               a = lookup_attribute (spec->name, TREE_CHAIN (a)))
278
            {
279
              if (simple_cst_equal (TREE_VALUE (a), args) == 1)
280
                break;
281
            }
282
 
283
          if (a == NULL_TREE)
284
            {
285
              /* This attribute isn't already in the list.  */
286
              if (DECL_P (*anode))
287
                DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
288
              else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
289
                {
290
                  TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
291
                  /* If this is the main variant, also push the attributes
292
                     out to the other variants.  */
293
                  if (*anode == TYPE_MAIN_VARIANT (*anode))
294
                    {
295
                      tree variant;
296
                      for (variant = *anode; variant;
297
                           variant = TYPE_NEXT_VARIANT (variant))
298
                        {
299
                          if (TYPE_ATTRIBUTES (variant) == old_attrs)
300
                            TYPE_ATTRIBUTES (variant)
301
                              = TYPE_ATTRIBUTES (*anode);
302
                          else if (!lookup_attribute
303
                                   (spec->name, TYPE_ATTRIBUTES (variant)))
304
                            TYPE_ATTRIBUTES (variant) = tree_cons
305
                              (name, args, TYPE_ATTRIBUTES (variant));
306
                        }
307
                    }
308
                }
309
              else
310
                *anode = build_type_attribute_variant (*anode,
311
                                                       tree_cons (name, args,
312
                                                                  old_attrs));
313
            }
314
        }
315
 
316
      if (fn_ptr_tmp)
317
        {
318
          /* Rebuild the function pointer type and put it in the
319
             appropriate place.  */
320
          fn_ptr_tmp = build_pointer_type (fn_ptr_tmp);
321
          if (DECL_P (*node))
322
            TREE_TYPE (*node) = fn_ptr_tmp;
323
          else
324
            {
325
              gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
326
              *node = fn_ptr_tmp;
327
            }
328
        }
329
    }
330
 
331
  return returned_attrs;
332
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.