* friend.c (make_friend_class): Robustify.
[official-gcc.git] / gcc / c-pragma.c
blob7cb7421d209ee3010a00d562275ae1abf0eae524
1 /* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
2 Copyright (C) 1992, 1997, 1998, 1999 Free Software Foundation, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU CC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU CC; see the file COPYING. If not, write to
18 the Free Software Foundation, 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include "config.h"
22 #include "system.h"
23 #include "rtl.h"
24 #include "tree.h"
25 #include "function.h"
26 #include "defaults.h"
27 #include "c-pragma.h"
28 #include "flags.h"
29 #include "toplev.h"
30 #include "ggc.h"
32 #ifdef HANDLE_GENERIC_PRAGMAS
34 #ifdef HANDLE_PRAGMA_PACK
35 /* When structure field packing is in effect, this variable is the
36 number of bits to use as the maximum alignment. When packing is not
37 in effect, this is zero. */
39 extern int maximum_field_alignment;
40 #endif
43 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44 typedef struct align_stack
46 int alignment;
47 unsigned int num_pushes;
48 tree id;
49 struct align_stack * prev;
50 } align_stack;
52 static struct align_stack * alignment_stack = NULL;
54 static int push_alignment PROTO((int, tree));
55 static int pop_alignment PROTO((tree));
57 /* Push an alignment value onto the stack. */
58 static int
59 push_alignment (alignment, id)
60 int alignment;
61 tree id;
63 switch (alignment)
65 case 0:
66 case 1:
67 case 2:
68 case 4:
69 case 8:
70 case 16:
71 break;
72 default:
73 warning ("\
74 Alignment must be a small power of two, not %d, in #pragma pack",
75 alignment);
76 return 0;
79 if (alignment_stack == NULL
80 || alignment_stack->alignment != alignment
81 || id != NULL_TREE)
83 align_stack * entry;
85 entry = (align_stack *) xmalloc (sizeof (* entry));
87 if (entry == NULL)
89 warning ("Out of memory pushing #pragma pack");
90 return 0;
93 entry->alignment = alignment;
94 entry->num_pushes = 1;
95 entry->id = id;
96 entry->prev = alignment_stack;
98 alignment_stack = entry;
100 maximum_field_alignment = alignment * 8;
102 else
103 alignment_stack->num_pushes ++;
105 return 1;
108 /* Undo a push of an alignment onto the stack. */
109 static int
110 pop_alignment (id)
111 tree id;
113 align_stack * entry;
115 if (alignment_stack == NULL)
117 warning ("\
118 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
120 return 0;
123 /* If we got an identifier, strip away everything above the target
124 entry so that the next step will restore the state just below it. */
125 if (id)
127 for (entry = alignment_stack; entry; entry = entry->prev)
128 if (entry->id == id)
130 entry->num_pushes = 1;
131 alignment_stack = entry;
132 break;
134 if (entry == NULL)
135 warning ("\
136 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
137 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
140 if (-- alignment_stack->num_pushes == 0)
142 entry = alignment_stack->prev;
144 if (entry == NULL)
145 maximum_field_alignment = 0;
146 else
147 maximum_field_alignment = entry->alignment * 8;
149 free (alignment_stack);
151 alignment_stack = entry;
154 return 1;
157 /* Generate 'packed' and 'aligned' attributes for decls whilst a
158 #pragma pack(push... is in effect. */
159 void
160 insert_pack_attributes (node, attributes, prefix)
161 tree node;
162 tree * attributes;
163 tree * prefix;
165 tree a;
166 int field_alignment;
168 /* If we are not packing, then there is nothing to do. */
169 if (maximum_field_alignment == 0
170 || alignment_stack == NULL)
171 return;
173 /* We are only interested in fields. */
174 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
175 || TREE_CODE (node) != FIELD_DECL)
176 return;
178 field_alignment = TYPE_ALIGN (TREE_TYPE (node));
179 if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
180 field_alignment = maximum_field_alignment;
182 /* Add a 'packed' attribute. */
183 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
185 /* If the alignment is > 8 then add an alignment attribute as well. */
186 if (field_alignment > 8)
188 /* If the aligned attribute is already present then do not override it. */
189 for (a = * attributes; a; a = TREE_CHAIN (a))
191 tree name = TREE_PURPOSE (a);
192 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
193 break;
196 if (a == NULL)
197 for (a = * prefix; a; a = TREE_CHAIN (a))
199 tree name = TREE_PURPOSE (a);
200 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
201 break;
204 if (a == NULL)
206 * attributes = tree_cons
207 (get_identifier ("aligned"),
208 tree_cons (NULL,
209 build_int_2 (field_alignment / 8, 0),
210 NULL),
211 * attributes);
215 return;
217 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
219 /* Handle one token of a pragma directive. TOKEN is the current token, and
220 STRING is its printable form. Some front ends do not support generating
221 tokens, and will only pass in a STRING. Also some front ends will reuse
222 the buffer containing STRING, so it must be copied to a local buffer if
223 it needs to be preserved.
225 If STRING is non-NULL, then the return value will be ignored, and there
226 will be futher calls to handle_pragma_token() in order to handle the rest of
227 the line containing the #pragma directive. If STRING is NULL, the entire
228 line has now been presented to handle_pragma_token() and the return value
229 should be zero if the pragma flawed in some way, or if the pragma was not
230 recognised, and non-zero if it was successfully handled. */
233 handle_pragma_token (string, token)
234 const char * string;
235 tree token;
237 static enum pragma_state state = ps_start;
238 static enum pragma_state type;
239 #ifdef HANDLE_PRAGMA_WEAK
240 static char * name;
241 static char * value;
242 #endif
243 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
244 static int align;
245 #endif
246 static tree id;
248 /* If we have reached the end of the #pragma directive then
249 determine what value we should return. */
251 if (string == NULL)
253 int ret_val = 0;
255 switch (type)
257 default:
258 abort ();
259 break;
261 case ps_done:
262 /* The pragma was not recognised. */
263 break;
265 #ifdef HANDLE_PRAGMA_PACK
266 case ps_pack:
267 if (state == ps_right)
269 maximum_field_alignment = align * 8;
270 ret_val = 1;
272 else
273 warning ("malformed `#pragma pack'");
274 break;
275 #endif /* HANDLE_PRAGMA_PACK */
277 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
278 case ps_push:
279 if (state == ps_right)
280 ret_val = push_alignment (align, id);
281 else
282 warning ("malformed '#pragma pack(push[,id],<n>)'");
283 break;
285 case ps_pop:
286 if (state == ps_right)
287 ret_val = pop_alignment (id);
288 else
289 warning ("malformed '#pragma pack(pop[,id])'");
290 break;
291 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
293 #ifdef HANDLE_PRAGMA_WEAK
294 case ps_weak:
295 if (HANDLE_PRAGMA_WEAK)
297 if (state == ps_name)
298 ret_val = add_weak (name, NULL);
299 else if (state == ps_value)
300 ret_val = add_weak (name, value);
301 else
302 warning ("malformed `#pragma weak'");
304 else
305 ret_val = 1; /* Ignore the pragma. */
306 break;
307 #endif /* HANDLE_PRAGMA_WEAK */
309 case ps_poison:
310 ret_val = 1;
311 break;
314 type = state = ps_start;
315 id = NULL_TREE;
317 return ret_val;
320 /* If we have been given a token, but it is not an identifier,
321 or a small constant, then something has gone wrong. */
322 if (token)
324 switch (TREE_CODE (token))
326 case IDENTIFIER_NODE:
327 break;
329 case INTEGER_CST:
330 if (TREE_INT_CST_HIGH (token) != 0)
331 return 0;
332 break;
334 default:
335 return 0;
339 switch (state)
341 case ps_start:
342 type = state = ps_done;
343 #ifdef HANDLE_PRAGMA_PACK
344 if (strcmp (string, "pack") == 0)
345 type = state = ps_pack;
346 #endif
347 #ifdef HANDLE_PRAGMA_WEAK
348 if (strcmp (string, "weak") == 0)
349 type = state = ps_weak;
350 #endif
351 if (strcmp (string, "poison") == 0)
352 type = state = ps_poison;
353 break;
355 #ifdef HANDLE_PRAGMA_WEAK
356 case ps_weak:
357 name = permalloc (strlen (string) + 1);
358 if (name == NULL)
360 warning ("Out of memory parsing #pragma weak");
361 state = ps_bad;
363 else
365 strcpy (name, string);
366 state = ps_name;
368 break;
370 case ps_name:
371 state = (strcmp (string, "=") ? ps_bad : ps_equals);
372 break;
374 case ps_equals:
375 value = permalloc (strlen (string) + 1);
376 if (value == NULL)
378 warning ("Out of memory parsing #pragma weak");
379 state = ps_bad;
381 else
383 strcpy (value, string);
384 state = ps_value;
386 break;
388 case ps_value:
389 state = ps_bad;
390 break;
391 #endif /* HANDLE_PRAGMA_WEAK */
393 #ifdef HANDLE_PRAGMA_PACK
394 case ps_pack:
395 state = (strcmp (string, "(") ? ps_bad : ps_left);
396 break;
398 case ps_left:
400 if (token == NULL_TREE)
402 /* #pragma pack () resets packing rules to their
403 defaults. */
404 if (strcmp (string, ")") == 0)
406 align = 0;
407 state = ps_right;
409 else
410 state = ps_bad;
412 else if (TREE_CODE (token) == INTEGER_CST)
413 goto handle_align;
415 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
416 else if (TREE_CODE (token) == IDENTIFIER_NODE)
418 if (strcmp (string, "push") == 0)
419 type = state = ps_push;
420 else if (strcmp (string, "pop") == 0)
421 type = state = ps_pop;
422 else
423 state = ps_bad;
425 #endif
426 else
427 state = ps_bad;
428 break;
430 handle_align:
431 align = TREE_INT_CST_LOW (token);
432 switch (align)
434 case 1:
435 case 2:
436 case 4:
437 case 8:
438 case 16:
439 state = ps_align;
440 break;
442 default:
443 state = ps_bad;
444 break;
446 break;
448 case ps_align:
449 state = (strcmp (string, ")") ? ps_bad : ps_right);
450 break;
452 case ps_right:
453 state = ps_bad;
454 break;
455 #endif /* HANDLE_PRAGMA_PACK */
457 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
458 case ps_push:
459 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
460 break;
462 case ps_pushid:
463 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
464 break;
466 case ps_pushcomma:
467 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
469 id = token;
470 state = ps_pushid;
471 break;
474 /* else fall through */
475 case ps_pushcomma2:
476 if (token && TREE_CODE (token) == INTEGER_CST)
477 goto handle_align;
478 else
479 state = ps_bad;
480 break;
482 case ps_pop:
483 if (strcmp (string, ",") == 0)
484 state = ps_popcomma;
485 else
486 state = (strcmp (string, ")") ? ps_bad : ps_right);
487 break;
489 case ps_popcomma:
490 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
492 id = token;
493 state = ps_align;
495 else
496 state = ps_bad;
497 break;
498 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
500 case ps_poison:
501 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
502 state = ps_bad;
503 break;
505 case ps_bad:
506 case ps_done:
507 break;
509 default:
510 abort ();
513 return 1;
515 #endif /* HANDLE_GENERIC_PRAGMAS */
517 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
518 static void
519 mark_align_stack (p)
520 void *p;
522 align_stack *a = *(align_stack **) p;
524 while (a)
526 ggc_mark_tree (a->id);
527 a = a->prev;
530 #endif
532 void
533 init_pragma ()
535 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
536 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
537 mark_align_stack);
538 #endif