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