c-pragma.c revision 119256
185597Speter/* Handle #pragma, system V.4 style.  Supports #pragma weak and #pragma pack.
285597Speter   Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002
385597Speter   Free Software Foundation, Inc.
485597Speter
585597SpeterThis file is part of GCC.
685597Speter
785597SpeterGCC is free software; you can redistribute it and/or modify it under
885597Speterthe terms of the GNU General Public License as published by the Free
985597SpeterSoftware Foundation; either version 2, or (at your option) any later
1085597Speterversion.
1185597Speter
1285597SpeterGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1385597SpeterWARRANTY; without even the implied warranty of MERCHANTABILITY or
1485597SpeterFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1585597Speterfor more details.
1685597Speter
1785597SpeterYou should have received a copy of the GNU General Public License
1885597Speteralong with GCC; see the file COPYING.  If not, write to the Free
1985597SpeterSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2085597Speter02111-1307, USA.  */
2185597Speter
2285597Speter#include "config.h"
2385597Speter#include "system.h"
2485597Speter#include "rtl.h"
2585597Speter#include "tree.h"
2685597Speter#include "function.h"
2785597Speter#include "cpplib.h"
2885597Speter#include "c-pragma.h"
29216338Sdim#include "flags.h"
30216338Sdim#include "toplev.h"
31216338Sdim#include "ggc.h"
3285597Speter#include "c-common.h"
3385597Speter#include "output.h"
3485597Speter#include "tm_p.h"
3585597Speter
3685597Speter#define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
3785597Speter#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
3885679Speter
3985679Spetertypedef struct align_stack GTY(())
4085679Speter{
4185597Speter  int                  alignment;
4285952Speter  unsigned int         num_pushes;
4385952Speter  tree                 id;
4485952Speter  struct align_stack * prev;
4585679Speter} align_stack;
4685679Speter
4785952Speterstatic GTY(()) struct align_stack * alignment_stack;
4885679Speter
4985597Speter#ifdef HANDLE_PRAGMA_PACK
5085679Speterstatic void handle_pragma_pack PARAMS ((cpp_reader *));
5185679Speter
5285679Speter#ifdef HANDLE_PRAGMA_PACK_PUSH_POP
5385597Speter/* If we have a "global" #pragma pack(<n>) in effect when the first
5485952Speter   #pragma pack(push,<n>) is encountered, this stores the value of
5585952Speter   maximum_field_alignment in effect.  When the final pop_alignment()
5685952Speter   happens, we restore the value to this, not to a value of 0 for
5785679Speter   maximum_field_alignment.  Value is in bits.  */
5885679Speterstatic int default_alignment;
5985952Speter#define SET_GLOBAL_ALIGNMENT(ALIGN) \
6085679Speter  (default_alignment = maximum_field_alignment = (ALIGN))
61
62static void push_alignment PARAMS ((int, tree));
63static void pop_alignment  PARAMS ((tree));
64
65/* Push an alignment value onto the stack.  */
66static void
67push_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.  */
99static void
100pop_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) */
157static void
158handle_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
259static GTY(()) tree pending_weaks;
260
261#ifdef HANDLE_PRAGMA_WEAK
262static void apply_pragma_weak PARAMS ((tree, tree));
263static void handle_pragma_weak PARAMS ((cpp_reader *));
264
265static void
266apply_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
285void
286maybe_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] */
318static void
319handle_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
350void
351maybe_apply_pragma_weak (decl)
352     tree decl ATTRIBUTE_UNUSED;
353{
354}
355#endif /* HANDLE_PRAGMA_WEAK */
356
357static GTY(()) tree pending_redefine_extname;
358
359#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
360static void handle_pragma_redefine_extname PARAMS ((cpp_reader *));
361
362/* #pragma redefined_extname oldname newname */
363static void
364handle_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
397void
398add_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
405static GTY(()) tree pragma_extern_prefix;
406
407#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
408static void handle_pragma_extern_prefix PARAMS ((cpp_reader *));
409
410/* #pragma extern_prefix "prefix" */
411static void
412handle_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
435tree
436maybe_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
491void
492init_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