* decl.c (grokfndecl): Remove dead code.
[official-gcc.git] / gcc / c-pragma.c
blob86bd5c48e1e7a240f24647f4d52a98cff7e92b5f
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 /* If we have a "global" #pragma pack(<n>) if effect when the first
55 #pragma push(pack,<n>) is encountered, this stores the the value of
56 maximum_field_alignment in effect. When the final pop_alignment()
57 happens, we restore the value to this, not to a value of 0 for
58 maximum_field_alignment. Value is in bits. */
59 static int default_alignment;
61 static int push_alignment PROTO((int, tree));
62 static int pop_alignment PROTO((tree));
64 /* Push an alignment value onto the stack. */
65 static int
66 push_alignment (alignment, id)
67 int alignment;
68 tree id;
70 switch (alignment)
72 case 0:
73 case 1:
74 case 2:
75 case 4:
76 case 8:
77 case 16:
78 break;
79 default:
80 warning ("\
81 Alignment must be a small power of two, not %d, in #pragma pack",
82 alignment);
83 return 0;
86 if (alignment_stack == NULL
87 || alignment_stack->alignment != alignment
88 || id != NULL_TREE)
90 align_stack * entry;
92 entry = (align_stack *) xmalloc (sizeof (* entry));
94 entry->alignment = alignment;
95 entry->num_pushes = 1;
96 entry->id = id;
97 entry->prev = alignment_stack;
99 /* The current value of maximum_field_alignment is not necessarily
100 0 since there may be a #pragma pack(<n>) in effect; remember it
101 so that we can restore it after the final #pragma pop(). */
102 if (alignment_stack == NULL)
103 default_alignment = maximum_field_alignment;
105 alignment_stack = entry;
107 maximum_field_alignment = alignment * 8;
109 else
110 alignment_stack->num_pushes ++;
112 return 1;
115 /* Undo a push of an alignment onto the stack. */
116 static int
117 pop_alignment (id)
118 tree id;
120 align_stack * entry;
122 if (alignment_stack == NULL)
124 warning ("\
125 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
127 return 0;
130 /* If we got an identifier, strip away everything above the target
131 entry so that the next step will restore the state just below it. */
132 if (id)
134 for (entry = alignment_stack; entry; entry = entry->prev)
135 if (entry->id == id)
137 entry->num_pushes = 1;
138 alignment_stack = entry;
139 break;
141 if (entry == NULL)
142 warning ("\
143 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
144 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
147 if (-- alignment_stack->num_pushes == 0)
149 entry = alignment_stack->prev;
151 if (entry == NULL)
152 maximum_field_alignment = default_alignment;
153 else
154 maximum_field_alignment = entry->alignment * 8;
156 free (alignment_stack);
158 alignment_stack = entry;
161 return 1;
163 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
165 /* Handle one token of a pragma directive. TOKEN is the current token, and
166 STRING is its printable form. Some front ends do not support generating
167 tokens, and will only pass in a STRING. Also some front ends will reuse
168 the buffer containing STRING, so it must be copied to a local buffer if
169 it needs to be preserved.
171 If STRING is non-NULL, then the return value will be ignored, and there
172 will be futher calls to handle_pragma_token() in order to handle the rest of
173 the line containing the #pragma directive. If STRING is NULL, the entire
174 line has now been presented to handle_pragma_token() and the return value
175 should be zero if the pragma flawed in some way, or if the pragma was not
176 recognised, and non-zero if it was successfully handled. */
179 handle_pragma_token (string, token)
180 const char * string;
181 tree token;
183 static enum pragma_state state = ps_start;
184 static enum pragma_state type;
185 #ifdef HANDLE_PRAGMA_WEAK
186 static char * name;
187 static char * value;
188 #endif
189 #if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
190 static int align;
191 #endif
192 static tree id;
194 /* If we have reached the end of the #pragma directive then
195 determine what value we should return. */
197 if (string == NULL)
199 int ret_val = 0;
201 switch (type)
203 default:
204 abort ();
205 break;
207 case ps_done:
208 /* The pragma was not recognised. */
209 break;
211 #ifdef HANDLE_PRAGMA_PACK
212 case ps_pack:
213 if (state == ps_right)
215 maximum_field_alignment = align * 8;
216 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
217 default_alignment = maximum_field_alignment;
218 #endif
219 ret_val = 1;
221 else
222 warning ("malformed `#pragma pack'");
223 break;
224 #endif /* HANDLE_PRAGMA_PACK */
226 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
227 case ps_push:
228 if (state == ps_right)
229 ret_val = push_alignment (align, id);
230 else
231 warning ("malformed '#pragma pack(push[,id],<n>)'");
232 break;
234 case ps_pop:
235 if (state == ps_right)
236 ret_val = pop_alignment (id);
237 else
238 warning ("malformed '#pragma pack(pop[,id])'");
239 break;
240 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
242 #ifdef HANDLE_PRAGMA_WEAK
243 case ps_weak:
244 if (HANDLE_PRAGMA_WEAK)
246 if (state == ps_name)
247 ret_val = add_weak (name, NULL);
248 else if (state == ps_value)
249 ret_val = add_weak (name, value);
250 else
251 warning ("malformed `#pragma weak'");
253 else
254 ret_val = 1; /* Ignore the pragma. */
255 break;
256 #endif /* HANDLE_PRAGMA_WEAK */
258 case ps_poison:
259 ret_val = 1;
260 break;
263 type = state = ps_start;
264 id = NULL_TREE;
266 return ret_val;
269 /* If we have been given a token, but it is not an identifier,
270 or a small constant, then something has gone wrong. */
271 if (token)
273 switch (TREE_CODE (token))
275 case IDENTIFIER_NODE:
276 break;
278 case INTEGER_CST:
279 if (TREE_INT_CST_HIGH (token) != 0)
280 return 0;
281 break;
283 default:
284 return 0;
288 switch (state)
290 case ps_start:
291 type = state = ps_done;
292 #ifdef HANDLE_PRAGMA_PACK
293 if (strcmp (string, "pack") == 0)
294 type = state = ps_pack;
295 #endif
296 #ifdef HANDLE_PRAGMA_WEAK
297 if (strcmp (string, "weak") == 0)
298 type = state = ps_weak;
299 #endif
300 if (strcmp (string, "poison") == 0)
301 type = state = ps_poison;
302 break;
304 #ifdef HANDLE_PRAGMA_WEAK
305 case ps_weak:
306 name = permalloc (strlen (string) + 1);
307 if (name == NULL)
309 warning ("Out of memory parsing #pragma weak");
310 state = ps_bad;
312 else
314 strcpy (name, string);
315 state = ps_name;
317 break;
319 case ps_name:
320 state = (strcmp (string, "=") ? ps_bad : ps_equals);
321 break;
323 case ps_equals:
324 value = permalloc (strlen (string) + 1);
325 if (value == NULL)
327 warning ("Out of memory parsing #pragma weak");
328 state = ps_bad;
330 else
332 strcpy (value, string);
333 state = ps_value;
335 break;
337 case ps_value:
338 state = ps_bad;
339 break;
340 #endif /* HANDLE_PRAGMA_WEAK */
342 #ifdef HANDLE_PRAGMA_PACK
343 case ps_pack:
344 state = (strcmp (string, "(") ? ps_bad : ps_left);
345 break;
347 case ps_left:
349 if (token == NULL_TREE)
351 /* #pragma pack () resets packing rules to their
352 defaults. */
353 if (strcmp (string, ")") == 0)
355 align = 0;
356 state = ps_right;
358 else
359 state = ps_bad;
361 else if (TREE_CODE (token) == INTEGER_CST)
362 goto handle_align;
364 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
365 else if (TREE_CODE (token) == IDENTIFIER_NODE)
367 if (strcmp (string, "push") == 0)
368 type = state = ps_push;
369 else if (strcmp (string, "pop") == 0)
370 type = state = ps_pop;
371 else
372 state = ps_bad;
374 #endif
375 else
376 state = ps_bad;
377 break;
379 handle_align:
380 align = TREE_INT_CST_LOW (token);
381 switch (align)
383 case 1:
384 case 2:
385 case 4:
386 case 8:
387 case 16:
388 state = ps_align;
389 break;
391 default:
392 state = ps_bad;
393 break;
395 break;
397 case ps_align:
398 state = (strcmp (string, ")") ? ps_bad : ps_right);
399 break;
401 case ps_right:
402 state = ps_bad;
403 break;
404 #endif /* HANDLE_PRAGMA_PACK */
406 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
407 case ps_push:
408 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
409 break;
411 case ps_pushid:
412 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
413 break;
415 case ps_pushcomma:
416 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
418 id = token;
419 state = ps_pushid;
420 break;
423 /* else fall through */
424 case ps_pushcomma2:
425 if (token && TREE_CODE (token) == INTEGER_CST)
426 goto handle_align;
427 else
428 state = ps_bad;
429 break;
431 case ps_pop:
432 if (strcmp (string, ",") == 0)
433 state = ps_popcomma;
434 else
435 state = (strcmp (string, ")") ? ps_bad : ps_right);
436 break;
438 case ps_popcomma:
439 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
441 id = token;
442 state = ps_align;
444 else
445 state = ps_bad;
446 break;
447 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
449 case ps_poison:
450 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
451 state = ps_bad;
452 break;
454 case ps_bad:
455 case ps_done:
456 break;
458 default:
459 abort ();
462 return 1;
464 #endif /* HANDLE_GENERIC_PRAGMAS */
466 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
467 static void
468 mark_align_stack (p)
469 void *p;
471 align_stack *a = *(align_stack **) p;
473 while (a)
475 ggc_mark_tree (a->id);
476 a = a->prev;
479 #endif
481 void
482 init_pragma ()
484 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
485 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
486 mark_align_stack);
487 #endif