]> gcc.gnu.org Git - gcc.git/blame - gcc/c-pragma.c
Daily bump.
[gcc.git] / gcc / c-pragma.c
CommitLineData
a187ac95 1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
0f92adae 2 Copyright (C) 1992, 1997, 1998, 1999 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"
4b578ebf 30
e2af664c 31#ifdef HANDLE_GENERIC_PRAGMAS
a187ac95 32
e2af664c 33#ifdef HANDLE_PRAGMA_PACK
a187ac95
RS
34/* When structure field packing is in effect, this variable is the
35 number of bits to use as the maximum alignment. When packing is not
0f41302f 36 in effect, this is zero. */
a187ac95
RS
37
38extern int maximum_field_alignment;
e2af664c
NC
39#endif
40
41
42#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
43typedef struct align_stack
44{
45 int alignment;
46 unsigned int num_pushes;
0f92adae 47 tree id;
e2af664c
NC
48 struct align_stack * prev;
49} align_stack;
50
51static struct align_stack * alignment_stack = NULL;
52
0f92adae
JM
53static int push_alignment PROTO((int, tree));
54static int pop_alignment PROTO((tree));
e2af664c
NC
55
56/* Push an alignment value onto the stack. */
57static int
0f92adae 58push_alignment (alignment, id)
e2af664c 59 int alignment;
0f92adae 60 tree id;
e2af664c
NC
61{
62 switch (alignment)
63 {
64 case 0:
65 case 1:
66 case 2:
67 case 4:
68 case 8:
69 case 16:
70 break;
71 default:
72 warning ("\
73Alignment must be a small power of two, not %d, in #pragma pack",
74 alignment);
75 return 0;
76 }
77
78 if (alignment_stack == NULL
0f92adae
JM
79 || alignment_stack->alignment != alignment
80 || id != NULL_TREE)
e2af664c
NC
81 {
82 align_stack * entry;
83
84 entry = (align_stack *) xmalloc (sizeof (* entry));
85
86 if (entry == NULL)
87 {
88 warning ("Out of memory pushing #pragma pack");
89 return 0;
90 }
91
92 entry->alignment = alignment;
93 entry->num_pushes = 1;
0f92adae 94 entry->id = id;
e2af664c
NC
95 entry->prev = alignment_stack;
96
97 alignment_stack = entry;
98
0f92adae 99 maximum_field_alignment = alignment * 8;
e2af664c
NC
100 }
101 else
102 alignment_stack->num_pushes ++;
103
104 return 1;
105}
106
107/* Undo a push of an alignment onto the stack. */
108static int
0f92adae
JM
109pop_alignment (id)
110 tree id;
e2af664c 111{
0f92adae
JM
112 align_stack * entry;
113
e2af664c
NC
114 if (alignment_stack == NULL)
115 {
116 warning ("\
0f92adae
JM
117#pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
118 );
e2af664c
NC
119 return 0;
120 }
121
0f92adae
JM
122 /* If we got an identifier, strip away everything above the target
123 entry so that the next step will restore the state just below it. */
124 if (id)
125 {
126 for (entry = alignment_stack; entry; entry = entry->prev)
127 if (entry->id == id)
128 {
129 entry->num_pushes = 1;
130 alignment_stack = entry;
131 break;
132 }
133 if (entry == NULL)
134 warning ("\
135#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
136 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
137 }
138
e2af664c
NC
139 if (-- alignment_stack->num_pushes == 0)
140 {
e2af664c
NC
141 entry = alignment_stack->prev;
142
224bb373 143 if (entry == NULL)
e2af664c
NC
144 maximum_field_alignment = 0;
145 else
146 maximum_field_alignment = entry->alignment * 8;
147
148 free (alignment_stack);
149
150 alignment_stack = entry;
151 }
152
153 return 1;
154}
155
156/* Generate 'packed' and 'aligned' attributes for decls whilst a
157 #pragma pack(push... is in effect. */
158void
159insert_pack_attributes (node, attributes, prefix)
160 tree node;
161 tree * attributes;
162 tree * prefix;
163{
164 tree a;
224bb373 165 int field_alignment;
e2af664c
NC
166
167 /* If we are not packing, then there is nothing to do. */
14ab9f52
NC
168 if (maximum_field_alignment == 0
169 || alignment_stack == NULL)
e2af664c
NC
170 return;
171
172 /* We are only interested in fields. */
173 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
174 || TREE_CODE (node) != FIELD_DECL)
175 return;
224bb373
MK
176
177 field_alignment = TYPE_ALIGN (TREE_TYPE (node));
178 if (field_alignment <= 0 || field_alignment > maximum_field_alignment)
179 field_alignment = maximum_field_alignment;
e2af664c
NC
180
181 /* Add a 'packed' attribute. */
182 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
183
184 /* If the alignment is > 8 then add an alignment attribute as well. */
224bb373 185 if (field_alignment > 8)
e2af664c
NC
186 {
187 /* If the aligned attribute is already present then do not override it. */
188 for (a = * attributes; a; a = TREE_CHAIN (a))
189 {
190 tree name = TREE_PURPOSE (a);
191 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
192 break;
193 }
194
195 if (a == NULL)
196 for (a = * prefix; a; a = TREE_CHAIN (a))
197 {
198 tree name = TREE_PURPOSE (a);
199 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
200 break;
201 }
202
203 if (a == NULL)
204 {
205 * attributes = tree_cons
206 (get_identifier ("aligned"),
207 tree_cons (NULL,
224bb373 208 build_int_2 (field_alignment / 8, 0),
e2af664c
NC
209 NULL),
210 * attributes);
211 }
212 }
213
214 return;
215}
216#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
217\f
e2af664c
NC
218/* Handle one token of a pragma directive. TOKEN is the current token, and
219 STRING is its printable form. Some front ends do not support generating
220 tokens, and will only pass in a STRING. Also some front ends will reuse
221 the buffer containing STRING, so it must be copied to a local buffer if
222 it needs to be preserved.
223
224 If STRING is non-NULL, then the return value will be ignored, and there
225 will be futher calls to handle_pragma_token() in order to handle the rest of
226 the line containing the #pragma directive. If STRING is NULL, the entire
227 line has now been presented to handle_pragma_token() and the return value
228 should be zero if the pragma flawed in some way, or if the pragma was not
229 recognised, and non-zero if it was successfully handled. */
a187ac95 230
f09db6e0 231int
a187ac95 232handle_pragma_token (string, token)
5d5993dd 233 const char * string;
a187ac95
RS
234 tree token;
235{
e2af664c
NC
236 static enum pragma_state state = ps_start;
237 static enum pragma_state type;
341a243e 238#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
239 static char * name;
240 static char * value;
341a243e
KG
241#endif
242#if defined(HANDLE_PRAGMA_PACK) || defined(HANDLE_PRAGMA_PACK_PUSH_POP)
a187ac95 243 static int align;
341a243e 244#endif
0f92adae 245 static tree id;
a187ac95 246
e2af664c
NC
247 /* If we have reached the end of the #pragma directive then
248 determine what value we should return. */
249
f09db6e0 250 if (string == NULL)
a187ac95 251 {
e2af664c
NC
252 int ret_val = 0;
253
254 switch (type)
a187ac95 255 {
e2af664c
NC
256 default:
257 abort ();
258 break;
259
260 case ps_done:
261 /* The pragma was not recognised. */
262 break;
263
264#ifdef HANDLE_PRAGMA_PACK
265 case ps_pack:
a187ac95 266 if (state == ps_right)
f09db6e0 267 {
e2af664c
NC
268 maximum_field_alignment = align * 8;
269 ret_val = 1;
f09db6e0 270 }
e2af664c
NC
271 else
272 warning ("malformed `#pragma pack'");
273 break;
274#endif /* HANDLE_PRAGMA_PACK */
275
276#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
277 case ps_push:
278 if (state == ps_right)
0f92adae 279 ret_val = push_alignment (align, id);
e2af664c 280 else
0f92adae 281 warning ("malformed '#pragma pack(push[,id],<n>)'");
e2af664c
NC
282 break;
283
284 case ps_pop:
285 if (state == ps_right)
0f92adae 286 ret_val = pop_alignment (id);
e2af664c 287 else
0f92adae 288 warning ("malformed '#pragma pack(pop[,id])'");
e2af664c
NC
289 break;
290#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
291
a3100298 292#ifdef HANDLE_PRAGMA_WEAK
e2af664c 293 case ps_weak:
a3100298 294 if (HANDLE_PRAGMA_WEAK)
e2af664c
NC
295 {
296 if (state == ps_name)
297 ret_val = add_weak (name, NULL);
298 else if (state == ps_value)
299 ret_val = add_weak (name, value);
300 else
301 warning ("malformed `#pragma weak'");
302 }
303 else
304 ret_val = 1; /* Ignore the pragma. */
305 break;
d300e551 306#endif /* HANDLE_PRAGMA_WEAK */
fc009f96
GK
307
308 case ps_poison:
309 ret_val = 1;
310 break;
a187ac95 311 }
a187ac95
RS
312
313 type = state = ps_start;
0f92adae 314 id = NULL_TREE;
f09db6e0
NC
315
316 return ret_val;
a187ac95
RS
317 }
318
e2af664c
NC
319 /* If we have been given a token, but it is not an identifier,
320 or a small constant, then something has gone wrong. */
321 if (token)
322 {
323 switch (TREE_CODE (token))
324 {
325 case IDENTIFIER_NODE:
326 break;
327
328 case INTEGER_CST:
329 if (TREE_INT_CST_HIGH (token) != 0)
330 return 0;
331 break;
332
333 default:
334 return 0;
335 }
336 }
337
a187ac95
RS
338 switch (state)
339 {
340 case ps_start:
e2af664c
NC
341 type = state = ps_done;
342#ifdef HANDLE_PRAGMA_PACK
343 if (strcmp (string, "pack") == 0)
344 type = state = ps_pack;
345#endif
f09db6e0 346#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
347 if (strcmp (string, "weak") == 0)
348 type = state = ps_weak;
fc009f96
GK
349#endif
350 if (strcmp (string, "poison") == 0)
351 type = state = ps_poison;
a187ac95 352 break;
fc009f96 353
f09db6e0 354#ifdef HANDLE_PRAGMA_WEAK
a187ac95 355 case ps_weak:
e2af664c
NC
356 name = permalloc (strlen (string) + 1);
357 if (name == NULL)
a187ac95 358 {
e2af664c
NC
359 warning ("Out of memory parsing #pragma weak");
360 state = ps_bad;
a187ac95
RS
361 }
362 else
e2af664c
NC
363 {
364 strcpy (name, string);
365 state = ps_name;
366 }
a187ac95 367 break;
f09db6e0 368
a187ac95
RS
369 case ps_name:
370 state = (strcmp (string, "=") ? ps_bad : ps_equals);
371 break;
372
373 case ps_equals:
e2af664c
NC
374 value = permalloc (strlen (string) + 1);
375 if (value == NULL)
a187ac95 376 {
e2af664c
NC
377 warning ("Out of memory parsing #pragma weak");
378 state = ps_bad;
a187ac95
RS
379 }
380 else
e2af664c
NC
381 {
382 strcpy (value, string);
383 state = ps_value;
384 }
a187ac95
RS
385 break;
386
387 case ps_value:
388 state = ps_bad;
389 break;
e2af664c
NC
390#endif /* HANDLE_PRAGMA_WEAK */
391
392#ifdef HANDLE_PRAGMA_PACK
a187ac95 393 case ps_pack:
e2af664c 394 state = (strcmp (string, "(") ? ps_bad : ps_left);
a187ac95
RS
395 break;
396
397 case ps_left:
7169a029 398
0f92adae 399 if (token == NULL_TREE)
3cc0b551
MK
400 {
401 /* #pragma pack () resets packing rules to their
402 defaults. */
403 if (strcmp (string, ")") == 0)
404 {
405 align = 0;
406 state = ps_right;
407 }
408 else
409 state = ps_bad;
410 }
0f92adae
JM
411 else if (TREE_CODE (token) == INTEGER_CST)
412 goto handle_align;
413
414#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
415 else if (TREE_CODE (token) == IDENTIFIER_NODE)
416 {
417 if (strcmp (string, "push") == 0)
418 type = state = ps_push;
419 else if (strcmp (string, "pop") == 0)
420 type = state = ps_pop;
421 else
422 state = ps_bad;
423 }
424#endif
7169a029 425 else
0f92adae
JM
426 state = ps_bad;
427 break;
428
429 handle_align:
430 align = TREE_INT_CST_LOW (token);
e2af664c 431 switch (align)
a187ac95 432 {
e2af664c
NC
433 case 1:
434 case 2:
435 case 4:
0f92adae
JM
436 case 8:
437 case 16:
e2af664c
NC
438 state = ps_align;
439 break;
440
e2af664c
NC
441 default:
442 state = ps_bad;
443 break;
a187ac95 444 }
a187ac95
RS
445 break;
446
447 case ps_align:
e2af664c 448 state = (strcmp (string, ")") ? ps_bad : ps_right);
a187ac95
RS
449 break;
450
451 case ps_right:
452 state = ps_bad;
453 break;
e2af664c 454#endif /* HANDLE_PRAGMA_PACK */
a187ac95 455
e2af664c
NC
456#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
457 case ps_push:
0f92adae 458 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma);
e2af664c
NC
459 break;
460
0f92adae
JM
461 case ps_pushid:
462 state = (strcmp (string, ",") ? ps_bad : ps_pushcomma2);
463 break;
464
465 case ps_pushcomma:
466 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
467 {
468 id = token;
469 state = ps_pushid;
470 break;
471 }
472
473 /* else fall through */
474 case ps_pushcomma2:
475 if (token && TREE_CODE (token) == INTEGER_CST)
476 goto handle_align;
477 else
478 state = ps_bad;
479 break;
480
481 case ps_pop:
482 if (strcmp (string, ",") == 0)
483 state = ps_popcomma;
484 else
485 state = (strcmp (string, ")") ? ps_bad : ps_right);
486 break;
487
488 case ps_popcomma:
489 if (token && TREE_CODE (token) == IDENTIFIER_NODE)
490 {
491 id = token;
492 state = ps_align;
493 }
494 else
495 state = ps_bad;
e2af664c
NC
496 break;
497#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
fc009f96
GK
498
499 case ps_poison:
500 if (token && TREE_CODE (token) != IDENTIFIER_NODE)
501 state = ps_bad;
502 break;
503
a187ac95
RS
504 case ps_bad:
505 case ps_done:
506 break;
507
508 default:
509 abort ();
510 }
f09db6e0
NC
511
512 return 1;
a187ac95 513}
e2af664c 514#endif /* HANDLE_GENERIC_PRAGMAS */
568767a6
RH
515\f
516#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
517static void
518mark_align_stack (p)
519 void *p;
520{
521 align_stack *a = (align_stack *) p;
522
523 while (a)
524 {
525 ggc_mark_tree (a->id);
526 a = a->prev;
527 }
528}
529#endif
530
531void
532init_pragma ()
533{
534#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
535 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack),
536 mark_align_stack);
537#endif
538}
This page took 0.555906 seconds and 5 git commands to generate.