]> gcc.gnu.org Git - gcc.git/blame - gcc/c-pragma.c
tree.h (INT_CST_LT, [...]): Remove unneeded casts.
[gcc.git] / gcc / c-pragma.c
CommitLineData
a187ac95 1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
3c71940f 2 Copyright (C) 1992, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
a187ac95
RS
3
4This file is part of GNU CC.
5
6GNU CC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GNU CC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU CC; see the file COPYING. If not, write to
940d9d63
RK
18the Free Software Foundation, 59 Temple Place - Suite 330,
19Boston, MA 02111-1307, USA. */
a187ac95 20
4b578ebf 21#include "config.h"
670ee920 22#include "system.h"
d05a5492 23#include "rtl.h"
4b578ebf 24#include "tree.h"
ca695ac9 25#include "function.h"
6be160ff 26#include "defaults.h"
3d6f7931 27#include "c-pragma.h"
750caf0d 28#include "flags.h"
5f6da302 29#include "toplev.h"
da9da134 30#include "ggc.h"
4b578ebf 31
e2af664c 32#ifdef HANDLE_GENERIC_PRAGMAS
a187ac95 33
e2af664c
NC
34#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
35typedef struct align_stack
36{
37 int alignment;
38 unsigned int num_pushes;
0f92adae 39 tree id;
e2af664c
NC
40 struct align_stack * prev;
41} align_stack;
42
43static struct align_stack * alignment_stack = NULL;
44
61e8b354
MK
45/* If we have a "global" #pragma pack(<n>) if effect when the first
46 #pragma push(pack,<n>) is encountered, this stores the the value of
47 maximum_field_alignment in effect. When the final pop_alignment()
48 happens, we restore the value to this, not to a value of 0 for
49 maximum_field_alignment. Value is in bits. */
50static int default_alignment;
51
6e090c76
KG
52static int push_alignment PARAMS ((int, tree));
53static int pop_alignment PARAMS ((tree));
c6991660
KG
54#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
55static void mark_align_stack PARAMS ((void *));
56#endif
e2af664c
NC
57
58/* Push an alignment value onto the stack. */
59static int
0f92adae 60push_alignment (alignment, id)
e2af664c 61 int alignment;
0f92adae 62 tree id;
e2af664c
NC
63{
64 switch (alignment)
65 {
66 case 0:
67 case 1:
68 case 2:
69 case 4:
70 case 8:
71 case 16:
72 break;
73 default:
74 warning ("\
75Alignment must be a small power of two, not %d, in #pragma pack",
76 alignment);
77 return 0;
78 }
79
80 if (alignment_stack == NULL
0f92adae
JM
81 || alignment_stack->alignment != alignment
82 || id != NULL_TREE)
e2af664c
NC
83 {
84 align_stack * entry;
85
86 entry = (align_stack *) xmalloc (sizeof (* entry));
87
e2af664c
NC
88 entry->alignment = alignment;
89 entry->num_pushes = 1;
0f92adae 90 entry->id = id;
e2af664c
NC
91 entry->prev = alignment_stack;
92
61e8b354
MK
93 /* The current value of maximum_field_alignment is not necessarily
94 0 since there may be a #pragma pack(<n>) in effect; remember it
95 so that we can restore it after the final #pragma pop(). */
96 if (alignment_stack == NULL)
97 default_alignment = maximum_field_alignment;
98
e2af664c
NC
99 alignment_stack = entry;
100
0f92adae 101 maximum_field_alignment = alignment * 8;
e2af664c
NC
102 }
103 else
104 alignment_stack->num_pushes ++;
105
106 return 1;
107}
108
109/* Undo a push of an alignment onto the stack. */
110static int
0f92adae
JM
111pop_alignment (id)
112 tree id;
e2af664c 113{
0f92adae
JM
114 align_stack * entry;
115
e2af664c
NC
116 if (alignment_stack == NULL)
117 {
118 warning ("\
0f92adae
JM
119#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
120 );
e2af664c
NC
121 return 0;
122 }
123
0f92adae
JM
124 /* If we got an identifier, strip away everything above the target
125 entry so that the next step will restore the state just below it. */
126 if (id)
127 {
128 for (entry = alignment_stack; entry; entry = entry->prev)
129 if (entry->id == id)
130 {
131 entry->num_pushes = 1;
132 alignment_stack = entry;
133 break;
134 }
135 if (entry == NULL)
136 warning ("\
137#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
138 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
139 }
140
e2af664c
NC
141 if (-- alignment_stack->num_pushes == 0)
142 {
e2af664c
NC
143 entry = alignment_stack->prev;
144
224bb373 145 if (entry == NULL)
61e8b354 146 maximum_field_alignment = default_alignment;
e2af664c
NC
147 else
148 maximum_field_alignment = entry->alignment * 8;
149
150 free (alignment_stack);
151
152 alignment_stack = entry;
153 }
154
155 return 1;
156}
e2af664c
NC
157#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
158\f
e2af664c
NC
159/* Handle one token of a pragma directive. TOKEN is the current token, and
160 STRING is its printable form. Some front ends do not support generating
161 tokens, and will only pass in a STRING. Also some front ends will reuse
162 the buffer containing STRING, so it must be copied to a local buffer if
163 it needs to be preserved.
164
165 If STRING is non-NULL, then the return value will be ignored, and there
05bccae2 166 will be futher calls to handle_pragma_token in order to handle the rest of
e2af664c 167 the line containing the #pragma directive. If STRING is NULL, the entire
05bccae2 168 line has now been presented to handle_pragma_token and the return value
e2af664c
NC
169 should be zero if the pragma flawed in some way, or if the pragma was not
170 recognised, and non-zero if it was successfully handled. */
a187ac95 171
f09db6e0 172int
a187ac95 173handle_pragma_token (string, token)
05bccae2 174 const char *string;
a187ac95
RS
175 tree token;
176{
e2af664c
NC
177 static enum pragma_state state = ps_start;
178 static enum pragma_state type;
341a243e 179#ifdef HANDLE_PRAGMA_WEAK
05bccae2
RK
180 static char *name;
181 static char *value;
341a243e
KG
182#endif
183#if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
05bccae2 184 static unsigned int align;
341a243e 185#endif
0f92adae 186 static tree id;
a187ac95 187
e2af664c
NC
188 /* If we have reached the end of the #pragma directive then
189 determine what value we should return. */
190
f09db6e0 191 if (string == NULL)
a187ac95 192 {
e2af664c
NC
193 int ret_val = 0;
194
195 switch (type)
a187ac95 196 {
e2af664c
NC
197 default:
198 abort ();
199 break;
200
201 case ps_done:
202 /* The pragma was not recognised. */
203 break;
204
205#ifdef HANDLE_PRAGMA_PACK
206 case ps_pack:
a187ac95 207 if (state == ps_right)
f09db6e0 208 {
e2af664c 209 maximum_field_alignment = align * 8;
61e8b354
MK
210#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
211 default_alignment = maximum_field_alignment;
212#endif
e2af664c 213 ret_val = 1;
f09db6e0 214 }
e2af664c
NC
215 else
216 warning ("malformed `#pragma pack'");
217 break;
218#endif /* HANDLE_PRAGMA_PACK */
219
220#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
221 case ps_push:
222 if (state == ps_right)
0f92adae 223 ret_val = push_alignment (align, id);
e2af664c 224 else
0f92adae 225 warning ("malformed '#pragma pack(push[,id],<n>)'");
e2af664c
NC
226 break;
227
228 case ps_pop:
229 if (state == ps_right)
0f92adae 230 ret_val = pop_alignment (id);
e2af664c 231 else
0f92adae 232 warning ("malformed '#pragma pack(pop[,id])'");
e2af664c
NC
233 break;
234#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
235
a3100298 236#ifdef HANDLE_PRAGMA_WEAK
e2af664c 237 case ps_weak:
a3100298 238 if (HANDLE_PRAGMA_WEAK)
e2af664c
NC
239 {
240 if (state == ps_name)
241 ret_val = add_weak (name, NULL);
242 else if (state == ps_value)
243 ret_val = add_weak (name, value);
244 else
245 warning ("malformed `#pragma weak'");
246 }
247 else
248 ret_val = 1; /* Ignore the pragma. */
249 break;
d300e551 250#endif /* HANDLE_PRAGMA_WEAK */
fc009f96
GK
251
252 case ps_poison:
253 ret_val = 1;
254 break;
a187ac95 255 }
a187ac95
RS
256
257 type = state = ps_start;
0f92adae 258 id = NULL_TREE;
f09db6e0
NC
259
260 return ret_val;
a187ac95
RS
261 }
262
e2af664c
NC
263 /* If we have been given a token, but it is not an identifier,
264 or a small constant, then something has gone wrong. */
265 if (token)
266 {
267 switch (TREE_CODE (token))
268 {
269 case IDENTIFIER_NODE:
270 break;
271
272 case INTEGER_CST:
273 if (TREE_INT_CST_HIGH (token) != 0)
274 return 0;
275 break;
276
277 default:
278 return 0;
279 }
280 }
281
a187ac95
RS
282 switch (state)
283 {
284 case ps_start:
e2af664c
NC
285 type = state = ps_done;
286#ifdef HANDLE_PRAGMA_PACK
287 if (strcmp (string, "pack") == 0)
288 type = state = ps_pack;
289#endif
f09db6e0 290#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
291 if (strcmp (string, "weak") == 0)
292 type = state = ps_weak;
fc009f96
GK
293#endif
294 if (strcmp (string, "poison") == 0)
295 type = state = ps_poison;
a187ac95 296 break;
fc009f96 297
f09db6e0 298#ifdef HANDLE_PRAGMA_WEAK
a187ac95 299 case ps_weak:
4dd7201e
ZW
300 name = xstrdup (string);
301 state = ps_name;
a187ac95 302 break;
f09db6e0 303
a187ac95
RS
304 case ps_name:
305 state = (strcmp (string, "=") ? ps_bad : ps_equals);
306 break;
307
308 case ps_equals:
4dd7201e
ZW
309 value = xstrdup (string);
310 state = ps_value;
a187ac95
RS
311 break;
312
313 case ps_value:
314 state = ps_bad;
315 break;
e2af664c
NC
316#endif /* HANDLE_PRAGMA_WEAK */
317
318#ifdef HANDLE_PRAGMA_PACK
a187ac95 319 case ps_pack:
e2af664c 320 state = (strcmp (string, "(") ? ps_bad : ps_left);
a187ac95
RS
321 break;
322
323 case ps_left:
7169a029 324
0f92adae 325 if (token == NULL_TREE)
3cc0b551
MK
326 {
327 /* #pragma pack () resets packing rules to their
328 defaults. */
329 if (strcmp (string, ")") == 0)
330 {
331 align = 0;
332 state = ps_right;
333 }
334 else
335 state = ps_bad;
336 }
0f92adae
JM
337 else if (TREE_CODE (token) == INTEGER_CST)
338 goto handle_align;
339
340#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
341 else if (TREE_CODE (token) == IDENTIFIER_NODE)
342 {
343 if (strcmp (string, "push") == 0)
344 type = state = ps_push;
345 else if (strcmp (string, "pop") == 0)
346 type = state = ps_pop;
347 else
348 state = ps_bad;
349 }
350#endif
7169a029 351 else
0f92adae
JM
352 state = ps_bad;
353 break;
354
355 handle_align:
05bccae2 356 switch (tree_log2 (token))
a187ac95 357 {
05bccae2 358 case 0:
e2af664c
NC
359 case 1:
360 case 2:
05bccae2 361 case 3:
e2af664c
NC
362 case 4:
363 state = ps_align;
05bccae2 364 align = 1 << tree_log2 (token);
e2af664c
NC
365 break;
366
e2af664c
NC
367 default:
368 state = ps_bad;
369 break;
a187ac95 370 }
a187ac95
RS
371 break;
372
373 case ps_align:
e2af664c 374 state = (strcmp (string, ")") ? ps_bad : ps_right);
a187ac95
RS
375 break;
376
377 case ps_right:
378 state = ps_bad;
379 break;
e2af664c 380#endif /* HANDLE_PRAGMA_PACK */
a187ac95 381
e2af664c
NC
382#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
383 case ps_push:
0f92adae 384 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
e2af664c
NC
385 break;
386
0f92adae
JM
387 case ps_pushid:
388 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
389 break;
390
391 case ps_pushcomma:
392 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
393 {
394 id = token;
395 state = ps_pushid;
396 break;
397 }
398
399 /* else fall through */
400 case ps_pushcomma2:
401 if (token && TREE_CODE (token) == INTEGER_CST)
402 goto handle_align;
403 else
404 state = ps_bad;
405 break;
406
407 case ps_pop:
408 if (strcmp (string, ",") == 0)
409 state = ps_popcomma;
410 else
411 state = (strcmp (string, ")") ? ps_bad : ps_right);
412 break;
413
414 case ps_popcomma:
415 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
416 {
417 id = token;
418 state = ps_align;
419 }
420 else
421 state = ps_bad;
e2af664c
NC
422 break;
423#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
fc009f96
GK
424
425 case ps_poison:
426 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
427 state = ps_bad;
428 break;
429
a187ac95
RS
430 case ps_bad:
431 case ps_done:
432 break;
433
434 default:
435 abort ();
436 }
f09db6e0
NC
437
438 return 1;
a187ac95 439}
e2af664c 440#endif /* HANDLE_GENERIC_PRAGMAS */
568767a6
RH
441\f
442#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
443static void
444mark_align_stack (p)
445 void *p;
446{
2cccc340 447 align_stack *a = *(align_stack **) p;
568767a6
RH
448
449 while (a)
450 {
451 ggc_mark_tree (a->id);
452 a = a->prev;
453 }
454}
455#endif
456
457void
458init_pragma ()
459{
460#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
461 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
462 mark_align_stack);
463#endif
464}
This page took 0.617464 seconds and 5 git commands to generate.