]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/attribs.c
Daily bump.
[thirdparty/gcc.git] / gcc / attribs.c
CommitLineData
e3f6ce11 1/* Functions dealing with attribute handling, used by most front ends.
80fabb90 2 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
978b9403 3 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
e3f6ce11 4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
67ce556b 19Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
2002110-1301, USA. */
e3f6ce11 21
22#include "config.h"
23#include "system.h"
805e22b2 24#include "coretypes.h"
25#include "tm.h"
e3f6ce11 26#include "tree.h"
27#include "flags.h"
28#include "toplev.h"
29#include "output.h"
30#include "rtl.h"
31#include "ggc.h"
e3f6ce11 32#include "tm_p.h"
e3f6ce11 33#include "cpplib.h"
34#include "target.h"
26ca6c20 35#include "langhooks.h"
e3f6ce11 36
aecda0d6 37static void init_attributes (void);
e3f6ce11 38
f8e93a2e 39/* Table of the tables of attributes (common, language, format, machine)
e3f6ce11 40 searched. */
41static const struct attribute_spec *attribute_tables[4];
42
43static bool attributes_initialized = false;
44
e3f6ce11 45/* Default empty table of attributes. */
46static const struct attribute_spec empty_attribute_table[] =
47{
48 { NULL, 0, 0, false, false, false, NULL }
49};
50
e3f6ce11 51/* Initialize attribute tables, and make some sanity checks
52 if --enable-checking. */
53
54static void
aecda0d6 55init_attributes (void)
e3f6ce11 56{
3585dac7 57 size_t i;
e3f6ce11 58
f8e93a2e 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;
e3f6ce11 62 attribute_tables[3] = targetm.attribute_table;
63
f8e93a2e 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
e3f6ce11 69#ifdef ENABLE_CHECKING
70 /* Make some sanity checks on the attribute tables. */
3585dac7 71 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
e3f6ce11 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);
a0c938f0 80
64db345d 81 gcc_assert (!(name[0] == '_' && name[1] == '_'
82 && name[len - 1] == '_' && name[len - 2] == '_'));
a0c938f0 83
e3f6ce11 84 /* The minimum and maximum lengths must be consistent. */
64db345d 85 gcc_assert (attribute_tables[i][j].min_length >= 0);
a0c938f0 86
64db345d 87 gcc_assert (attribute_tables[i][j].max_length == -1
88 || (attribute_tables[i][j].max_length
89 >= attribute_tables[i][j].min_length));
a0c938f0 90
e3f6ce11 91 /* An attribute cannot require both a DECL and a TYPE. */
64db345d 92 gcc_assert (!attribute_tables[i][j].decl_required
93 || !attribute_tables[i][j].type_required);
a0c938f0 94
e3f6ce11 95 /* If an attribute requires a function type, in particular
96 it requires a type. */
64db345d 97 gcc_assert (!attribute_tables[i][j].function_type_required
98 || attribute_tables[i][j].type_required);
e3f6ce11 99 }
100 }
101
102 /* Check that each name occurs just once in each table. */
3585dac7 103 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
e3f6ce11 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++)
64db345d 108 gcc_assert (strcmp (attribute_tables[i][j].name,
109 attribute_tables[i][k].name));
e3f6ce11 110 }
111 /* Check that no name occurs in more than one table. */
3585dac7 112 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
e3f6ce11 113 {
3585dac7 114 size_t j, k, l;
e3f6ce11 115
3585dac7 116 for (j = i + 1; j < ARRAY_SIZE (attribute_tables); j++)
e3f6ce11 117 for (k = 0; attribute_tables[i][k].name != NULL; k++)
118 for (l = 0; attribute_tables[j][l].name != NULL; l++)
64db345d 119 gcc_assert (strcmp (attribute_tables[i][k].name,
120 attribute_tables[j][l].name));
e3f6ce11 121 }
122#endif
123
124 attributes_initialized = true;
125}
126\f
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
101cc430 134 a decl attribute to the declaration rather than to its type). */
e3f6ce11 135
136tree
aecda0d6 137decl_attributes (tree *node, tree attributes, int flags)
e3f6ce11 138{
139 tree a;
140 tree returned_attrs = NULL_TREE;
141
142 if (!attributes_initialized)
143 init_attributes ();
144
883b2e73 145 targetm.insert_attributes (*node, &attributes);
e3f6ce11 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;
79bdd5ff 154 tree fn_ptr_tmp = NULL_TREE;
40265b77 155 size_t i;
e3f6ce11 156
3585dac7 157 for (i = 0; i < ARRAY_SIZE (attribute_tables); i++)
e3f6ce11 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 {
9b2d6d13 175 warning (OPT_Wattributes, "%qs attribute directive ignored",
e3f6ce11 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 {
eb586f2c 183 error ("wrong number of arguments specified for %qs attribute",
e3f6ce11 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 {
9b2d6d13 200 warning (OPT_Wattributes, "%qs attribute does not apply to types",
e3f6ce11 201 IDENTIFIER_POINTER (name));
202 continue;
203 }
204 }
205
aa9c60c1 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. */
e3f6ce11 210 if (spec->type_required && DECL_P (*anode))
aa9c60c1 211 {
212 anode = &TREE_TYPE (*anode);
213 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
214 }
e3f6ce11 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 {
79bdd5ff 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
a0c938f0 230 This would all be simpler if attributes were part of the
231 declarator, grumble grumble. */
79bdd5ff 232 fn_ptr_tmp = TREE_TYPE (*anode);
233 anode = &fn_ptr_tmp;
234 flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE;
e3f6ce11 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 {
9b2d6d13 246 warning (OPT_Wattributes,
247 "%qs attribute only applies to function types",
e3f6ce11 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);
ae4718db 257
258 /* Layout the decl in case anything changed. */
259 if (spec->type_required && DECL_P (*node)
e56de52f 260 && (TREE_CODE (*node) == VAR_DECL
261 || TREE_CODE (*node) == PARM_DECL
262 || TREE_CODE (*node) == RESULT_DECL))
1c0a6d1e 263 relayout_decl (*node);
ae4718db 264
e3f6ce11 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)
316e17ae 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 }
e3f6ce11 309 else
310 *anode = build_type_attribute_variant (*anode,
311 tree_cons (name, args,
312 old_attrs));
313 }
314 }
79bdd5ff 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;
79bdd5ff 323 else
64db345d 324 {
325 gcc_assert (TREE_CODE (*node) == POINTER_TYPE);
326 *node = fn_ptr_tmp;
327 }
79bdd5ff 328 }
e3f6ce11 329 }
330
331 return returned_attrs;
332}