]> gcc.gnu.org Git - gcc.git/blame - gcc/c-pragma.c
ttp53.C: New test.
[gcc.git] / gcc / c-pragma.c
CommitLineData
a187ac95 1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack.
f09db6e0 2 Copyright (C) 1992, 1997, 1998 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"
1ef08c63 25#include "except.h"
ca695ac9 26#include "function.h"
6be160ff 27#include "defaults.h"
3d6f7931 28#include "c-pragma.h"
750caf0d 29#include "flags.h"
5f6da302 30#include "toplev.h"
4b578ebf 31
e2af664c 32#ifdef HANDLE_GENERIC_PRAGMAS
a187ac95 33
e2af664c 34#ifdef HANDLE_PRAGMA_PACK
a187ac95
RS
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
0f41302f 37 in effect, this is zero. */
a187ac95
RS
38
39extern int maximum_field_alignment;
e2af664c
NC
40#endif
41
42
43#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
44typedef struct align_stack
45{
46 int alignment;
47 unsigned int num_pushes;
48 struct align_stack * prev;
49} align_stack;
50
51static struct align_stack * alignment_stack = NULL;
52
53static int push_alignment PROTO((int));
54static int pop_alignment PROTO((void));
55
56/* Push an alignment value onto the stack. */
57static int
58push_alignment (alignment)
59 int alignment;
60{
61 switch (alignment)
62 {
63 case 0:
64 case 1:
65 case 2:
66 case 4:
67 case 8:
68 case 16:
69 break;
70 default:
71 warning ("\
72Alignment must be a small power of two, not %d, in #pragma pack",
73 alignment);
74 return 0;
75 }
76
77 if (alignment_stack == NULL
78 || alignment_stack->alignment != alignment)
79 {
80 align_stack * entry;
81
82 entry = (align_stack *) xmalloc (sizeof (* entry));
83
84 if (entry == NULL)
85 {
86 warning ("Out of memory pushing #pragma pack");
87 return 0;
88 }
89
90 entry->alignment = alignment;
91 entry->num_pushes = 1;
92 entry->prev = alignment_stack;
93
94 alignment_stack = entry;
95
96 if (alignment < 8)
97 maximum_field_alignment = alignment * 8;
98 else
99 /* MSVC ignores alignments > 4. */
100 maximum_field_alignment = 0;
101 }
102 else
103 alignment_stack->num_pushes ++;
104
105 return 1;
106}
107
108/* Undo a push of an alignment onto the stack. */
109static int
110pop_alignment ()
111{
112 if (alignment_stack == NULL)
113 {
114 warning ("\
115#pragma pack(pop) encountered without corresponding #pragma pack(push,<n>)");
116 return 0;
117 }
118
119 if (-- alignment_stack->num_pushes == 0)
120 {
121 align_stack * entry;
122
123 entry = alignment_stack->prev;
124
125 if (entry == NULL || entry->alignment > 4)
126 maximum_field_alignment = 0;
127 else
128 maximum_field_alignment = entry->alignment * 8;
129
130 free (alignment_stack);
131
132 alignment_stack = entry;
133 }
134
135 return 1;
136}
137
138/* Generate 'packed' and 'aligned' attributes for decls whilst a
139 #pragma pack(push... is in effect. */
140void
141insert_pack_attributes (node, attributes, prefix)
142 tree node;
143 tree * attributes;
144 tree * prefix;
145{
146 tree a;
147
148 /* If we are not packing, then there is nothing to do. */
14ab9f52
NC
149 if (maximum_field_alignment == 0
150 || alignment_stack == NULL)
e2af664c
NC
151 return;
152
153 /* We are only interested in fields. */
154 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd'
155 || TREE_CODE (node) != FIELD_DECL)
156 return;
157
158 /* Add a 'packed' attribute. */
159 * attributes = tree_cons (get_identifier ("packed"), NULL, * attributes);
160
161 /* If the alignment is > 8 then add an alignment attribute as well. */
162 if (maximum_field_alignment > 8)
163 {
164 /* If the aligned attribute is already present then do not override it. */
165 for (a = * attributes; a; a = TREE_CHAIN (a))
166 {
167 tree name = TREE_PURPOSE (a);
168 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
169 break;
170 }
171
172 if (a == NULL)
173 for (a = * prefix; a; a = TREE_CHAIN (a))
174 {
175 tree name = TREE_PURPOSE (a);
176 if (strcmp (IDENTIFIER_POINTER (name), "aligned") == 0)
177 break;
178 }
179
180 if (a == NULL)
181 {
182 * attributes = tree_cons
183 (get_identifier ("aligned"),
184 tree_cons (NULL,
185 build_int_2 (maximum_field_alignment / 8, 0),
186 NULL),
187 * attributes);
188 }
189 }
190
191 return;
192}
193#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
194\f
195#ifdef HANDLE_PRAGMA_WEAK
196static int add_weak PROTO((char *, char *));
197
198static int
199add_weak (name, value)
200 char * name;
201 char * value;
202{
203 struct weak_syms * weak;
a187ac95 204
e2af664c
NC
205 weak = (struct weak_syms *) permalloc (sizeof (struct weak_syms));
206
207 if (weak == NULL)
208 return 0;
209
210 weak->next = weak_decls;
211 weak->name = name;
212 weak->value = value;
213 weak_decls = weak;
214
215 return 1;
216}
217#endif /* HANDLE_PRAGMA_WEAK */
218\f
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.
224
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. */
a187ac95 231
f09db6e0 232int
a187ac95 233handle_pragma_token (string, token)
e2af664c 234 char * string;
a187ac95
RS
235 tree token;
236{
e2af664c
NC
237 static enum pragma_state state = ps_start;
238 static enum pragma_state type;
239 static char * name;
240 static char * value;
a187ac95
RS
241 static int align;
242
e2af664c
NC
243 /* If we have reached the end of the #pragma directive then
244 determine what value we should return. */
245
f09db6e0 246 if (string == NULL)
a187ac95 247 {
e2af664c
NC
248 int ret_val = 0;
249
250 switch (type)
a187ac95 251 {
e2af664c
NC
252 default:
253 abort ();
254 break;
255
256 case ps_done:
257 /* The pragma was not recognised. */
258 break;
259
260#ifdef HANDLE_PRAGMA_PACK
261 case ps_pack:
a187ac95 262 if (state == ps_right)
f09db6e0 263 {
e2af664c
NC
264 maximum_field_alignment = align * 8;
265 ret_val = 1;
f09db6e0 266 }
e2af664c
NC
267 else
268 warning ("malformed `#pragma pack'");
269 break;
270#endif /* HANDLE_PRAGMA_PACK */
271
272#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
273 case ps_push:
274 if (state == ps_right)
275 ret_val = push_alignment (align);
276 else
277 warning ("incomplete '#pragma pack(push,<n>)'");
278 break;
279
280 case ps_pop:
281 if (state == ps_right)
282 ret_val = pop_alignment ();
283 else
284 warning ("missing closing parenthesis in '#pragma pack(pop)'");
285 break;
286#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
287
a3100298 288#ifdef HANDLE_PRAGMA_WEAK
e2af664c 289 case ps_weak:
a3100298 290 if (HANDLE_PRAGMA_WEAK)
e2af664c
NC
291 {
292 if (state == ps_name)
293 ret_val = add_weak (name, NULL);
294 else if (state == ps_value)
295 ret_val = add_weak (name, value);
296 else
297 warning ("malformed `#pragma weak'");
298 }
299 else
300 ret_val = 1; /* Ignore the pragma. */
301 break;
d300e551 302#endif /* HANDLE_PRAGMA_WEAK */
a187ac95 303 }
a187ac95
RS
304
305 type = state = ps_start;
f09db6e0
NC
306
307 return ret_val;
a187ac95
RS
308 }
309
e2af664c
NC
310 /* If we have been given a token, but it is not an identifier,
311 or a small constant, then something has gone wrong. */
312 if (token)
313 {
314 switch (TREE_CODE (token))
315 {
316 case IDENTIFIER_NODE:
317 break;
318
319 case INTEGER_CST:
320 if (TREE_INT_CST_HIGH (token) != 0)
321 return 0;
322 break;
323
324 default:
325 return 0;
326 }
327 }
328
a187ac95
RS
329 switch (state)
330 {
331 case ps_start:
e2af664c
NC
332 type = state = ps_done;
333#ifdef HANDLE_PRAGMA_PACK
334 if (strcmp (string, "pack") == 0)
335 type = state = ps_pack;
336#endif
f09db6e0 337#ifdef HANDLE_PRAGMA_WEAK
e2af664c
NC
338 if (strcmp (string, "weak") == 0)
339 type = state = ps_weak;
f09db6e0 340#endif
a187ac95 341 break;
f09db6e0
NC
342
343#ifdef HANDLE_PRAGMA_WEAK
a187ac95 344 case ps_weak:
e2af664c
NC
345 name = permalloc (strlen (string) + 1);
346 if (name == NULL)
a187ac95 347 {
e2af664c
NC
348 warning ("Out of memory parsing #pragma weak");
349 state = ps_bad;
a187ac95
RS
350 }
351 else
e2af664c
NC
352 {
353 strcpy (name, string);
354 state = ps_name;
355 }
a187ac95 356 break;
f09db6e0 357
a187ac95
RS
358 case ps_name:
359 state = (strcmp (string, "=") ? ps_bad : ps_equals);
360 break;
361
362 case ps_equals:
e2af664c
NC
363 value = permalloc (strlen (string) + 1);
364 if (value == NULL)
a187ac95 365 {
e2af664c
NC
366 warning ("Out of memory parsing #pragma weak");
367 state = ps_bad;
a187ac95
RS
368 }
369 else
e2af664c
NC
370 {
371 strcpy (value, string);
372 state = ps_value;
373 }
a187ac95
RS
374 break;
375
376 case ps_value:
377 state = ps_bad;
378 break;
e2af664c
NC
379#endif /* HANDLE_PRAGMA_WEAK */
380
381#ifdef HANDLE_PRAGMA_PACK
a187ac95 382 case ps_pack:
e2af664c 383 state = (strcmp (string, "(") ? ps_bad : ps_left);
a187ac95
RS
384 break;
385
386 case ps_left:
e2af664c
NC
387 align = atoi (string);
388 switch (align)
a187ac95 389 {
e2af664c
NC
390 case 1:
391 case 2:
392 case 4:
393 state = ps_align;
394 break;
395
396 case 0:
397 state = (strcmp (string, ")") ? ps_bad : ps_right);
398#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
399 if (state == ps_bad)
400 {
401 if (strcmp (string, "push") == 0)
402 type = state = ps_push;
403 else if (strcmp (string, "pop") == 0)
404 type = state = ps_pop;
405 }
406#endif
407 break;
408
409 default:
410 state = ps_bad;
411 break;
a187ac95 412 }
a187ac95
RS
413 break;
414
e2af664c
NC
415#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
416 case ps_pop:
417#endif
a187ac95 418 case ps_align:
e2af664c 419 state = (strcmp (string, ")") ? ps_bad : ps_right);
a187ac95
RS
420 break;
421
422 case ps_right:
423 state = ps_bad;
424 break;
e2af664c 425#endif /* HANDLE_PRAGMA_PACK */
a187ac95 426
e2af664c
NC
427#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
428 case ps_push:
429 state = (strcmp (string, ",") ? ps_bad : ps_comma);
430 break;
431
432 case ps_comma:
433 align = atoi (string);
434 state = ps_align;
435 break;
436#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
437
a187ac95
RS
438 case ps_bad:
439 case ps_done:
440 break;
441
442 default:
443 abort ();
444 }
f09db6e0
NC
445
446 return 1;
a187ac95 447}
e2af664c 448#endif /* HANDLE_GENERIC_PRAGMAS */
This page took 0.406386 seconds and 5 git commands to generate.