xref: /openbsd-src/gnu/usr.bin/gcc/gcc/c-pragma.c (revision c87b03e512fc05ed6e0222f6fb0ae86264b1d05b)
1 /* Handle #pragma, system V.4 style.  Supports #pragma weak and #pragma pack.
2    Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002
3    Free Software Foundation, Inc.
4 
5 This file is part of GCC.
6 
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11 
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21 
22 #include "config.h"
23 #include "system.h"
24 #include "rtl.h"
25 #include "tree.h"
26 #include "function.h"
27 #include "cpplib.h"
28 #include "c-pragma.h"
29 #include "flags.h"
30 #include "toplev.h"
31 #include "ggc.h"
32 #include "c-common.h"
33 #include "output.h"
34 #include "tm_p.h"
35 
36 #define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
37 #define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
38 
39 typedef struct align_stack GTY(())
40 {
41   int                  alignment;
42   unsigned int         num_pushes;
43   tree                 id;
44   struct align_stack * prev;
45 } align_stack;
46 
47 static GTY(()) struct align_stack * alignment_stack;
48 
49 #ifdef HANDLE_PRAGMA_PACK
50 static void handle_pragma_pack PARAMS ((cpp_reader *));
51 
52 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
53 /* If we have a "global" #pragma pack(<n>) in effect when the first
54    #pragma pack(push,<n>) is encountered, this stores the value of
55    maximum_field_alignment in effect.  When the final pop_alignment()
56    happens, we restore the value to this, not to a value of 0 for
57    maximum_field_alignment.  Value is in bits.  */
58 static int default_alignment;
59 #define SET_GLOBAL_ALIGNMENT(ALIGN) \
60   (default_alignment = maximum_field_alignment = (ALIGN))
61 
62 static void push_alignment PARAMS ((int, tree));
63 static void pop_alignment  PARAMS ((tree));
64 
65 /* Push an alignment value onto the stack.  */
66 static void
push_alignment(alignment,id)67 push_alignment (alignment, id)
68      int alignment;
69      tree id;
70 {
71   if (alignment_stack == NULL
72       || alignment_stack->alignment != alignment
73       || id != NULL_TREE)
74     {
75       align_stack * entry;
76 
77       entry = (align_stack *) ggc_alloc (sizeof (* entry));
78 
79       entry->alignment  = alignment;
80       entry->num_pushes = 1;
81       entry->id         = id;
82       entry->prev       = alignment_stack;
83 
84       /* The current value of maximum_field_alignment is not necessarily
85 	 0 since there may be a #pragma pack(<n>) in effect; remember it
86 	 so that we can restore it after the final #pragma pop().  */
87       if (alignment_stack == NULL)
88 	default_alignment = maximum_field_alignment;
89 
90       alignment_stack = entry;
91 
92       maximum_field_alignment = alignment;
93     }
94   else
95     alignment_stack->num_pushes ++;
96 }
97 
98 /* Undo a push of an alignment onto the stack.  */
99 static void
pop_alignment(id)100 pop_alignment (id)
101      tree id;
102 {
103   align_stack * entry;
104 
105   if (alignment_stack == NULL)
106     {
107       warning ("\
108 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
109 	       );
110       return;
111     }
112 
113   /* If we got an identifier, strip away everything above the target
114      entry so that the next step will restore the state just below it.  */
115   if (id)
116     {
117       for (entry = alignment_stack; entry; entry = entry->prev)
118 	if (entry->id == id)
119 	  {
120 	    entry->num_pushes = 1;
121 	    alignment_stack = entry;
122 	    break;
123 	  }
124       if (entry == NULL)
125 	warning ("\
126 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
127 		 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
128     }
129 
130   if (-- alignment_stack->num_pushes == 0)
131     {
132       entry = alignment_stack->prev;
133 
134       if (entry == NULL)
135 	maximum_field_alignment = default_alignment;
136       else
137 	maximum_field_alignment = entry->alignment;
138 
139       alignment_stack = entry;
140     }
141 }
142 #else  /* not HANDLE_PRAGMA_PACK_PUSH_POP */
143 #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
144 #define push_alignment(ID, N) \
145     GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target")
146 #define pop_alignment(ID) \
147     GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target")
148 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
149 
150 /* #pragma pack ()
151    #pragma pack (N)
152 
153    #pragma pack (push, N)
154    #pragma pack (push, ID, N)
155    #pragma pack (pop)
156    #pragma pack (pop, ID) */
157 static void
handle_pragma_pack(dummy)158 handle_pragma_pack (dummy)
159      cpp_reader *dummy ATTRIBUTE_UNUSED;
160 {
161   tree x, id = 0;
162   int align = -1;
163   enum cpp_ttype token;
164   enum { set, push, pop } action;
165 
166   if (c_lex (&x) != CPP_OPEN_PAREN)
167     GCC_BAD ("missing '(' after '#pragma pack' - ignored");
168 
169   token = c_lex (&x);
170   if (token == CPP_CLOSE_PAREN)
171     {
172       action = set;
173       align = 0;
174     }
175   else if (token == CPP_NUMBER)
176     {
177       align = TREE_INT_CST_LOW (x);
178       action = set;
179       if (c_lex (&x) != CPP_CLOSE_PAREN)
180 	GCC_BAD ("malformed '#pragma pack' - ignored");
181     }
182   else if (token == CPP_NAME)
183     {
184 #define GCC_BAD_ACTION do { if (action == push) \
185 	  GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
186 	else \
187 	  GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
188 	} while (0)
189 
190       const char *op = IDENTIFIER_POINTER (x);
191       if (!strcmp (op, "push"))
192 	action = push;
193       else if (!strcmp (op, "pop"))
194 	action = pop;
195       else
196 	GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
197 
198       token = c_lex (&x);
199       if (token != CPP_COMMA && action == push)
200 	GCC_BAD_ACTION;
201 
202       if (token == CPP_COMMA)
203 	{
204 	  token = c_lex (&x);
205 	  if (token == CPP_NAME)
206 	    {
207 	      id = x;
208 	      if (action == push && c_lex (&x) != CPP_COMMA)
209 		GCC_BAD_ACTION;
210 	      token = c_lex (&x);
211 	    }
212 
213 	  if (action == push)
214 	    {
215 	      if (token == CPP_NUMBER)
216 		{
217 		  align = TREE_INT_CST_LOW (x);
218 		  token = c_lex (&x);
219 		}
220 	      else
221 		GCC_BAD_ACTION;
222 	    }
223 	}
224 
225       if (token != CPP_CLOSE_PAREN)
226 	GCC_BAD_ACTION;
227 #undef GCC_BAD_ACTION
228     }
229   else
230     GCC_BAD ("malformed '#pragma pack' - ignored");
231 
232   if (c_lex (&x) != CPP_EOF)
233     warning ("junk at end of '#pragma pack'");
234 
235   if (action != pop)
236     switch (align)
237       {
238       case 0:
239       case 1:
240       case 2:
241       case 4:
242       case 8:
243       case 16:
244 	align *= BITS_PER_UNIT;
245 	break;
246       default:
247 	GCC_BAD2 ("alignment must be a small power of two, not %d", align);
248       }
249 
250   switch (action)
251     {
252     case set:   SET_GLOBAL_ALIGNMENT (align);  break;
253     case push:  push_alignment (align, id);    break;
254     case pop:   pop_alignment (id);            break;
255     }
256 }
257 #endif  /* HANDLE_PRAGMA_PACK */
258 
259 static GTY(()) tree pending_weaks;
260 
261 #ifdef HANDLE_PRAGMA_WEAK
262 static void apply_pragma_weak PARAMS ((tree, tree));
263 static void handle_pragma_weak PARAMS ((cpp_reader *));
264 
265 static void
apply_pragma_weak(decl,value)266 apply_pragma_weak (decl, value)
267      tree decl, value;
268 {
269   if (value)
270     {
271       value = build_string (IDENTIFIER_LENGTH (value),
272 			    IDENTIFIER_POINTER (value));
273       decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
274 					       build_tree_list (NULL, value)),
275 		       0);
276     }
277 
278   if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
279       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
280     warning_with_decl (decl, "applying #pragma weak `%s' after first use results in unspecified behavior");
281 
282   declare_weak (decl);
283 }
284 
285 void
maybe_apply_pragma_weak(decl)286 maybe_apply_pragma_weak (decl)
287      tree decl;
288 {
289   tree *p, t, id;
290 
291   /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed.  */
292 
293   /* No weak symbols pending, take the short-cut.  */
294   if (!pending_weaks)
295     return;
296   /* If it's not visible outside this file, it doesn't matter whether
297      it's weak.  */
298   if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
299     return;
300   /* If it's not a function or a variable, it can't be weak.
301      FIXME: what kinds of things are visible outside this file but
302      aren't functions or variables?   Should this be an abort() instead?  */
303   if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
304     return;
305 
306   id = DECL_ASSEMBLER_NAME (decl);
307 
308   for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t))
309     if (id == TREE_PURPOSE (t))
310       {
311 	apply_pragma_weak (decl, TREE_VALUE (t));
312 	*p = TREE_CHAIN (t);
313 	break;
314       }
315 }
316 
317 /* #pragma weak name [= value] */
318 static void
handle_pragma_weak(dummy)319 handle_pragma_weak (dummy)
320      cpp_reader *dummy ATTRIBUTE_UNUSED;
321 {
322   tree name, value, x, decl;
323   enum cpp_ttype t;
324 
325   value = 0;
326 
327   if (c_lex (&name) != CPP_NAME)
328     GCC_BAD ("malformed #pragma weak, ignored");
329   t = c_lex (&x);
330   if (t == CPP_EQ)
331     {
332       if (c_lex (&value) != CPP_NAME)
333 	GCC_BAD ("malformed #pragma weak, ignored");
334       t = c_lex (&x);
335     }
336   if (t != CPP_EOF)
337     warning ("junk at end of #pragma weak");
338 
339   decl = identifier_global_value (name);
340   if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
341     {
342       apply_pragma_weak (decl, value);
343       if (value)
344 	assemble_alias (decl, value);
345     }
346   else
347     pending_weaks = tree_cons (name, value, pending_weaks);
348 }
349 #else
350 void
maybe_apply_pragma_weak(decl)351 maybe_apply_pragma_weak (decl)
352      tree decl ATTRIBUTE_UNUSED;
353 {
354 }
355 #endif /* HANDLE_PRAGMA_WEAK */
356 
357 static GTY(()) tree pending_redefine_extname;
358 
359 #ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
360 static void handle_pragma_redefine_extname PARAMS ((cpp_reader *));
361 
362 /* #pragma redefined_extname oldname newname */
363 static void
handle_pragma_redefine_extname(dummy)364 handle_pragma_redefine_extname (dummy)
365      cpp_reader *dummy ATTRIBUTE_UNUSED;
366 {
367   tree oldname, newname, decl, x;
368   enum cpp_ttype t;
369 
370   if (c_lex (&oldname) != CPP_NAME)
371     {
372       warning ("malformed #pragma redefine_extname, ignored");
373       return;
374     }
375   if (c_lex (&newname) != CPP_NAME)
376     {
377       warning ("malformed #pragma redefine_extname, ignored");
378       return;
379     }
380   t = c_lex (&x);
381   if (t != CPP_EOF)
382     warning ("junk at end of #pragma redefine_extname");
383 
384   decl = identifier_global_value (oldname);
385   if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
386     {
387       if (DECL_ASSEMBLER_NAME_SET_P (decl)
388 	  && DECL_ASSEMBLER_NAME (decl) != newname)
389         warning ("#pragma redefine_extname conflicts with declaration");
390       SET_DECL_ASSEMBLER_NAME (decl, newname);
391     }
392   else
393     add_to_renaming_pragma_list(oldname, newname);
394 }
395 #endif
396 
397 void
add_to_renaming_pragma_list(oldname,newname)398 add_to_renaming_pragma_list (oldname, newname)
399 	tree oldname, newname;
400 {
401   pending_redefine_extname
402     = tree_cons (oldname, newname, pending_redefine_extname);
403 }
404 
405 static GTY(()) tree pragma_extern_prefix;
406 
407 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
408 static void handle_pragma_extern_prefix PARAMS ((cpp_reader *));
409 
410 /* #pragma extern_prefix "prefix" */
411 static void
handle_pragma_extern_prefix(dummy)412 handle_pragma_extern_prefix (dummy)
413      cpp_reader *dummy ATTRIBUTE_UNUSED;
414 {
415   tree prefix, x;
416   enum cpp_ttype t;
417 
418   if (c_lex (&prefix) != CPP_STRING)
419     {
420       warning ("malformed #pragma extern_prefix, ignored");
421       return;
422     }
423   t = c_lex (&x);
424   if (t != CPP_EOF)
425     warning ("junk at end of #pragma extern_prefix");
426 
427   /* Note that the length includes the null terminator.  */
428   pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
429 }
430 #endif
431 
432 /* Hook from the front ends to apply the results of one of the preceeding
433    pragmas that rename variables.  */
434 
435 tree
maybe_apply_renaming_pragma(decl,asmname)436 maybe_apply_renaming_pragma (decl, asmname)
437      tree decl, asmname;
438 {
439   tree oldname;
440 
441   /* Copied from the check in set_decl_assembler_name.  */
442   if (TREE_CODE (decl) == FUNCTION_DECL
443       || (TREE_CODE (decl) == VAR_DECL
444           && (TREE_STATIC (decl)
445               || DECL_EXTERNAL (decl)
446               || TREE_PUBLIC (decl))))
447     oldname = DECL_ASSEMBLER_NAME (decl);
448   else
449     return asmname;
450 
451   /* If the name begins with a *, that's a sign of an asmname attached to
452      a previous declaration.  */
453   if (IDENTIFIER_POINTER (oldname)[0] == '*')
454     {
455       const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1;
456       if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0)
457 	warning ("asm declaration conflicts with previous rename");
458       asmname = build_string (strlen (oldasmname), oldasmname);
459     }
460 
461   {
462     tree *p, t;
463 
464     for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t))
465       if (oldname == TREE_PURPOSE (t))
466 	{
467 	  const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t));
468 
469 	  if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0)
470             warning ("#pragma redefine_extname conflicts with declaration");
471 	  *p = TREE_CHAIN (t);
472 
473 	  return build_string (strlen (newname), newname);
474 	}
475   }
476 
477 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
478   if (pragma_extern_prefix && !asmname)
479     {
480       char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix),
481 			IDENTIFIER_POINTER (oldname), NULL);
482       asmname = build_string (strlen (x), x);
483       free (x);
484       return asmname;
485     }
486 #endif
487 
488   return asmname;
489 }
490 
491 void
init_pragma()492 init_pragma ()
493 {
494 #ifdef HANDLE_PRAGMA_PACK
495   cpp_register_pragma (parse_in, 0, "pack", handle_pragma_pack);
496 #endif
497 #ifdef HANDLE_PRAGMA_WEAK
498   cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak);
499 #endif
500 #ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
501   cpp_register_pragma (parse_in, 0, "redefine_extname",
502 		       handle_pragma_redefine_extname);
503 #endif
504 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
505   cpp_register_pragma (parse_in, 0, "extern_prefix",
506 		       handle_pragma_extern_prefix);
507 #endif
508 
509 #ifdef REGISTER_TARGET_PRAGMAS
510   REGISTER_TARGET_PRAGMAS (parse_in);
511 #endif
512 }
513 
514 #include "gt-c-pragma.h"
515