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