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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gcc-4.2.2/] [gcc/] [attribs.c] - Blame information for rev 816

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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