xref: /dflybsd-src/contrib/gcc-4.7/gcc/c-family/c-pragma.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Handle #pragma, system V.4 style.  Supports #pragma weak and #pragma pack.
2*e4b17023SJohn Marino    Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
3*e4b17023SJohn Marino    2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4*e4b17023SJohn Marino 
5*e4b17023SJohn Marino This file is part of GCC.
6*e4b17023SJohn Marino 
7*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
8*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
9*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
10*e4b17023SJohn Marino version.
11*e4b17023SJohn Marino 
12*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*e4b17023SJohn Marino for more details.
16*e4b17023SJohn Marino 
17*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
18*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
19*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
20*e4b17023SJohn Marino 
21*e4b17023SJohn Marino #include "config.h"
22*e4b17023SJohn Marino #include "system.h"
23*e4b17023SJohn Marino #include "coretypes.h"
24*e4b17023SJohn Marino #include "tm.h"
25*e4b17023SJohn Marino #include "tree.h"
26*e4b17023SJohn Marino #include "function.h"		/* For cfun.  FIXME: Does the parser know
27*e4b17023SJohn Marino 				   when it is inside a function, so that
28*e4b17023SJohn Marino 				   we don't have to look at cfun?  */
29*e4b17023SJohn Marino #include "cpplib.h"
30*e4b17023SJohn Marino #include "c-pragma.h"
31*e4b17023SJohn Marino #include "flags.h"
32*e4b17023SJohn Marino #include "c-common.h"
33*e4b17023SJohn Marino #include "output.h"
34*e4b17023SJohn Marino #include "tm_p.h"		/* For REGISTER_TARGET_PRAGMAS (why is
35*e4b17023SJohn Marino 				   this not a target hook?).  */
36*e4b17023SJohn Marino #include "vec.h"
37*e4b17023SJohn Marino #include "vecprim.h"
38*e4b17023SJohn Marino #include "target.h"
39*e4b17023SJohn Marino #include "diagnostic.h"
40*e4b17023SJohn Marino #include "opts.h"
41*e4b17023SJohn Marino #include "plugin.h"
42*e4b17023SJohn Marino 
43*e4b17023SJohn Marino #define GCC_BAD(gmsgid) \
44*e4b17023SJohn Marino   do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
45*e4b17023SJohn Marino #define GCC_BAD2(gmsgid, arg) \
46*e4b17023SJohn Marino   do { warning (OPT_Wpragmas, gmsgid, arg); return; } while (0)
47*e4b17023SJohn Marino 
48*e4b17023SJohn Marino typedef struct GTY(()) align_stack {
49*e4b17023SJohn Marino   int		       alignment;
50*e4b17023SJohn Marino   tree		       id;
51*e4b17023SJohn Marino   struct align_stack * prev;
52*e4b17023SJohn Marino } align_stack;
53*e4b17023SJohn Marino 
54*e4b17023SJohn Marino static GTY(()) struct align_stack * alignment_stack;
55*e4b17023SJohn Marino 
56*e4b17023SJohn Marino static void handle_pragma_pack (cpp_reader *);
57*e4b17023SJohn Marino 
58*e4b17023SJohn Marino /* If we have a "global" #pragma pack(<n>) in effect when the first
59*e4b17023SJohn Marino    #pragma pack(push,<n>) is encountered, this stores the value of
60*e4b17023SJohn Marino    maximum_field_alignment in effect.  When the final pop_alignment()
61*e4b17023SJohn Marino    happens, we restore the value to this, not to a value of 0 for
62*e4b17023SJohn Marino    maximum_field_alignment.  Value is in bits.  */
63*e4b17023SJohn Marino static int default_alignment;
64*e4b17023SJohn Marino #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
65*e4b17023SJohn Marino 	? &default_alignment \
66*e4b17023SJohn Marino 	: &alignment_stack->alignment) = (ALIGN))
67*e4b17023SJohn Marino 
68*e4b17023SJohn Marino static void push_alignment (int, tree);
69*e4b17023SJohn Marino static void pop_alignment (tree);
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino /* Push an alignment value onto the stack.  */
72*e4b17023SJohn Marino static void
push_alignment(int alignment,tree id)73*e4b17023SJohn Marino push_alignment (int alignment, tree id)
74*e4b17023SJohn Marino {
75*e4b17023SJohn Marino   align_stack * entry;
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino   entry = ggc_alloc_align_stack ();
78*e4b17023SJohn Marino 
79*e4b17023SJohn Marino   entry->alignment  = alignment;
80*e4b17023SJohn Marino   entry->id	    = id;
81*e4b17023SJohn Marino   entry->prev	    = alignment_stack;
82*e4b17023SJohn Marino 
83*e4b17023SJohn Marino   /* The current value of maximum_field_alignment is not necessarily
84*e4b17023SJohn Marino      0 since there may be a #pragma pack(<n>) in effect; remember it
85*e4b17023SJohn Marino      so that we can restore it after the final #pragma pop().  */
86*e4b17023SJohn Marino   if (alignment_stack == NULL)
87*e4b17023SJohn Marino     default_alignment = maximum_field_alignment;
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino   alignment_stack = entry;
90*e4b17023SJohn Marino 
91*e4b17023SJohn Marino   maximum_field_alignment = alignment;
92*e4b17023SJohn Marino }
93*e4b17023SJohn Marino 
94*e4b17023SJohn Marino /* Undo a push of an alignment onto the stack.  */
95*e4b17023SJohn Marino static void
pop_alignment(tree id)96*e4b17023SJohn Marino pop_alignment (tree id)
97*e4b17023SJohn Marino {
98*e4b17023SJohn Marino   align_stack * entry;
99*e4b17023SJohn Marino 
100*e4b17023SJohn Marino   if (alignment_stack == NULL)
101*e4b17023SJohn Marino     GCC_BAD ("#pragma pack (pop) encountered without matching #pragma pack (push)");
102*e4b17023SJohn Marino 
103*e4b17023SJohn Marino   /* If we got an identifier, strip away everything above the target
104*e4b17023SJohn Marino      entry so that the next step will restore the state just below it.  */
105*e4b17023SJohn Marino   if (id)
106*e4b17023SJohn Marino     {
107*e4b17023SJohn Marino       for (entry = alignment_stack; entry; entry = entry->prev)
108*e4b17023SJohn Marino 	if (entry->id == id)
109*e4b17023SJohn Marino 	  {
110*e4b17023SJohn Marino 	    alignment_stack = entry;
111*e4b17023SJohn Marino 	    break;
112*e4b17023SJohn Marino 	  }
113*e4b17023SJohn Marino       if (entry == NULL)
114*e4b17023SJohn Marino 	warning (OPT_Wpragmas, "\
115*e4b17023SJohn Marino #pragma pack(pop, %E) encountered without matching #pragma pack(push, %E)"
116*e4b17023SJohn Marino 		 , id, id);
117*e4b17023SJohn Marino     }
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino   entry = alignment_stack->prev;
120*e4b17023SJohn Marino 
121*e4b17023SJohn Marino   maximum_field_alignment = entry ? entry->alignment : default_alignment;
122*e4b17023SJohn Marino 
123*e4b17023SJohn Marino   alignment_stack = entry;
124*e4b17023SJohn Marino }
125*e4b17023SJohn Marino 
126*e4b17023SJohn Marino /* #pragma pack ()
127*e4b17023SJohn Marino    #pragma pack (N)
128*e4b17023SJohn Marino 
129*e4b17023SJohn Marino    #pragma pack (push)
130*e4b17023SJohn Marino    #pragma pack (push, N)
131*e4b17023SJohn Marino    #pragma pack (push, ID)
132*e4b17023SJohn Marino    #pragma pack (push, ID, N)
133*e4b17023SJohn Marino    #pragma pack (pop)
134*e4b17023SJohn Marino    #pragma pack (pop, ID) */
135*e4b17023SJohn Marino static void
handle_pragma_pack(cpp_reader * ARG_UNUSED (dummy))136*e4b17023SJohn Marino handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
137*e4b17023SJohn Marino {
138*e4b17023SJohn Marino   tree x, id = 0;
139*e4b17023SJohn Marino   int align = -1;
140*e4b17023SJohn Marino   enum cpp_ttype token;
141*e4b17023SJohn Marino   enum { set, push, pop } action;
142*e4b17023SJohn Marino 
143*e4b17023SJohn Marino   if (pragma_lex (&x) != CPP_OPEN_PAREN)
144*e4b17023SJohn Marino     GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
145*e4b17023SJohn Marino 
146*e4b17023SJohn Marino   token = pragma_lex (&x);
147*e4b17023SJohn Marino   if (token == CPP_CLOSE_PAREN)
148*e4b17023SJohn Marino     {
149*e4b17023SJohn Marino       action = set;
150*e4b17023SJohn Marino       align = initial_max_fld_align;
151*e4b17023SJohn Marino     }
152*e4b17023SJohn Marino   else if (token == CPP_NUMBER)
153*e4b17023SJohn Marino     {
154*e4b17023SJohn Marino       if (TREE_CODE (x) != INTEGER_CST)
155*e4b17023SJohn Marino 	GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
156*e4b17023SJohn Marino       align = TREE_INT_CST_LOW (x);
157*e4b17023SJohn Marino       action = set;
158*e4b17023SJohn Marino       if (pragma_lex (&x) != CPP_CLOSE_PAREN)
159*e4b17023SJohn Marino 	GCC_BAD ("malformed %<#pragma pack%> - ignored");
160*e4b17023SJohn Marino     }
161*e4b17023SJohn Marino   else if (token == CPP_NAME)
162*e4b17023SJohn Marino     {
163*e4b17023SJohn Marino #define GCC_BAD_ACTION do { if (action != pop) \
164*e4b17023SJohn Marino 	  GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
165*e4b17023SJohn Marino 	else \
166*e4b17023SJohn Marino 	  GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
167*e4b17023SJohn Marino 	} while (0)
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino       const char *op = IDENTIFIER_POINTER (x);
170*e4b17023SJohn Marino       if (!strcmp (op, "push"))
171*e4b17023SJohn Marino 	action = push;
172*e4b17023SJohn Marino       else if (!strcmp (op, "pop"))
173*e4b17023SJohn Marino 	action = pop;
174*e4b17023SJohn Marino       else
175*e4b17023SJohn Marino 	GCC_BAD2 ("unknown action %qE for %<#pragma pack%> - ignored", x);
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino       while ((token = pragma_lex (&x)) == CPP_COMMA)
178*e4b17023SJohn Marino 	{
179*e4b17023SJohn Marino 	  token = pragma_lex (&x);
180*e4b17023SJohn Marino 	  if (token == CPP_NAME && id == 0)
181*e4b17023SJohn Marino 	    {
182*e4b17023SJohn Marino 	      id = x;
183*e4b17023SJohn Marino 	    }
184*e4b17023SJohn Marino 	  else if (token == CPP_NUMBER && action == push && align == -1)
185*e4b17023SJohn Marino 	    {
186*e4b17023SJohn Marino 	      if (TREE_CODE (x) != INTEGER_CST)
187*e4b17023SJohn Marino 		GCC_BAD ("invalid constant in %<#pragma pack%> - ignored");
188*e4b17023SJohn Marino 	      align = TREE_INT_CST_LOW (x);
189*e4b17023SJohn Marino 	      if (align == -1)
190*e4b17023SJohn Marino 		action = set;
191*e4b17023SJohn Marino 	    }
192*e4b17023SJohn Marino 	  else
193*e4b17023SJohn Marino 	    GCC_BAD_ACTION;
194*e4b17023SJohn Marino 	}
195*e4b17023SJohn Marino 
196*e4b17023SJohn Marino       if (token != CPP_CLOSE_PAREN)
197*e4b17023SJohn Marino 	GCC_BAD_ACTION;
198*e4b17023SJohn Marino #undef GCC_BAD_ACTION
199*e4b17023SJohn Marino     }
200*e4b17023SJohn Marino   else
201*e4b17023SJohn Marino     GCC_BAD ("malformed %<#pragma pack%> - ignored");
202*e4b17023SJohn Marino 
203*e4b17023SJohn Marino   if (pragma_lex (&x) != CPP_EOF)
204*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma pack%>");
205*e4b17023SJohn Marino 
206*e4b17023SJohn Marino   if (flag_pack_struct)
207*e4b17023SJohn Marino     GCC_BAD ("#pragma pack has no effect with -fpack-struct - ignored");
208*e4b17023SJohn Marino 
209*e4b17023SJohn Marino   if (action != pop)
210*e4b17023SJohn Marino     switch (align)
211*e4b17023SJohn Marino       {
212*e4b17023SJohn Marino       case 0:
213*e4b17023SJohn Marino       case 1:
214*e4b17023SJohn Marino       case 2:
215*e4b17023SJohn Marino       case 4:
216*e4b17023SJohn Marino       case 8:
217*e4b17023SJohn Marino       case 16:
218*e4b17023SJohn Marino 	align *= BITS_PER_UNIT;
219*e4b17023SJohn Marino 	break;
220*e4b17023SJohn Marino       case -1:
221*e4b17023SJohn Marino 	if (action == push)
222*e4b17023SJohn Marino 	  {
223*e4b17023SJohn Marino 	    align = maximum_field_alignment;
224*e4b17023SJohn Marino 	    break;
225*e4b17023SJohn Marino 	  }
226*e4b17023SJohn Marino       default:
227*e4b17023SJohn Marino 	GCC_BAD2 ("alignment must be a small power of two, not %d", align);
228*e4b17023SJohn Marino       }
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino   switch (action)
231*e4b17023SJohn Marino     {
232*e4b17023SJohn Marino     case set:   SET_GLOBAL_ALIGNMENT (align);  break;
233*e4b17023SJohn Marino     case push:  push_alignment (align, id);    break;
234*e4b17023SJohn Marino     case pop:   pop_alignment (id);	       break;
235*e4b17023SJohn Marino     }
236*e4b17023SJohn Marino }
237*e4b17023SJohn Marino 
238*e4b17023SJohn Marino typedef struct GTY(()) pending_weak_d
239*e4b17023SJohn Marino {
240*e4b17023SJohn Marino   tree name;
241*e4b17023SJohn Marino   tree value;
242*e4b17023SJohn Marino } pending_weak;
243*e4b17023SJohn Marino 
244*e4b17023SJohn Marino DEF_VEC_O(pending_weak);
245*e4b17023SJohn Marino DEF_VEC_ALLOC_O(pending_weak,gc);
246*e4b17023SJohn Marino 
247*e4b17023SJohn Marino static GTY(()) VEC(pending_weak,gc) *pending_weaks;
248*e4b17023SJohn Marino 
249*e4b17023SJohn Marino static void apply_pragma_weak (tree, tree);
250*e4b17023SJohn Marino static void handle_pragma_weak (cpp_reader *);
251*e4b17023SJohn Marino 
252*e4b17023SJohn Marino static void
apply_pragma_weak(tree decl,tree value)253*e4b17023SJohn Marino apply_pragma_weak (tree decl, tree value)
254*e4b17023SJohn Marino {
255*e4b17023SJohn Marino   if (value)
256*e4b17023SJohn Marino     {
257*e4b17023SJohn Marino       value = build_string (IDENTIFIER_LENGTH (value),
258*e4b17023SJohn Marino 			    IDENTIFIER_POINTER (value));
259*e4b17023SJohn Marino       decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
260*e4b17023SJohn Marino 					       build_tree_list (NULL, value)),
261*e4b17023SJohn Marino 		       0);
262*e4b17023SJohn Marino     }
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino   if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
265*e4b17023SJohn Marino       && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma.  */
266*e4b17023SJohn Marino       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
267*e4b17023SJohn Marino     warning (OPT_Wpragmas, "applying #pragma weak %q+D after first use "
268*e4b17023SJohn Marino 	     "results in unspecified behavior", decl);
269*e4b17023SJohn Marino 
270*e4b17023SJohn Marino   declare_weak (decl);
271*e4b17023SJohn Marino }
272*e4b17023SJohn Marino 
273*e4b17023SJohn Marino void
maybe_apply_pragma_weak(tree decl)274*e4b17023SJohn Marino maybe_apply_pragma_weak (tree decl)
275*e4b17023SJohn Marino {
276*e4b17023SJohn Marino   tree id;
277*e4b17023SJohn Marino   int i;
278*e4b17023SJohn Marino   pending_weak *pe;
279*e4b17023SJohn Marino 
280*e4b17023SJohn Marino   /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed.  */
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino   /* No weak symbols pending, take the short-cut.  */
283*e4b17023SJohn Marino   if (!pending_weaks)
284*e4b17023SJohn Marino     return;
285*e4b17023SJohn Marino   /* If it's not visible outside this file, it doesn't matter whether
286*e4b17023SJohn Marino      it's weak.  */
287*e4b17023SJohn Marino   if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
288*e4b17023SJohn Marino     return;
289*e4b17023SJohn Marino   /* If it's not a function or a variable, it can't be weak.
290*e4b17023SJohn Marino      FIXME: what kinds of things are visible outside this file but
291*e4b17023SJohn Marino      aren't functions or variables?   Should this be an assert instead?  */
292*e4b17023SJohn Marino   if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
293*e4b17023SJohn Marino     return;
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino   id = DECL_ASSEMBLER_NAME (decl);
296*e4b17023SJohn Marino 
297*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (pending_weak, pending_weaks, i, pe)
298*e4b17023SJohn Marino     if (id == pe->name)
299*e4b17023SJohn Marino       {
300*e4b17023SJohn Marino 	apply_pragma_weak (decl, pe->value);
301*e4b17023SJohn Marino 	VEC_unordered_remove (pending_weak, pending_weaks, i);
302*e4b17023SJohn Marino 	break;
303*e4b17023SJohn Marino       }
304*e4b17023SJohn Marino }
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino /* Process all "#pragma weak A = B" directives where we have not seen
307*e4b17023SJohn Marino    a decl for A.  */
308*e4b17023SJohn Marino void
maybe_apply_pending_pragma_weaks(void)309*e4b17023SJohn Marino maybe_apply_pending_pragma_weaks (void)
310*e4b17023SJohn Marino {
311*e4b17023SJohn Marino   tree alias_id, id, decl;
312*e4b17023SJohn Marino   int i;
313*e4b17023SJohn Marino   pending_weak *pe;
314*e4b17023SJohn Marino 
315*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (pending_weak, pending_weaks, i, pe)
316*e4b17023SJohn Marino     {
317*e4b17023SJohn Marino       alias_id = pe->name;
318*e4b17023SJohn Marino       id = pe->value;
319*e4b17023SJohn Marino 
320*e4b17023SJohn Marino       if (id == NULL)
321*e4b17023SJohn Marino 	continue;
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino       decl = build_decl (UNKNOWN_LOCATION,
324*e4b17023SJohn Marino 			 FUNCTION_DECL, alias_id, default_function_type);
325*e4b17023SJohn Marino 
326*e4b17023SJohn Marino       DECL_ARTIFICIAL (decl) = 1;
327*e4b17023SJohn Marino       TREE_PUBLIC (decl) = 1;
328*e4b17023SJohn Marino       DECL_EXTERNAL (decl) = 1;
329*e4b17023SJohn Marino       DECL_WEAK (decl) = 1;
330*e4b17023SJohn Marino 
331*e4b17023SJohn Marino       assemble_alias (decl, id);
332*e4b17023SJohn Marino     }
333*e4b17023SJohn Marino }
334*e4b17023SJohn Marino 
335*e4b17023SJohn Marino /* #pragma weak name [= value] */
336*e4b17023SJohn Marino static void
handle_pragma_weak(cpp_reader * ARG_UNUSED (dummy))337*e4b17023SJohn Marino handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
338*e4b17023SJohn Marino {
339*e4b17023SJohn Marino   tree name, value, x, decl;
340*e4b17023SJohn Marino   enum cpp_ttype t;
341*e4b17023SJohn Marino 
342*e4b17023SJohn Marino   value = 0;
343*e4b17023SJohn Marino 
344*e4b17023SJohn Marino   if (pragma_lex (&name) != CPP_NAME)
345*e4b17023SJohn Marino     GCC_BAD ("malformed #pragma weak, ignored");
346*e4b17023SJohn Marino   t = pragma_lex (&x);
347*e4b17023SJohn Marino   if (t == CPP_EQ)
348*e4b17023SJohn Marino     {
349*e4b17023SJohn Marino       if (pragma_lex (&value) != CPP_NAME)
350*e4b17023SJohn Marino 	GCC_BAD ("malformed #pragma weak, ignored");
351*e4b17023SJohn Marino       t = pragma_lex (&x);
352*e4b17023SJohn Marino     }
353*e4b17023SJohn Marino   if (t != CPP_EOF)
354*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma weak%>");
355*e4b17023SJohn Marino 
356*e4b17023SJohn Marino   decl = identifier_global_value (name);
357*e4b17023SJohn Marino   if (decl && DECL_P (decl))
358*e4b17023SJohn Marino     {
359*e4b17023SJohn Marino       apply_pragma_weak (decl, value);
360*e4b17023SJohn Marino       if (value)
361*e4b17023SJohn Marino 	assemble_alias (decl, value);
362*e4b17023SJohn Marino     }
363*e4b17023SJohn Marino   else
364*e4b17023SJohn Marino     {
365*e4b17023SJohn Marino       pending_weak *pe;
366*e4b17023SJohn Marino       pe = VEC_safe_push (pending_weak, gc, pending_weaks, NULL);
367*e4b17023SJohn Marino       pe->name = name;
368*e4b17023SJohn Marino       pe->value = value;
369*e4b17023SJohn Marino     }
370*e4b17023SJohn Marino }
371*e4b17023SJohn Marino 
372*e4b17023SJohn Marino /* GCC supports two #pragma directives for renaming the external
373*e4b17023SJohn Marino    symbol associated with a declaration (DECL_ASSEMBLER_NAME), for
374*e4b17023SJohn Marino    compatibility with the Solaris and Tru64 system headers.  GCC also
375*e4b17023SJohn Marino    has its own notation for this, __asm__("name") annotations.
376*e4b17023SJohn Marino 
377*e4b17023SJohn Marino    Corner cases of these features and their interaction:
378*e4b17023SJohn Marino 
379*e4b17023SJohn Marino    1) Both pragmas silently apply only to declarations with external
380*e4b17023SJohn Marino       linkage (that is, TREE_PUBLIC || DECL_EXTERNAL).  Asm labels
381*e4b17023SJohn Marino       do not have this restriction.
382*e4b17023SJohn Marino 
383*e4b17023SJohn Marino    2) In C++, both #pragmas silently apply only to extern "C" declarations.
384*e4b17023SJohn Marino       Asm labels do not have this restriction.
385*e4b17023SJohn Marino 
386*e4b17023SJohn Marino    3) If any of the three ways of changing DECL_ASSEMBLER_NAME is
387*e4b17023SJohn Marino       applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the
388*e4b17023SJohn Marino       new name is different, a warning issues and the name does not change.
389*e4b17023SJohn Marino 
390*e4b17023SJohn Marino    4) The "source name" for #pragma redefine_extname is the DECL_NAME,
391*e4b17023SJohn Marino       *not* the DECL_ASSEMBLER_NAME.
392*e4b17023SJohn Marino 
393*e4b17023SJohn Marino    5) If #pragma extern_prefix is in effect and a declaration occurs
394*e4b17023SJohn Marino       with an __asm__ name, the #pragma extern_prefix is silently
395*e4b17023SJohn Marino       ignored for that declaration.
396*e4b17023SJohn Marino 
397*e4b17023SJohn Marino    6) If #pragma extern_prefix and #pragma redefine_extname apply to
398*e4b17023SJohn Marino       the same declaration, whichever triggered first wins, and a warning
399*e4b17023SJohn Marino       is issued.  (We would like to have #pragma redefine_extname always
400*e4b17023SJohn Marino       win, but it can appear either before or after the declaration, and
401*e4b17023SJohn Marino       if it appears afterward, we have no way of knowing whether a modified
402*e4b17023SJohn Marino       DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.)  */
403*e4b17023SJohn Marino 
404*e4b17023SJohn Marino typedef struct GTY(()) pending_redefinition_d {
405*e4b17023SJohn Marino   tree oldname;
406*e4b17023SJohn Marino   tree newname;
407*e4b17023SJohn Marino } pending_redefinition;
408*e4b17023SJohn Marino 
409*e4b17023SJohn Marino DEF_VEC_O(pending_redefinition);
410*e4b17023SJohn Marino DEF_VEC_ALLOC_O(pending_redefinition,gc);
411*e4b17023SJohn Marino 
412*e4b17023SJohn Marino static GTY(()) VEC(pending_redefinition,gc) *pending_redefine_extname;
413*e4b17023SJohn Marino 
414*e4b17023SJohn Marino static void handle_pragma_redefine_extname (cpp_reader *);
415*e4b17023SJohn Marino 
416*e4b17023SJohn Marino /* #pragma redefine_extname oldname newname */
417*e4b17023SJohn Marino static void
handle_pragma_redefine_extname(cpp_reader * ARG_UNUSED (dummy))418*e4b17023SJohn Marino handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
419*e4b17023SJohn Marino {
420*e4b17023SJohn Marino   tree oldname, newname, decls, x;
421*e4b17023SJohn Marino   enum cpp_ttype t;
422*e4b17023SJohn Marino   bool found;
423*e4b17023SJohn Marino 
424*e4b17023SJohn Marino   if (pragma_lex (&oldname) != CPP_NAME)
425*e4b17023SJohn Marino     GCC_BAD ("malformed #pragma redefine_extname, ignored");
426*e4b17023SJohn Marino   if (pragma_lex (&newname) != CPP_NAME)
427*e4b17023SJohn Marino     GCC_BAD ("malformed #pragma redefine_extname, ignored");
428*e4b17023SJohn Marino   t = pragma_lex (&x);
429*e4b17023SJohn Marino   if (t != CPP_EOF)
430*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma redefine_extname%>");
431*e4b17023SJohn Marino 
432*e4b17023SJohn Marino   found = false;
433*e4b17023SJohn Marino   for (decls = c_linkage_bindings (oldname);
434*e4b17023SJohn Marino        decls; )
435*e4b17023SJohn Marino     {
436*e4b17023SJohn Marino       tree decl;
437*e4b17023SJohn Marino       if (TREE_CODE (decls) == TREE_LIST)
438*e4b17023SJohn Marino 	{
439*e4b17023SJohn Marino 	  decl = TREE_VALUE (decls);
440*e4b17023SJohn Marino 	  decls = TREE_CHAIN (decls);
441*e4b17023SJohn Marino 	}
442*e4b17023SJohn Marino       else
443*e4b17023SJohn Marino 	{
444*e4b17023SJohn Marino 	  decl = decls;
445*e4b17023SJohn Marino 	  decls = NULL_TREE;
446*e4b17023SJohn Marino 	}
447*e4b17023SJohn Marino 
448*e4b17023SJohn Marino       if ((TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
449*e4b17023SJohn Marino 	  && (TREE_CODE (decl) == FUNCTION_DECL
450*e4b17023SJohn Marino 	      || TREE_CODE (decl) == VAR_DECL))
451*e4b17023SJohn Marino 	{
452*e4b17023SJohn Marino 	  found = true;
453*e4b17023SJohn Marino 	  if (DECL_ASSEMBLER_NAME_SET_P (decl))
454*e4b17023SJohn Marino 	    {
455*e4b17023SJohn Marino 	      const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
456*e4b17023SJohn Marino 	      name = targetm.strip_name_encoding (name);
457*e4b17023SJohn Marino 
458*e4b17023SJohn Marino 	      if (strcmp (name, IDENTIFIER_POINTER (newname)))
459*e4b17023SJohn Marino 		warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
460*e4b17023SJohn Marino 			 "conflict with previous rename");
461*e4b17023SJohn Marino 	    }
462*e4b17023SJohn Marino 	  else
463*e4b17023SJohn Marino 	    change_decl_assembler_name (decl, newname);
464*e4b17023SJohn Marino 	}
465*e4b17023SJohn Marino     }
466*e4b17023SJohn Marino 
467*e4b17023SJohn Marino   if (!found)
468*e4b17023SJohn Marino     /* We have to add this to the rename list even if there's already
469*e4b17023SJohn Marino        a global value that doesn't meet the above criteria, because in
470*e4b17023SJohn Marino        C++ "struct foo {...};" puts "foo" in the current namespace but
471*e4b17023SJohn Marino        does *not* conflict with a subsequent declaration of a function
472*e4b17023SJohn Marino        or variable foo.  See g++.dg/other/pragma-re-2.C.  */
473*e4b17023SJohn Marino     add_to_renaming_pragma_list (oldname, newname);
474*e4b17023SJohn Marino }
475*e4b17023SJohn Marino 
476*e4b17023SJohn Marino /* This is called from here and from ia64.c.  */
477*e4b17023SJohn Marino void
add_to_renaming_pragma_list(tree oldname,tree newname)478*e4b17023SJohn Marino add_to_renaming_pragma_list (tree oldname, tree newname)
479*e4b17023SJohn Marino {
480*e4b17023SJohn Marino   unsigned ix;
481*e4b17023SJohn Marino   pending_redefinition *p;
482*e4b17023SJohn Marino 
483*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
484*e4b17023SJohn Marino     if (oldname == p->oldname)
485*e4b17023SJohn Marino       {
486*e4b17023SJohn Marino 	if (p->newname != newname)
487*e4b17023SJohn Marino 	  warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
488*e4b17023SJohn Marino 		   "conflict with previous #pragma redefine_extname");
489*e4b17023SJohn Marino 	return;
490*e4b17023SJohn Marino       }
491*e4b17023SJohn Marino 
492*e4b17023SJohn Marino   p = VEC_safe_push (pending_redefinition, gc, pending_redefine_extname, NULL);
493*e4b17023SJohn Marino   p->oldname = oldname;
494*e4b17023SJohn Marino   p->newname = newname;
495*e4b17023SJohn Marino }
496*e4b17023SJohn Marino 
497*e4b17023SJohn Marino /* The current prefix set by #pragma extern_prefix.  */
498*e4b17023SJohn Marino GTY(()) tree pragma_extern_prefix;
499*e4b17023SJohn Marino 
500*e4b17023SJohn Marino /* #pragma extern_prefix "prefix" */
501*e4b17023SJohn Marino static void
handle_pragma_extern_prefix(cpp_reader * ARG_UNUSED (dummy))502*e4b17023SJohn Marino handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
503*e4b17023SJohn Marino {
504*e4b17023SJohn Marino   tree prefix, x;
505*e4b17023SJohn Marino   enum cpp_ttype t;
506*e4b17023SJohn Marino 
507*e4b17023SJohn Marino   if (pragma_lex (&prefix) != CPP_STRING)
508*e4b17023SJohn Marino     GCC_BAD ("malformed #pragma extern_prefix, ignored");
509*e4b17023SJohn Marino   t = pragma_lex (&x);
510*e4b17023SJohn Marino   if (t != CPP_EOF)
511*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma extern_prefix%>");
512*e4b17023SJohn Marino 
513*e4b17023SJohn Marino   if (targetm.handle_pragma_extern_prefix)
514*e4b17023SJohn Marino     /* Note that the length includes the null terminator.  */
515*e4b17023SJohn Marino     pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
516*e4b17023SJohn Marino   else if (warn_unknown_pragmas > in_system_header)
517*e4b17023SJohn Marino     warning (OPT_Wunknown_pragmas,
518*e4b17023SJohn Marino 	     "#pragma extern_prefix not supported on this target");
519*e4b17023SJohn Marino }
520*e4b17023SJohn Marino 
521*e4b17023SJohn Marino /* Hook from the front ends to apply the results of one of the preceding
522*e4b17023SJohn Marino    pragmas that rename variables.  */
523*e4b17023SJohn Marino 
524*e4b17023SJohn Marino tree
maybe_apply_renaming_pragma(tree decl,tree asmname)525*e4b17023SJohn Marino maybe_apply_renaming_pragma (tree decl, tree asmname)
526*e4b17023SJohn Marino {
527*e4b17023SJohn Marino   unsigned ix;
528*e4b17023SJohn Marino   pending_redefinition *p;
529*e4b17023SJohn Marino 
530*e4b17023SJohn Marino   /* The renaming pragmas are only applied to declarations with
531*e4b17023SJohn Marino      external linkage.  */
532*e4b17023SJohn Marino   if ((TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
533*e4b17023SJohn Marino       || (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
534*e4b17023SJohn Marino       || !has_c_linkage (decl))
535*e4b17023SJohn Marino     return asmname;
536*e4b17023SJohn Marino 
537*e4b17023SJohn Marino   /* If the DECL_ASSEMBLER_NAME is already set, it does not change,
538*e4b17023SJohn Marino      but we may warn about a rename that conflicts.  */
539*e4b17023SJohn Marino   if (DECL_ASSEMBLER_NAME_SET_P (decl))
540*e4b17023SJohn Marino     {
541*e4b17023SJohn Marino       const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
542*e4b17023SJohn Marino       oldname = targetm.strip_name_encoding (oldname);
543*e4b17023SJohn Marino 
544*e4b17023SJohn Marino       if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
545*e4b17023SJohn Marino 	  warning (OPT_Wpragmas, "asm declaration ignored due to "
546*e4b17023SJohn Marino 		   "conflict with previous rename");
547*e4b17023SJohn Marino 
548*e4b17023SJohn Marino       /* Take any pending redefine_extname off the list.  */
549*e4b17023SJohn Marino       FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
550*e4b17023SJohn Marino 	if (DECL_NAME (decl) == p->oldname)
551*e4b17023SJohn Marino 	  {
552*e4b17023SJohn Marino 	    /* Only warn if there is a conflict.  */
553*e4b17023SJohn Marino 	    if (strcmp (IDENTIFIER_POINTER (p->newname), oldname))
554*e4b17023SJohn Marino 	      warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
555*e4b17023SJohn Marino 		       "conflict with previous rename");
556*e4b17023SJohn Marino 
557*e4b17023SJohn Marino 	    VEC_unordered_remove (pending_redefinition,
558*e4b17023SJohn Marino 				  pending_redefine_extname, ix);
559*e4b17023SJohn Marino 	    break;
560*e4b17023SJohn Marino 	  }
561*e4b17023SJohn Marino       return 0;
562*e4b17023SJohn Marino     }
563*e4b17023SJohn Marino 
564*e4b17023SJohn Marino   /* Find out if we have a pending #pragma redefine_extname.  */
565*e4b17023SJohn Marino   FOR_EACH_VEC_ELT (pending_redefinition, pending_redefine_extname, ix, p)
566*e4b17023SJohn Marino     if (DECL_NAME (decl) == p->oldname)
567*e4b17023SJohn Marino       {
568*e4b17023SJohn Marino 	tree newname = p->newname;
569*e4b17023SJohn Marino 	VEC_unordered_remove (pending_redefinition,
570*e4b17023SJohn Marino 			      pending_redefine_extname, ix);
571*e4b17023SJohn Marino 
572*e4b17023SJohn Marino 	/* If we already have an asmname, #pragma redefine_extname is
573*e4b17023SJohn Marino 	   ignored (with a warning if it conflicts).  */
574*e4b17023SJohn Marino 	if (asmname)
575*e4b17023SJohn Marino 	  {
576*e4b17023SJohn Marino 	    if (strcmp (TREE_STRING_POINTER (asmname),
577*e4b17023SJohn Marino 			IDENTIFIER_POINTER (newname)) != 0)
578*e4b17023SJohn Marino 	      warning (OPT_Wpragmas, "#pragma redefine_extname ignored due to "
579*e4b17023SJohn Marino 		       "conflict with __asm__ declaration");
580*e4b17023SJohn Marino 	    return asmname;
581*e4b17023SJohn Marino 	  }
582*e4b17023SJohn Marino 
583*e4b17023SJohn Marino 	/* Otherwise we use what we've got; #pragma extern_prefix is
584*e4b17023SJohn Marino 	   silently ignored.  */
585*e4b17023SJohn Marino 	return build_string (IDENTIFIER_LENGTH (newname),
586*e4b17023SJohn Marino 			     IDENTIFIER_POINTER (newname));
587*e4b17023SJohn Marino       }
588*e4b17023SJohn Marino 
589*e4b17023SJohn Marino   /* If we've got an asmname, #pragma extern_prefix is silently ignored.  */
590*e4b17023SJohn Marino   if (asmname)
591*e4b17023SJohn Marino     return asmname;
592*e4b17023SJohn Marino 
593*e4b17023SJohn Marino   /* If #pragma extern_prefix is in effect, apply it.  */
594*e4b17023SJohn Marino   if (pragma_extern_prefix)
595*e4b17023SJohn Marino     {
596*e4b17023SJohn Marino       const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix);
597*e4b17023SJohn Marino       size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1;
598*e4b17023SJohn Marino 
599*e4b17023SJohn Marino       const char *id = IDENTIFIER_POINTER (DECL_NAME (decl));
600*e4b17023SJohn Marino       size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl));
601*e4b17023SJohn Marino 
602*e4b17023SJohn Marino       char *newname = (char *) alloca (plen + ilen + 1);
603*e4b17023SJohn Marino 
604*e4b17023SJohn Marino       memcpy (newname,        prefix, plen);
605*e4b17023SJohn Marino       memcpy (newname + plen, id, ilen + 1);
606*e4b17023SJohn Marino 
607*e4b17023SJohn Marino       return build_string (plen + ilen, newname);
608*e4b17023SJohn Marino     }
609*e4b17023SJohn Marino 
610*e4b17023SJohn Marino   /* Nada.  */
611*e4b17023SJohn Marino   return 0;
612*e4b17023SJohn Marino }
613*e4b17023SJohn Marino 
614*e4b17023SJohn Marino 
615*e4b17023SJohn Marino static void handle_pragma_visibility (cpp_reader *);
616*e4b17023SJohn Marino 
617*e4b17023SJohn Marino static VEC (int, heap) *visstack;
618*e4b17023SJohn Marino 
619*e4b17023SJohn Marino /* Push the visibility indicated by STR onto the top of the #pragma
620*e4b17023SJohn Marino    visibility stack.  KIND is 0 for #pragma GCC visibility, 1 for
621*e4b17023SJohn Marino    C++ namespace with visibility attribute and 2 for C++ builtin
622*e4b17023SJohn Marino    ABI namespace.  push_visibility/pop_visibility calls must have
623*e4b17023SJohn Marino    matching KIND, it is not allowed to push visibility using one
624*e4b17023SJohn Marino    KIND and pop using a different one.  */
625*e4b17023SJohn Marino 
626*e4b17023SJohn Marino void
push_visibility(const char * str,int kind)627*e4b17023SJohn Marino push_visibility (const char *str, int kind)
628*e4b17023SJohn Marino {
629*e4b17023SJohn Marino   VEC_safe_push (int, heap, visstack,
630*e4b17023SJohn Marino 		 ((int) default_visibility) | (kind << 8));
631*e4b17023SJohn Marino   if (!strcmp (str, "default"))
632*e4b17023SJohn Marino     default_visibility = VISIBILITY_DEFAULT;
633*e4b17023SJohn Marino   else if (!strcmp (str, "internal"))
634*e4b17023SJohn Marino     default_visibility = VISIBILITY_INTERNAL;
635*e4b17023SJohn Marino   else if (!strcmp (str, "hidden"))
636*e4b17023SJohn Marino     default_visibility = VISIBILITY_HIDDEN;
637*e4b17023SJohn Marino   else if (!strcmp (str, "protected"))
638*e4b17023SJohn Marino     default_visibility = VISIBILITY_PROTECTED;
639*e4b17023SJohn Marino   else
640*e4b17023SJohn Marino     GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected");
641*e4b17023SJohn Marino   visibility_options.inpragma = 1;
642*e4b17023SJohn Marino }
643*e4b17023SJohn Marino 
644*e4b17023SJohn Marino /* Pop a level of the #pragma visibility stack.  Return true if
645*e4b17023SJohn Marino    successful.  */
646*e4b17023SJohn Marino 
647*e4b17023SJohn Marino bool
pop_visibility(int kind)648*e4b17023SJohn Marino pop_visibility (int kind)
649*e4b17023SJohn Marino {
650*e4b17023SJohn Marino   if (!VEC_length (int, visstack))
651*e4b17023SJohn Marino     return false;
652*e4b17023SJohn Marino   if ((VEC_last (int, visstack) >> 8) != kind)
653*e4b17023SJohn Marino     return false;
654*e4b17023SJohn Marino   default_visibility
655*e4b17023SJohn Marino     = (enum symbol_visibility) (VEC_pop (int, visstack) & 0xff);
656*e4b17023SJohn Marino   visibility_options.inpragma
657*e4b17023SJohn Marino     = VEC_length (int, visstack) != 0;
658*e4b17023SJohn Marino   return true;
659*e4b17023SJohn Marino }
660*e4b17023SJohn Marino 
661*e4b17023SJohn Marino /* Sets the default visibility for symbols to something other than that
662*e4b17023SJohn Marino    specified on the command line.  */
663*e4b17023SJohn Marino 
664*e4b17023SJohn Marino static void
handle_pragma_visibility(cpp_reader * dummy ATTRIBUTE_UNUSED)665*e4b17023SJohn Marino handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
666*e4b17023SJohn Marino {
667*e4b17023SJohn Marino   /* Form is #pragma GCC visibility push(hidden)|pop */
668*e4b17023SJohn Marino   tree x;
669*e4b17023SJohn Marino   enum cpp_ttype token;
670*e4b17023SJohn Marino   enum { bad, push, pop } action = bad;
671*e4b17023SJohn Marino 
672*e4b17023SJohn Marino   token = pragma_lex (&x);
673*e4b17023SJohn Marino   if (token == CPP_NAME)
674*e4b17023SJohn Marino     {
675*e4b17023SJohn Marino       const char *op = IDENTIFIER_POINTER (x);
676*e4b17023SJohn Marino       if (!strcmp (op, "push"))
677*e4b17023SJohn Marino 	action = push;
678*e4b17023SJohn Marino       else if (!strcmp (op, "pop"))
679*e4b17023SJohn Marino 	action = pop;
680*e4b17023SJohn Marino     }
681*e4b17023SJohn Marino   if (bad == action)
682*e4b17023SJohn Marino     GCC_BAD ("#pragma GCC visibility must be followed by push or pop");
683*e4b17023SJohn Marino   else
684*e4b17023SJohn Marino     {
685*e4b17023SJohn Marino       if (pop == action)
686*e4b17023SJohn Marino 	{
687*e4b17023SJohn Marino 	  if (! pop_visibility (0))
688*e4b17023SJohn Marino 	    GCC_BAD ("no matching push for %<#pragma GCC visibility pop%>");
689*e4b17023SJohn Marino 	}
690*e4b17023SJohn Marino       else
691*e4b17023SJohn Marino 	{
692*e4b17023SJohn Marino 	  if (pragma_lex (&x) != CPP_OPEN_PAREN)
693*e4b17023SJohn Marino 	    GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
694*e4b17023SJohn Marino 	  token = pragma_lex (&x);
695*e4b17023SJohn Marino 	  if (token != CPP_NAME)
696*e4b17023SJohn Marino 	    GCC_BAD ("malformed #pragma GCC visibility push");
697*e4b17023SJohn Marino 	  else
698*e4b17023SJohn Marino 	    push_visibility (IDENTIFIER_POINTER (x), 0);
699*e4b17023SJohn Marino 	  if (pragma_lex (&x) != CPP_CLOSE_PAREN)
700*e4b17023SJohn Marino 	    GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
701*e4b17023SJohn Marino 	}
702*e4b17023SJohn Marino     }
703*e4b17023SJohn Marino   if (pragma_lex (&x) != CPP_EOF)
704*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma GCC visibility%>");
705*e4b17023SJohn Marino }
706*e4b17023SJohn Marino 
707*e4b17023SJohn Marino static void
handle_pragma_diagnostic(cpp_reader * ARG_UNUSED (dummy))708*e4b17023SJohn Marino handle_pragma_diagnostic(cpp_reader *ARG_UNUSED(dummy))
709*e4b17023SJohn Marino {
710*e4b17023SJohn Marino   const char *kind_string, *option_string;
711*e4b17023SJohn Marino   unsigned int option_index;
712*e4b17023SJohn Marino   enum cpp_ttype token;
713*e4b17023SJohn Marino   diagnostic_t kind;
714*e4b17023SJohn Marino   tree x;
715*e4b17023SJohn Marino   struct cl_option_handlers handlers;
716*e4b17023SJohn Marino 
717*e4b17023SJohn Marino   token = pragma_lex (&x);
718*e4b17023SJohn Marino   if (token != CPP_NAME)
719*e4b17023SJohn Marino     GCC_BAD ("missing [error|warning|ignored] after %<#pragma GCC diagnostic%>");
720*e4b17023SJohn Marino   kind_string = IDENTIFIER_POINTER (x);
721*e4b17023SJohn Marino   if (strcmp (kind_string, "error") == 0)
722*e4b17023SJohn Marino     kind = DK_ERROR;
723*e4b17023SJohn Marino   else if (strcmp (kind_string, "warning") == 0)
724*e4b17023SJohn Marino     kind = DK_WARNING;
725*e4b17023SJohn Marino   else if (strcmp (kind_string, "ignored") == 0)
726*e4b17023SJohn Marino     kind = DK_IGNORED;
727*e4b17023SJohn Marino   else if (strcmp (kind_string, "push") == 0)
728*e4b17023SJohn Marino     {
729*e4b17023SJohn Marino       diagnostic_push_diagnostics (global_dc, input_location);
730*e4b17023SJohn Marino       return;
731*e4b17023SJohn Marino     }
732*e4b17023SJohn Marino   else if (strcmp (kind_string, "pop") == 0)
733*e4b17023SJohn Marino     {
734*e4b17023SJohn Marino       diagnostic_pop_diagnostics (global_dc, input_location);
735*e4b17023SJohn Marino       return;
736*e4b17023SJohn Marino     }
737*e4b17023SJohn Marino   else
738*e4b17023SJohn Marino     GCC_BAD ("expected [error|warning|ignored|push|pop] after %<#pragma GCC diagnostic%>");
739*e4b17023SJohn Marino 
740*e4b17023SJohn Marino   token = pragma_lex (&x);
741*e4b17023SJohn Marino   if (token != CPP_STRING)
742*e4b17023SJohn Marino     GCC_BAD ("missing option after %<#pragma GCC diagnostic%> kind");
743*e4b17023SJohn Marino   option_string = TREE_STRING_POINTER (x);
744*e4b17023SJohn Marino   set_default_handlers (&handlers);
745*e4b17023SJohn Marino   for (option_index = 0; option_index < cl_options_count; option_index++)
746*e4b17023SJohn Marino     if (strcmp (cl_options[option_index].opt_text, option_string) == 0)
747*e4b17023SJohn Marino       {
748*e4b17023SJohn Marino 	control_warning_option (option_index, (int) kind, kind != DK_IGNORED,
749*e4b17023SJohn Marino 				input_location, c_family_lang_mask, &handlers,
750*e4b17023SJohn Marino 				&global_options, &global_options_set,
751*e4b17023SJohn Marino 				global_dc);
752*e4b17023SJohn Marino 	return;
753*e4b17023SJohn Marino       }
754*e4b17023SJohn Marino   GCC_BAD ("unknown option after %<#pragma GCC diagnostic%> kind");
755*e4b17023SJohn Marino }
756*e4b17023SJohn Marino 
757*e4b17023SJohn Marino /*  Parse #pragma GCC target (xxx) to set target specific options.  */
758*e4b17023SJohn Marino static void
handle_pragma_target(cpp_reader * ARG_UNUSED (dummy))759*e4b17023SJohn Marino handle_pragma_target(cpp_reader *ARG_UNUSED(dummy))
760*e4b17023SJohn Marino {
761*e4b17023SJohn Marino   enum cpp_ttype token;
762*e4b17023SJohn Marino   tree x;
763*e4b17023SJohn Marino   bool close_paren_needed_p = false;
764*e4b17023SJohn Marino 
765*e4b17023SJohn Marino   if (cfun)
766*e4b17023SJohn Marino     {
767*e4b17023SJohn Marino       error ("#pragma GCC option is not allowed inside functions");
768*e4b17023SJohn Marino       return;
769*e4b17023SJohn Marino     }
770*e4b17023SJohn Marino 
771*e4b17023SJohn Marino   token = pragma_lex (&x);
772*e4b17023SJohn Marino   if (token == CPP_OPEN_PAREN)
773*e4b17023SJohn Marino     {
774*e4b17023SJohn Marino       close_paren_needed_p = true;
775*e4b17023SJohn Marino       token = pragma_lex (&x);
776*e4b17023SJohn Marino     }
777*e4b17023SJohn Marino 
778*e4b17023SJohn Marino   if (token != CPP_STRING)
779*e4b17023SJohn Marino     {
780*e4b17023SJohn Marino       GCC_BAD ("%<#pragma GCC option%> is not a string");
781*e4b17023SJohn Marino       return;
782*e4b17023SJohn Marino     }
783*e4b17023SJohn Marino 
784*e4b17023SJohn Marino   /* Strings are user options.  */
785*e4b17023SJohn Marino   else
786*e4b17023SJohn Marino     {
787*e4b17023SJohn Marino       tree args = NULL_TREE;
788*e4b17023SJohn Marino 
789*e4b17023SJohn Marino       do
790*e4b17023SJohn Marino 	{
791*e4b17023SJohn Marino 	  /* Build up the strings now as a tree linked list.  Skip empty
792*e4b17023SJohn Marino 	     strings.  */
793*e4b17023SJohn Marino 	  if (TREE_STRING_LENGTH (x) > 0)
794*e4b17023SJohn Marino 	    args = tree_cons (NULL_TREE, x, args);
795*e4b17023SJohn Marino 
796*e4b17023SJohn Marino 	  token = pragma_lex (&x);
797*e4b17023SJohn Marino 	  while (token == CPP_COMMA)
798*e4b17023SJohn Marino 	    token = pragma_lex (&x);
799*e4b17023SJohn Marino 	}
800*e4b17023SJohn Marino       while (token == CPP_STRING);
801*e4b17023SJohn Marino 
802*e4b17023SJohn Marino       if (close_paren_needed_p)
803*e4b17023SJohn Marino 	{
804*e4b17023SJohn Marino 	  if (token == CPP_CLOSE_PAREN)
805*e4b17023SJohn Marino 	    token = pragma_lex (&x);
806*e4b17023SJohn Marino 	  else
807*e4b17023SJohn Marino 	    GCC_BAD ("%<#pragma GCC target (string [,string]...)%> does "
808*e4b17023SJohn Marino 		     "not have a final %<)%>");
809*e4b17023SJohn Marino 	}
810*e4b17023SJohn Marino 
811*e4b17023SJohn Marino       if (token != CPP_EOF)
812*e4b17023SJohn Marino 	{
813*e4b17023SJohn Marino 	  error ("#pragma GCC target string... is badly formed");
814*e4b17023SJohn Marino 	  return;
815*e4b17023SJohn Marino 	}
816*e4b17023SJohn Marino 
817*e4b17023SJohn Marino       /* put arguments in the order the user typed them.  */
818*e4b17023SJohn Marino       args = nreverse (args);
819*e4b17023SJohn Marino 
820*e4b17023SJohn Marino       if (targetm.target_option.pragma_parse (args, NULL_TREE))
821*e4b17023SJohn Marino 	current_target_pragma = args;
822*e4b17023SJohn Marino     }
823*e4b17023SJohn Marino }
824*e4b17023SJohn Marino 
825*e4b17023SJohn Marino /* Handle #pragma GCC optimize to set optimization options.  */
826*e4b17023SJohn Marino static void
handle_pragma_optimize(cpp_reader * ARG_UNUSED (dummy))827*e4b17023SJohn Marino handle_pragma_optimize (cpp_reader *ARG_UNUSED(dummy))
828*e4b17023SJohn Marino {
829*e4b17023SJohn Marino   enum cpp_ttype token;
830*e4b17023SJohn Marino   tree x;
831*e4b17023SJohn Marino   bool close_paren_needed_p = false;
832*e4b17023SJohn Marino   tree optimization_previous_node = optimization_current_node;
833*e4b17023SJohn Marino 
834*e4b17023SJohn Marino   if (cfun)
835*e4b17023SJohn Marino     {
836*e4b17023SJohn Marino       error ("#pragma GCC optimize is not allowed inside functions");
837*e4b17023SJohn Marino       return;
838*e4b17023SJohn Marino     }
839*e4b17023SJohn Marino 
840*e4b17023SJohn Marino   token = pragma_lex (&x);
841*e4b17023SJohn Marino   if (token == CPP_OPEN_PAREN)
842*e4b17023SJohn Marino     {
843*e4b17023SJohn Marino       close_paren_needed_p = true;
844*e4b17023SJohn Marino       token = pragma_lex (&x);
845*e4b17023SJohn Marino     }
846*e4b17023SJohn Marino 
847*e4b17023SJohn Marino   if (token != CPP_STRING && token != CPP_NUMBER)
848*e4b17023SJohn Marino     {
849*e4b17023SJohn Marino       GCC_BAD ("%<#pragma GCC optimize%> is not a string or number");
850*e4b17023SJohn Marino       return;
851*e4b17023SJohn Marino     }
852*e4b17023SJohn Marino 
853*e4b17023SJohn Marino   /* Strings/numbers are user options.  */
854*e4b17023SJohn Marino   else
855*e4b17023SJohn Marino     {
856*e4b17023SJohn Marino       tree args = NULL_TREE;
857*e4b17023SJohn Marino 
858*e4b17023SJohn Marino       do
859*e4b17023SJohn Marino 	{
860*e4b17023SJohn Marino 	  /* Build up the numbers/strings now as a list.  */
861*e4b17023SJohn Marino 	  if (token != CPP_STRING || TREE_STRING_LENGTH (x) > 0)
862*e4b17023SJohn Marino 	    args = tree_cons (NULL_TREE, x, args);
863*e4b17023SJohn Marino 
864*e4b17023SJohn Marino 	  token = pragma_lex (&x);
865*e4b17023SJohn Marino 	  while (token == CPP_COMMA)
866*e4b17023SJohn Marino 	    token = pragma_lex (&x);
867*e4b17023SJohn Marino 	}
868*e4b17023SJohn Marino       while (token == CPP_STRING || token == CPP_NUMBER);
869*e4b17023SJohn Marino 
870*e4b17023SJohn Marino       if (close_paren_needed_p)
871*e4b17023SJohn Marino 	{
872*e4b17023SJohn Marino 	  if (token == CPP_CLOSE_PAREN)
873*e4b17023SJohn Marino 	    token = pragma_lex (&x);
874*e4b17023SJohn Marino 	  else
875*e4b17023SJohn Marino 	    GCC_BAD ("%<#pragma GCC optimize (string [,string]...)%> does "
876*e4b17023SJohn Marino 		     "not have a final %<)%>");
877*e4b17023SJohn Marino 	}
878*e4b17023SJohn Marino 
879*e4b17023SJohn Marino       if (token != CPP_EOF)
880*e4b17023SJohn Marino 	{
881*e4b17023SJohn Marino 	  error ("#pragma GCC optimize string... is badly formed");
882*e4b17023SJohn Marino 	  return;
883*e4b17023SJohn Marino 	}
884*e4b17023SJohn Marino 
885*e4b17023SJohn Marino       /* put arguments in the order the user typed them.  */
886*e4b17023SJohn Marino       args = nreverse (args);
887*e4b17023SJohn Marino 
888*e4b17023SJohn Marino       parse_optimize_options (args, false);
889*e4b17023SJohn Marino       current_optimize_pragma = chainon (current_optimize_pragma, args);
890*e4b17023SJohn Marino       optimization_current_node = build_optimization_node ();
891*e4b17023SJohn Marino       c_cpp_builtins_optimize_pragma (parse_in,
892*e4b17023SJohn Marino 				      optimization_previous_node,
893*e4b17023SJohn Marino 				      optimization_current_node);
894*e4b17023SJohn Marino     }
895*e4b17023SJohn Marino }
896*e4b17023SJohn Marino 
897*e4b17023SJohn Marino /* Stack of the #pragma GCC options created with #pragma GCC push_option.  Save
898*e4b17023SJohn Marino    both the binary representation of the options and the TREE_LIST of
899*e4b17023SJohn Marino    strings that will be added to the function's attribute list.  */
900*e4b17023SJohn Marino typedef struct GTY(()) opt_stack {
901*e4b17023SJohn Marino   struct opt_stack *prev;
902*e4b17023SJohn Marino   tree target_binary;
903*e4b17023SJohn Marino   tree target_strings;
904*e4b17023SJohn Marino   tree optimize_binary;
905*e4b17023SJohn Marino   tree optimize_strings;
906*e4b17023SJohn Marino } opt_stack;
907*e4b17023SJohn Marino 
908*e4b17023SJohn Marino static GTY(()) struct opt_stack * options_stack;
909*e4b17023SJohn Marino 
910*e4b17023SJohn Marino /* Handle #pragma GCC push_options to save the current target and optimization
911*e4b17023SJohn Marino    options.  */
912*e4b17023SJohn Marino 
913*e4b17023SJohn Marino static void
handle_pragma_push_options(cpp_reader * ARG_UNUSED (dummy))914*e4b17023SJohn Marino handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
915*e4b17023SJohn Marino {
916*e4b17023SJohn Marino   enum cpp_ttype token;
917*e4b17023SJohn Marino   tree x = 0;
918*e4b17023SJohn Marino   opt_stack *p;
919*e4b17023SJohn Marino 
920*e4b17023SJohn Marino   token = pragma_lex (&x);
921*e4b17023SJohn Marino   if (token != CPP_EOF)
922*e4b17023SJohn Marino     {
923*e4b17023SJohn Marino       warning (OPT_Wpragmas, "junk at end of %<#pragma push_options%>");
924*e4b17023SJohn Marino       return;
925*e4b17023SJohn Marino     }
926*e4b17023SJohn Marino 
927*e4b17023SJohn Marino   p = ggc_alloc_opt_stack ();
928*e4b17023SJohn Marino   p->prev = options_stack;
929*e4b17023SJohn Marino   options_stack = p;
930*e4b17023SJohn Marino 
931*e4b17023SJohn Marino   /* Save optimization and target flags in binary format.  */
932*e4b17023SJohn Marino   p->optimize_binary = build_optimization_node ();
933*e4b17023SJohn Marino   p->target_binary = build_target_option_node ();
934*e4b17023SJohn Marino 
935*e4b17023SJohn Marino   /* Save optimization and target flags in string list format.  */
936*e4b17023SJohn Marino   p->optimize_strings = copy_list (current_optimize_pragma);
937*e4b17023SJohn Marino   p->target_strings = copy_list (current_target_pragma);
938*e4b17023SJohn Marino }
939*e4b17023SJohn Marino 
940*e4b17023SJohn Marino /* Handle #pragma GCC pop_options to restore the current target and
941*e4b17023SJohn Marino    optimization options from a previous push_options.  */
942*e4b17023SJohn Marino 
943*e4b17023SJohn Marino static void
handle_pragma_pop_options(cpp_reader * ARG_UNUSED (dummy))944*e4b17023SJohn Marino handle_pragma_pop_options (cpp_reader *ARG_UNUSED(dummy))
945*e4b17023SJohn Marino {
946*e4b17023SJohn Marino   enum cpp_ttype token;
947*e4b17023SJohn Marino   tree x = 0;
948*e4b17023SJohn Marino   opt_stack *p;
949*e4b17023SJohn Marino 
950*e4b17023SJohn Marino   token = pragma_lex (&x);
951*e4b17023SJohn Marino   if (token != CPP_EOF)
952*e4b17023SJohn Marino     {
953*e4b17023SJohn Marino       warning (OPT_Wpragmas, "junk at end of %<#pragma pop_options%>");
954*e4b17023SJohn Marino       return;
955*e4b17023SJohn Marino     }
956*e4b17023SJohn Marino 
957*e4b17023SJohn Marino   if (! options_stack)
958*e4b17023SJohn Marino     {
959*e4b17023SJohn Marino       warning (OPT_Wpragmas,
960*e4b17023SJohn Marino 	       "%<#pragma GCC pop_options%> without a corresponding "
961*e4b17023SJohn Marino 	       "%<#pragma GCC push_options%>");
962*e4b17023SJohn Marino       return;
963*e4b17023SJohn Marino     }
964*e4b17023SJohn Marino 
965*e4b17023SJohn Marino   p = options_stack;
966*e4b17023SJohn Marino   options_stack = p->prev;
967*e4b17023SJohn Marino 
968*e4b17023SJohn Marino   if (p->target_binary != target_option_current_node)
969*e4b17023SJohn Marino     {
970*e4b17023SJohn Marino       (void) targetm.target_option.pragma_parse (NULL_TREE, p->target_binary);
971*e4b17023SJohn Marino       target_option_current_node = p->target_binary;
972*e4b17023SJohn Marino     }
973*e4b17023SJohn Marino 
974*e4b17023SJohn Marino   if (p->optimize_binary != optimization_current_node)
975*e4b17023SJohn Marino     {
976*e4b17023SJohn Marino       tree old_optimize = optimization_current_node;
977*e4b17023SJohn Marino       cl_optimization_restore (&global_options,
978*e4b17023SJohn Marino 			       TREE_OPTIMIZATION (p->optimize_binary));
979*e4b17023SJohn Marino       c_cpp_builtins_optimize_pragma (parse_in, old_optimize,
980*e4b17023SJohn Marino 				      p->optimize_binary);
981*e4b17023SJohn Marino       optimization_current_node = p->optimize_binary;
982*e4b17023SJohn Marino     }
983*e4b17023SJohn Marino 
984*e4b17023SJohn Marino   current_target_pragma = p->target_strings;
985*e4b17023SJohn Marino   current_optimize_pragma = p->optimize_strings;
986*e4b17023SJohn Marino }
987*e4b17023SJohn Marino 
988*e4b17023SJohn Marino /* Handle #pragma GCC reset_options to restore the current target and
989*e4b17023SJohn Marino    optimization options to the original options used on the command line.  */
990*e4b17023SJohn Marino 
991*e4b17023SJohn Marino static void
handle_pragma_reset_options(cpp_reader * ARG_UNUSED (dummy))992*e4b17023SJohn Marino handle_pragma_reset_options (cpp_reader *ARG_UNUSED(dummy))
993*e4b17023SJohn Marino {
994*e4b17023SJohn Marino   enum cpp_ttype token;
995*e4b17023SJohn Marino   tree x = 0;
996*e4b17023SJohn Marino   tree new_optimize = optimization_default_node;
997*e4b17023SJohn Marino   tree new_target = target_option_default_node;
998*e4b17023SJohn Marino 
999*e4b17023SJohn Marino   token = pragma_lex (&x);
1000*e4b17023SJohn Marino   if (token != CPP_EOF)
1001*e4b17023SJohn Marino     {
1002*e4b17023SJohn Marino       warning (OPT_Wpragmas, "junk at end of %<#pragma reset_options%>");
1003*e4b17023SJohn Marino       return;
1004*e4b17023SJohn Marino     }
1005*e4b17023SJohn Marino 
1006*e4b17023SJohn Marino   if (new_target != target_option_current_node)
1007*e4b17023SJohn Marino     {
1008*e4b17023SJohn Marino       (void) targetm.target_option.pragma_parse (NULL_TREE, new_target);
1009*e4b17023SJohn Marino       target_option_current_node = new_target;
1010*e4b17023SJohn Marino     }
1011*e4b17023SJohn Marino 
1012*e4b17023SJohn Marino   if (new_optimize != optimization_current_node)
1013*e4b17023SJohn Marino     {
1014*e4b17023SJohn Marino       tree old_optimize = optimization_current_node;
1015*e4b17023SJohn Marino       cl_optimization_restore (&global_options,
1016*e4b17023SJohn Marino 			       TREE_OPTIMIZATION (new_optimize));
1017*e4b17023SJohn Marino       c_cpp_builtins_optimize_pragma (parse_in, old_optimize, new_optimize);
1018*e4b17023SJohn Marino       optimization_current_node = new_optimize;
1019*e4b17023SJohn Marino     }
1020*e4b17023SJohn Marino 
1021*e4b17023SJohn Marino   current_target_pragma = NULL_TREE;
1022*e4b17023SJohn Marino   current_optimize_pragma = NULL_TREE;
1023*e4b17023SJohn Marino }
1024*e4b17023SJohn Marino 
1025*e4b17023SJohn Marino /* Print a plain user-specified message.  */
1026*e4b17023SJohn Marino 
1027*e4b17023SJohn Marino static void
handle_pragma_message(cpp_reader * ARG_UNUSED (dummy))1028*e4b17023SJohn Marino handle_pragma_message (cpp_reader *ARG_UNUSED(dummy))
1029*e4b17023SJohn Marino {
1030*e4b17023SJohn Marino   enum cpp_ttype token;
1031*e4b17023SJohn Marino   tree x, message = 0;
1032*e4b17023SJohn Marino 
1033*e4b17023SJohn Marino   token = pragma_lex (&x);
1034*e4b17023SJohn Marino   if (token == CPP_OPEN_PAREN)
1035*e4b17023SJohn Marino     {
1036*e4b17023SJohn Marino       token = pragma_lex (&x);
1037*e4b17023SJohn Marino       if (token == CPP_STRING)
1038*e4b17023SJohn Marino         message = x;
1039*e4b17023SJohn Marino       else
1040*e4b17023SJohn Marino         GCC_BAD ("expected a string after %<#pragma message%>");
1041*e4b17023SJohn Marino       if (pragma_lex (&x) != CPP_CLOSE_PAREN)
1042*e4b17023SJohn Marino         GCC_BAD ("malformed %<#pragma message%>, ignored");
1043*e4b17023SJohn Marino     }
1044*e4b17023SJohn Marino   else if (token == CPP_STRING)
1045*e4b17023SJohn Marino     message = x;
1046*e4b17023SJohn Marino   else
1047*e4b17023SJohn Marino     GCC_BAD ("expected a string after %<#pragma message%>");
1048*e4b17023SJohn Marino 
1049*e4b17023SJohn Marino   gcc_assert (message);
1050*e4b17023SJohn Marino 
1051*e4b17023SJohn Marino   if (pragma_lex (&x) != CPP_EOF)
1052*e4b17023SJohn Marino     warning (OPT_Wpragmas, "junk at end of %<#pragma message%>");
1053*e4b17023SJohn Marino 
1054*e4b17023SJohn Marino   if (TREE_STRING_LENGTH (message) > 1)
1055*e4b17023SJohn Marino     inform (input_location, "#pragma message: %s", TREE_STRING_POINTER (message));
1056*e4b17023SJohn Marino }
1057*e4b17023SJohn Marino 
1058*e4b17023SJohn Marino /* Mark whether the current location is valid for a STDC pragma.  */
1059*e4b17023SJohn Marino 
1060*e4b17023SJohn Marino static bool valid_location_for_stdc_pragma;
1061*e4b17023SJohn Marino 
1062*e4b17023SJohn Marino void
mark_valid_location_for_stdc_pragma(bool flag)1063*e4b17023SJohn Marino mark_valid_location_for_stdc_pragma (bool flag)
1064*e4b17023SJohn Marino {
1065*e4b17023SJohn Marino   valid_location_for_stdc_pragma = flag;
1066*e4b17023SJohn Marino }
1067*e4b17023SJohn Marino 
1068*e4b17023SJohn Marino /* Return true if the current location is valid for a STDC pragma.  */
1069*e4b17023SJohn Marino 
1070*e4b17023SJohn Marino bool
valid_location_for_stdc_pragma_p(void)1071*e4b17023SJohn Marino valid_location_for_stdc_pragma_p (void)
1072*e4b17023SJohn Marino {
1073*e4b17023SJohn Marino   return valid_location_for_stdc_pragma;
1074*e4b17023SJohn Marino }
1075*e4b17023SJohn Marino 
1076*e4b17023SJohn Marino enum pragma_switch_t { PRAGMA_ON, PRAGMA_OFF, PRAGMA_DEFAULT, PRAGMA_BAD };
1077*e4b17023SJohn Marino 
1078*e4b17023SJohn Marino /* A STDC pragma must appear outside of external declarations or
1079*e4b17023SJohn Marino    preceding all explicit declarations and statements inside a compound
1080*e4b17023SJohn Marino    statement; its behavior is undefined if used in any other context.
1081*e4b17023SJohn Marino    It takes a switch of ON, OFF, or DEFAULT.  */
1082*e4b17023SJohn Marino 
1083*e4b17023SJohn Marino static enum pragma_switch_t
handle_stdc_pragma(const char * pname)1084*e4b17023SJohn Marino handle_stdc_pragma (const char *pname)
1085*e4b17023SJohn Marino {
1086*e4b17023SJohn Marino   const char *arg;
1087*e4b17023SJohn Marino   tree t;
1088*e4b17023SJohn Marino   enum pragma_switch_t ret;
1089*e4b17023SJohn Marino 
1090*e4b17023SJohn Marino   if (!valid_location_for_stdc_pragma_p ())
1091*e4b17023SJohn Marino     {
1092*e4b17023SJohn Marino       warning (OPT_Wpragmas, "invalid location for %<pragma %s%>, ignored",
1093*e4b17023SJohn Marino 	       pname);
1094*e4b17023SJohn Marino       return PRAGMA_BAD;
1095*e4b17023SJohn Marino     }
1096*e4b17023SJohn Marino 
1097*e4b17023SJohn Marino   if (pragma_lex (&t) != CPP_NAME)
1098*e4b17023SJohn Marino     {
1099*e4b17023SJohn Marino       warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
1100*e4b17023SJohn Marino       return PRAGMA_BAD;
1101*e4b17023SJohn Marino     }
1102*e4b17023SJohn Marino 
1103*e4b17023SJohn Marino   arg = IDENTIFIER_POINTER (t);
1104*e4b17023SJohn Marino 
1105*e4b17023SJohn Marino   if (!strcmp (arg, "ON"))
1106*e4b17023SJohn Marino     ret = PRAGMA_ON;
1107*e4b17023SJohn Marino   else if (!strcmp (arg, "OFF"))
1108*e4b17023SJohn Marino     ret = PRAGMA_OFF;
1109*e4b17023SJohn Marino   else if (!strcmp (arg, "DEFAULT"))
1110*e4b17023SJohn Marino     ret = PRAGMA_DEFAULT;
1111*e4b17023SJohn Marino   else
1112*e4b17023SJohn Marino     {
1113*e4b17023SJohn Marino       warning (OPT_Wpragmas, "malformed %<#pragma %s%>, ignored", pname);
1114*e4b17023SJohn Marino       return PRAGMA_BAD;
1115*e4b17023SJohn Marino     }
1116*e4b17023SJohn Marino 
1117*e4b17023SJohn Marino   if (pragma_lex (&t) != CPP_EOF)
1118*e4b17023SJohn Marino     {
1119*e4b17023SJohn Marino       warning (OPT_Wpragmas, "junk at end of %<#pragma %s%>", pname);
1120*e4b17023SJohn Marino       return PRAGMA_BAD;
1121*e4b17023SJohn Marino     }
1122*e4b17023SJohn Marino 
1123*e4b17023SJohn Marino   return ret;
1124*e4b17023SJohn Marino }
1125*e4b17023SJohn Marino 
1126*e4b17023SJohn Marino /* #pragma STDC FLOAT_CONST_DECIMAL64 ON
1127*e4b17023SJohn Marino    #pragma STDC FLOAT_CONST_DECIMAL64 OFF
1128*e4b17023SJohn Marino    #pragma STDC FLOAT_CONST_DECIMAL64 DEFAULT */
1129*e4b17023SJohn Marino 
1130*e4b17023SJohn Marino static void
handle_pragma_float_const_decimal64(cpp_reader * ARG_UNUSED (dummy))1131*e4b17023SJohn Marino handle_pragma_float_const_decimal64 (cpp_reader *ARG_UNUSED (dummy))
1132*e4b17023SJohn Marino {
1133*e4b17023SJohn Marino   if (c_dialect_cxx ())
1134*e4b17023SJohn Marino     {
1135*e4b17023SJohn Marino       if (warn_unknown_pragmas > in_system_header)
1136*e4b17023SJohn Marino 	warning (OPT_Wunknown_pragmas,
1137*e4b17023SJohn Marino 		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
1138*e4b17023SJohn Marino 		 " for C++");
1139*e4b17023SJohn Marino       return;
1140*e4b17023SJohn Marino     }
1141*e4b17023SJohn Marino 
1142*e4b17023SJohn Marino   if (!targetm.decimal_float_supported_p ())
1143*e4b17023SJohn Marino     {
1144*e4b17023SJohn Marino       if (warn_unknown_pragmas > in_system_header)
1145*e4b17023SJohn Marino 	warning (OPT_Wunknown_pragmas,
1146*e4b17023SJohn Marino 		 "%<#pragma STDC FLOAT_CONST_DECIMAL64%> is not supported"
1147*e4b17023SJohn Marino 		 " on this target");
1148*e4b17023SJohn Marino       return;
1149*e4b17023SJohn Marino     }
1150*e4b17023SJohn Marino 
1151*e4b17023SJohn Marino   pedwarn (input_location, OPT_pedantic,
1152*e4b17023SJohn Marino 	   "ISO C does not support %<#pragma STDC FLOAT_CONST_DECIMAL64%>");
1153*e4b17023SJohn Marino 
1154*e4b17023SJohn Marino   switch (handle_stdc_pragma ("STDC FLOAT_CONST_DECIMAL64"))
1155*e4b17023SJohn Marino     {
1156*e4b17023SJohn Marino     case PRAGMA_ON:
1157*e4b17023SJohn Marino       set_float_const_decimal64 ();
1158*e4b17023SJohn Marino       break;
1159*e4b17023SJohn Marino     case PRAGMA_OFF:
1160*e4b17023SJohn Marino     case PRAGMA_DEFAULT:
1161*e4b17023SJohn Marino       clear_float_const_decimal64 ();
1162*e4b17023SJohn Marino       break;
1163*e4b17023SJohn Marino     case PRAGMA_BAD:
1164*e4b17023SJohn Marino       break;
1165*e4b17023SJohn Marino     }
1166*e4b17023SJohn Marino }
1167*e4b17023SJohn Marino 
1168*e4b17023SJohn Marino /* A vector of registered pragma callbacks, which is never freed.   */
1169*e4b17023SJohn Marino DEF_VEC_O (internal_pragma_handler);
1170*e4b17023SJohn Marino DEF_VEC_ALLOC_O (internal_pragma_handler, heap);
1171*e4b17023SJohn Marino 
VEC(internal_pragma_handler,heap)1172*e4b17023SJohn Marino static VEC(internal_pragma_handler, heap) *registered_pragmas;
1173*e4b17023SJohn Marino 
1174*e4b17023SJohn Marino typedef struct
1175*e4b17023SJohn Marino {
1176*e4b17023SJohn Marino   const char *space;
1177*e4b17023SJohn Marino   const char *name;
1178*e4b17023SJohn Marino } pragma_ns_name;
1179*e4b17023SJohn Marino 
1180*e4b17023SJohn Marino DEF_VEC_O (pragma_ns_name);
1181*e4b17023SJohn Marino DEF_VEC_ALLOC_O (pragma_ns_name, heap);
1182*e4b17023SJohn Marino 
VEC(pragma_ns_name,heap)1183*e4b17023SJohn Marino static VEC(pragma_ns_name, heap) *registered_pp_pragmas;
1184*e4b17023SJohn Marino 
1185*e4b17023SJohn Marino struct omp_pragma_def { const char *name; unsigned int id; };
1186*e4b17023SJohn Marino static const struct omp_pragma_def omp_pragmas[] = {
1187*e4b17023SJohn Marino   { "atomic", PRAGMA_OMP_ATOMIC },
1188*e4b17023SJohn Marino   { "barrier", PRAGMA_OMP_BARRIER },
1189*e4b17023SJohn Marino   { "critical", PRAGMA_OMP_CRITICAL },
1190*e4b17023SJohn Marino   { "flush", PRAGMA_OMP_FLUSH },
1191*e4b17023SJohn Marino   { "for", PRAGMA_OMP_FOR },
1192*e4b17023SJohn Marino   { "master", PRAGMA_OMP_MASTER },
1193*e4b17023SJohn Marino   { "ordered", PRAGMA_OMP_ORDERED },
1194*e4b17023SJohn Marino   { "parallel", PRAGMA_OMP_PARALLEL },
1195*e4b17023SJohn Marino   { "section", PRAGMA_OMP_SECTION },
1196*e4b17023SJohn Marino   { "sections", PRAGMA_OMP_SECTIONS },
1197*e4b17023SJohn Marino   { "single", PRAGMA_OMP_SINGLE },
1198*e4b17023SJohn Marino   { "task", PRAGMA_OMP_TASK },
1199*e4b17023SJohn Marino   { "taskwait", PRAGMA_OMP_TASKWAIT },
1200*e4b17023SJohn Marino   { "taskyield", PRAGMA_OMP_TASKYIELD },
1201*e4b17023SJohn Marino   { "threadprivate", PRAGMA_OMP_THREADPRIVATE }
1202*e4b17023SJohn Marino };
1203*e4b17023SJohn Marino 
1204*e4b17023SJohn Marino void
c_pp_lookup_pragma(unsigned int id,const char ** space,const char ** name)1205*e4b17023SJohn Marino c_pp_lookup_pragma (unsigned int id, const char **space, const char **name)
1206*e4b17023SJohn Marino {
1207*e4b17023SJohn Marino   const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
1208*e4b17023SJohn Marino   int i;
1209*e4b17023SJohn Marino 
1210*e4b17023SJohn Marino   for (i = 0; i < n_omp_pragmas; ++i)
1211*e4b17023SJohn Marino     if (omp_pragmas[i].id == id)
1212*e4b17023SJohn Marino       {
1213*e4b17023SJohn Marino 	*space = "omp";
1214*e4b17023SJohn Marino 	*name = omp_pragmas[i].name;
1215*e4b17023SJohn Marino 	return;
1216*e4b17023SJohn Marino       }
1217*e4b17023SJohn Marino 
1218*e4b17023SJohn Marino   if (id >= PRAGMA_FIRST_EXTERNAL
1219*e4b17023SJohn Marino       && (id < PRAGMA_FIRST_EXTERNAL
1220*e4b17023SJohn Marino 	  + VEC_length (pragma_ns_name, registered_pp_pragmas)))
1221*e4b17023SJohn Marino     {
1222*e4b17023SJohn Marino       *space = VEC_index (pragma_ns_name, registered_pp_pragmas,
1223*e4b17023SJohn Marino 			  id - PRAGMA_FIRST_EXTERNAL)->space;
1224*e4b17023SJohn Marino       *name = VEC_index (pragma_ns_name, registered_pp_pragmas,
1225*e4b17023SJohn Marino 			 id - PRAGMA_FIRST_EXTERNAL)->name;
1226*e4b17023SJohn Marino       return;
1227*e4b17023SJohn Marino     }
1228*e4b17023SJohn Marino 
1229*e4b17023SJohn Marino   gcc_unreachable ();
1230*e4b17023SJohn Marino }
1231*e4b17023SJohn Marino 
1232*e4b17023SJohn Marino /* Front-end wrappers for pragma registration to avoid dragging
1233*e4b17023SJohn Marino    cpplib.h in almost everywhere.  */
1234*e4b17023SJohn Marino 
1235*e4b17023SJohn Marino static void
c_register_pragma_1(const char * space,const char * name,internal_pragma_handler ihandler,bool allow_expansion)1236*e4b17023SJohn Marino c_register_pragma_1 (const char *space, const char *name,
1237*e4b17023SJohn Marino                      internal_pragma_handler ihandler, bool allow_expansion)
1238*e4b17023SJohn Marino {
1239*e4b17023SJohn Marino   unsigned id;
1240*e4b17023SJohn Marino 
1241*e4b17023SJohn Marino   if (flag_preprocess_only)
1242*e4b17023SJohn Marino     {
1243*e4b17023SJohn Marino       pragma_ns_name ns_name;
1244*e4b17023SJohn Marino 
1245*e4b17023SJohn Marino       if (!allow_expansion)
1246*e4b17023SJohn Marino 	return;
1247*e4b17023SJohn Marino 
1248*e4b17023SJohn Marino       ns_name.space = space;
1249*e4b17023SJohn Marino       ns_name.name = name;
1250*e4b17023SJohn Marino       VEC_safe_push (pragma_ns_name, heap, registered_pp_pragmas, &ns_name);
1251*e4b17023SJohn Marino       id = VEC_length (pragma_ns_name, registered_pp_pragmas);
1252*e4b17023SJohn Marino       id += PRAGMA_FIRST_EXTERNAL - 1;
1253*e4b17023SJohn Marino     }
1254*e4b17023SJohn Marino   else
1255*e4b17023SJohn Marino     {
1256*e4b17023SJohn Marino       VEC_safe_push (internal_pragma_handler, heap, registered_pragmas,
1257*e4b17023SJohn Marino                      &ihandler);
1258*e4b17023SJohn Marino       id = VEC_length (internal_pragma_handler, registered_pragmas);
1259*e4b17023SJohn Marino       id += PRAGMA_FIRST_EXTERNAL - 1;
1260*e4b17023SJohn Marino 
1261*e4b17023SJohn Marino       /* The C++ front end allocates 6 bits in cp_token; the C front end
1262*e4b17023SJohn Marino 	 allocates 7 bits in c_token.  At present this is sufficient.  */
1263*e4b17023SJohn Marino       gcc_assert (id < 64);
1264*e4b17023SJohn Marino     }
1265*e4b17023SJohn Marino 
1266*e4b17023SJohn Marino   cpp_register_deferred_pragma (parse_in, space, name, id,
1267*e4b17023SJohn Marino 				allow_expansion, false);
1268*e4b17023SJohn Marino }
1269*e4b17023SJohn Marino 
1270*e4b17023SJohn Marino /* Register a C pragma handler, using a space and a name.  It disallows pragma
1271*e4b17023SJohn Marino    expansion (if you want it, use c_register_pragma_with_expansion instead).  */
1272*e4b17023SJohn Marino void
c_register_pragma(const char * space,const char * name,pragma_handler_1arg handler)1273*e4b17023SJohn Marino c_register_pragma (const char *space, const char *name,
1274*e4b17023SJohn Marino                    pragma_handler_1arg handler)
1275*e4b17023SJohn Marino {
1276*e4b17023SJohn Marino   internal_pragma_handler ihandler;
1277*e4b17023SJohn Marino 
1278*e4b17023SJohn Marino   ihandler.handler.handler_1arg = handler;
1279*e4b17023SJohn Marino   ihandler.extra_data = false;
1280*e4b17023SJohn Marino   ihandler.data = NULL;
1281*e4b17023SJohn Marino   c_register_pragma_1 (space, name, ihandler, false);
1282*e4b17023SJohn Marino }
1283*e4b17023SJohn Marino 
1284*e4b17023SJohn Marino /* Register a C pragma handler, using a space and a name, it also carries an
1285*e4b17023SJohn Marino    extra data field which can be used by the handler.  It disallows pragma
1286*e4b17023SJohn Marino    expansion (if you want it, use c_register_pragma_with_expansion_and_data
1287*e4b17023SJohn Marino    instead).  */
1288*e4b17023SJohn Marino void
c_register_pragma_with_data(const char * space,const char * name,pragma_handler_2arg handler,void * data)1289*e4b17023SJohn Marino c_register_pragma_with_data (const char *space, const char *name,
1290*e4b17023SJohn Marino                              pragma_handler_2arg handler, void * data)
1291*e4b17023SJohn Marino {
1292*e4b17023SJohn Marino   internal_pragma_handler ihandler;
1293*e4b17023SJohn Marino 
1294*e4b17023SJohn Marino   ihandler.handler.handler_2arg = handler;
1295*e4b17023SJohn Marino   ihandler.extra_data = true;
1296*e4b17023SJohn Marino   ihandler.data = data;
1297*e4b17023SJohn Marino   c_register_pragma_1 (space, name, ihandler, false);
1298*e4b17023SJohn Marino }
1299*e4b17023SJohn Marino 
1300*e4b17023SJohn Marino /* Register a C pragma handler, using a space and a name.  It allows pragma
1301*e4b17023SJohn Marino    expansion as in the following example:
1302*e4b17023SJohn Marino 
1303*e4b17023SJohn Marino    #define NUMBER 10
1304*e4b17023SJohn Marino    #pragma count (NUMBER)
1305*e4b17023SJohn Marino 
1306*e4b17023SJohn Marino    Name expansion is still disallowed.  */
1307*e4b17023SJohn Marino void
c_register_pragma_with_expansion(const char * space,const char * name,pragma_handler_1arg handler)1308*e4b17023SJohn Marino c_register_pragma_with_expansion (const char *space, const char *name,
1309*e4b17023SJohn Marino 				  pragma_handler_1arg handler)
1310*e4b17023SJohn Marino {
1311*e4b17023SJohn Marino   internal_pragma_handler ihandler;
1312*e4b17023SJohn Marino 
1313*e4b17023SJohn Marino   ihandler.handler.handler_1arg = handler;
1314*e4b17023SJohn Marino   ihandler.extra_data = false;
1315*e4b17023SJohn Marino   ihandler.data = NULL;
1316*e4b17023SJohn Marino   c_register_pragma_1 (space, name, ihandler, true);
1317*e4b17023SJohn Marino }
1318*e4b17023SJohn Marino 
1319*e4b17023SJohn Marino /* Register a C pragma handler, using a space and a name, it also carries an
1320*e4b17023SJohn Marino    extra data field which can be used by the handler.  It allows pragma
1321*e4b17023SJohn Marino    expansion as in the following example:
1322*e4b17023SJohn Marino 
1323*e4b17023SJohn Marino    #define NUMBER 10
1324*e4b17023SJohn Marino    #pragma count (NUMBER)
1325*e4b17023SJohn Marino 
1326*e4b17023SJohn Marino    Name expansion is still disallowed.  */
1327*e4b17023SJohn Marino void
c_register_pragma_with_expansion_and_data(const char * space,const char * name,pragma_handler_2arg handler,void * data)1328*e4b17023SJohn Marino c_register_pragma_with_expansion_and_data (const char *space, const char *name,
1329*e4b17023SJohn Marino                                            pragma_handler_2arg handler,
1330*e4b17023SJohn Marino                                            void *data)
1331*e4b17023SJohn Marino {
1332*e4b17023SJohn Marino   internal_pragma_handler ihandler;
1333*e4b17023SJohn Marino 
1334*e4b17023SJohn Marino   ihandler.handler.handler_2arg = handler;
1335*e4b17023SJohn Marino   ihandler.extra_data = true;
1336*e4b17023SJohn Marino   ihandler.data = data;
1337*e4b17023SJohn Marino   c_register_pragma_1 (space, name, ihandler, true);
1338*e4b17023SJohn Marino }
1339*e4b17023SJohn Marino 
1340*e4b17023SJohn Marino void
c_invoke_pragma_handler(unsigned int id)1341*e4b17023SJohn Marino c_invoke_pragma_handler (unsigned int id)
1342*e4b17023SJohn Marino {
1343*e4b17023SJohn Marino   internal_pragma_handler *ihandler;
1344*e4b17023SJohn Marino   pragma_handler_1arg handler_1arg;
1345*e4b17023SJohn Marino   pragma_handler_2arg handler_2arg;
1346*e4b17023SJohn Marino 
1347*e4b17023SJohn Marino   id -= PRAGMA_FIRST_EXTERNAL;
1348*e4b17023SJohn Marino   ihandler = VEC_index (internal_pragma_handler, registered_pragmas, id);
1349*e4b17023SJohn Marino   if (ihandler->extra_data)
1350*e4b17023SJohn Marino     {
1351*e4b17023SJohn Marino       handler_2arg = ihandler->handler.handler_2arg;
1352*e4b17023SJohn Marino       handler_2arg (parse_in, ihandler->data);
1353*e4b17023SJohn Marino     }
1354*e4b17023SJohn Marino   else
1355*e4b17023SJohn Marino     {
1356*e4b17023SJohn Marino       handler_1arg = ihandler->handler.handler_1arg;
1357*e4b17023SJohn Marino       handler_1arg (parse_in);
1358*e4b17023SJohn Marino     }
1359*e4b17023SJohn Marino }
1360*e4b17023SJohn Marino 
1361*e4b17023SJohn Marino /* Set up front-end pragmas.  */
1362*e4b17023SJohn Marino void
init_pragma(void)1363*e4b17023SJohn Marino init_pragma (void)
1364*e4b17023SJohn Marino {
1365*e4b17023SJohn Marino   if (flag_openmp)
1366*e4b17023SJohn Marino     {
1367*e4b17023SJohn Marino       const int n_omp_pragmas = sizeof (omp_pragmas) / sizeof (*omp_pragmas);
1368*e4b17023SJohn Marino       int i;
1369*e4b17023SJohn Marino 
1370*e4b17023SJohn Marino       for (i = 0; i < n_omp_pragmas; ++i)
1371*e4b17023SJohn Marino 	cpp_register_deferred_pragma (parse_in, "omp", omp_pragmas[i].name,
1372*e4b17023SJohn Marino 				      omp_pragmas[i].id, true, true);
1373*e4b17023SJohn Marino     }
1374*e4b17023SJohn Marino 
1375*e4b17023SJohn Marino   if (!flag_preprocess_only)
1376*e4b17023SJohn Marino     cpp_register_deferred_pragma (parse_in, "GCC", "pch_preprocess",
1377*e4b17023SJohn Marino 				  PRAGMA_GCC_PCH_PREPROCESS, false, false);
1378*e4b17023SJohn Marino 
1379*e4b17023SJohn Marino #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
1380*e4b17023SJohn Marino   c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
1381*e4b17023SJohn Marino #else
1382*e4b17023SJohn Marino   c_register_pragma (0, "pack", handle_pragma_pack);
1383*e4b17023SJohn Marino #endif
1384*e4b17023SJohn Marino   c_register_pragma (0, "weak", handle_pragma_weak);
1385*e4b17023SJohn Marino   c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
1386*e4b17023SJohn Marino 
1387*e4b17023SJohn Marino   c_register_pragma ("GCC", "diagnostic", handle_pragma_diagnostic);
1388*e4b17023SJohn Marino   c_register_pragma ("GCC", "target", handle_pragma_target);
1389*e4b17023SJohn Marino   c_register_pragma ("GCC", "optimize", handle_pragma_optimize);
1390*e4b17023SJohn Marino   c_register_pragma ("GCC", "push_options", handle_pragma_push_options);
1391*e4b17023SJohn Marino   c_register_pragma ("GCC", "pop_options", handle_pragma_pop_options);
1392*e4b17023SJohn Marino   c_register_pragma ("GCC", "reset_options", handle_pragma_reset_options);
1393*e4b17023SJohn Marino 
1394*e4b17023SJohn Marino   c_register_pragma ("STDC", "FLOAT_CONST_DECIMAL64",
1395*e4b17023SJohn Marino 		     handle_pragma_float_const_decimal64);
1396*e4b17023SJohn Marino 
1397*e4b17023SJohn Marino   c_register_pragma_with_expansion (0, "redefine_extname",
1398*e4b17023SJohn Marino 				    handle_pragma_redefine_extname);
1399*e4b17023SJohn Marino   c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
1400*e4b17023SJohn Marino 
1401*e4b17023SJohn Marino   c_register_pragma_with_expansion (0, "message", handle_pragma_message);
1402*e4b17023SJohn Marino 
1403*e4b17023SJohn Marino #ifdef REGISTER_TARGET_PRAGMAS
1404*e4b17023SJohn Marino   REGISTER_TARGET_PRAGMAS ();
1405*e4b17023SJohn Marino #endif
1406*e4b17023SJohn Marino 
1407*e4b17023SJohn Marino   /* Allow plugins to register their own pragmas. */
1408*e4b17023SJohn Marino   invoke_plugin_callbacks (PLUGIN_PRAGMAS, NULL);
1409*e4b17023SJohn Marino }
1410*e4b17023SJohn Marino 
1411*e4b17023SJohn Marino #include "gt-c-family-c-pragma.h"
1412