00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "function.h"
00029 #include "cpplib.h"
00030 #include "c-pragma.h"
00031 #include "flags.h"
00032 #include "toplev.h"
00033 #include "ggc.h"
00034 #include "c-common.h"
00035 #include "output.h"
00036 #include "tm_p.h"
00037 #include "target.h"
00038
00039 #define GCC_BAD(gmsgid) do { warning (gmsgid); return; } while (0)
00040 #define GCC_BAD2(gmsgid, arg) \
00041 do { warning (gmsgid, arg); return; } while (0)
00042
00043 typedef struct align_stack GTY(())
00044 {
00045 int alignment;
00046 tree id;
00047 struct align_stack * prev;
00048 } align_stack;
00049
00050 static GTY(()) struct align_stack * alignment_stack;
00051
00052 #ifdef HANDLE_PRAGMA_PACK
00053 static void handle_pragma_pack (cpp_reader *);
00054
00055 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
00056
00057
00058
00059
00060
00061 static int default_alignment;
00062 #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = *(alignment_stack == NULL \
00063 ? &default_alignment \
00064 : &alignment_stack->alignment) = (ALIGN))
00065
00066 static void push_alignment (int, tree);
00067 static void pop_alignment (tree);
00068
00069
00070 static void
00071 push_alignment (int alignment, tree id)
00072 {
00073 align_stack * entry;
00074
00075 entry = ggc_alloc (sizeof (* entry));
00076
00077 entry->alignment = alignment;
00078 entry->id = id;
00079 entry->prev = alignment_stack;
00080
00081
00082
00083
00084 if (alignment_stack == NULL)
00085 default_alignment = maximum_field_alignment;
00086
00087 alignment_stack = entry;
00088
00089 maximum_field_alignment = alignment;
00090 }
00091
00092
00093 static void
00094 pop_alignment (tree id)
00095 {
00096 align_stack * entry;
00097
00098 if (alignment_stack == NULL)
00099 GCC_BAD ("#pragma pack (pop) encountered without matching #pragma pack (push)");
00100
00101
00102
00103 if (id)
00104 {
00105 for (entry = alignment_stack; entry; entry = entry->prev)
00106 if (entry->id == id)
00107 {
00108 alignment_stack = entry;
00109 break;
00110 }
00111 if (entry == NULL)
00112 warning ("\
00113 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s)"
00114 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
00115 }
00116
00117 entry = alignment_stack->prev;
00118
00119 maximum_field_alignment = entry ? entry->alignment : default_alignment;
00120
00121 alignment_stack = entry;
00122 }
00123 #else
00124 #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
00125 #define push_alignment(ID, N) \
00126 GCC_BAD ("#pragma pack(push[, id], <n>) is not supported on this target")
00127 #define pop_alignment(ID) \
00128 GCC_BAD ("#pragma pack(pop[, id], <n>) is not supported on this target")
00129 #endif
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140 static void
00141 handle_pragma_pack (cpp_reader * ARG_UNUSED (dummy))
00142 {
00143 tree x, id = 0;
00144 int align = -1;
00145 enum cpp_ttype token;
00146 enum { set, push, pop } action;
00147
00148 if (c_lex (&x) != CPP_OPEN_PAREN)
00149 GCC_BAD ("missing %<(%> after %<#pragma pack%> - ignored");
00150
00151 token = c_lex (&x);
00152 if (token == CPP_CLOSE_PAREN)
00153 {
00154 action = set;
00155 align = initial_max_fld_align;
00156 }
00157 else if (token == CPP_NUMBER)
00158 {
00159 align = TREE_INT_CST_LOW (x);
00160 action = set;
00161 if (c_lex (&x) != CPP_CLOSE_PAREN)
00162 GCC_BAD ("malformed %<#pragma pack%> - ignored");
00163 }
00164 else if (token == CPP_NAME)
00165 {
00166 #define GCC_BAD_ACTION do { if (action != pop) \
00167 GCC_BAD ("malformed %<#pragma pack(push[, id][, <n>])%> - ignored"); \
00168 else \
00169 GCC_BAD ("malformed %<#pragma pack(pop[, id])%> - ignored"); \
00170 } while (0)
00171
00172 const char *op = IDENTIFIER_POINTER (x);
00173 if (!strcmp (op, "push"))
00174 action = push;
00175 else if (!strcmp (op, "pop"))
00176 action = pop;
00177 else
00178 GCC_BAD2 ("unknown action %qs for %<#pragma pack%> - ignored", op);
00179
00180 while ((token = c_lex (&x)) == CPP_COMMA)
00181 {
00182 token = c_lex (&x);
00183 if (token == CPP_NAME && id == 0)
00184 {
00185 id = x;
00186 }
00187 else if (token == CPP_NUMBER && action == push && align == -1)
00188 {
00189 align = TREE_INT_CST_LOW (x);
00190 if (align == -1)
00191 action = set;
00192 }
00193 else
00194 GCC_BAD_ACTION;
00195 }
00196
00197 if (token != CPP_CLOSE_PAREN)
00198 GCC_BAD_ACTION;
00199 #undef GCC_BAD_ACTION
00200 }
00201 else
00202 GCC_BAD ("malformed %<#pragma pack%> - ignored");
00203
00204 if (c_lex (&x) != CPP_EOF)
00205 warning ("junk at end of %<#pragma pack%>");
00206
00207 if (flag_pack_struct)
00208 GCC_BAD ("#pragma pack has no effect with -fpack-struct - ignored");
00209
00210 if (action != pop)
00211 switch (align)
00212 {
00213 case 0:
00214 case 1:
00215 case 2:
00216 case 4:
00217 case 8:
00218 case 16:
00219 align *= BITS_PER_UNIT;
00220 break;
00221 case -1:
00222 if (action == push)
00223 {
00224 align = maximum_field_alignment;
00225 break;
00226 }
00227 default:
00228 GCC_BAD2 ("alignment must be a small power of two, not %d", align);
00229 }
00230
00231 switch (action)
00232 {
00233 case set: SET_GLOBAL_ALIGNMENT (align); break;
00234 case push: push_alignment (align, id); break;
00235 case pop: pop_alignment (id); break;
00236 }
00237 }
00238 #endif
00239
00240 static GTY(()) tree pending_weaks;
00241
00242 #ifdef HANDLE_PRAGMA_WEAK
00243 static void apply_pragma_weak (tree, tree);
00244 static void handle_pragma_weak (cpp_reader *);
00245
00246 static void
00247 apply_pragma_weak (tree decl, tree value)
00248 {
00249 if (value)
00250 {
00251 value = build_string (IDENTIFIER_LENGTH (value),
00252 IDENTIFIER_POINTER (value));
00253 decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
00254 build_tree_list (NULL, value)),
00255 0);
00256 }
00257
00258 if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
00259 && !DECL_WEAK (decl)
00260 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
00261 warning ("%Japplying #pragma weak %qD after first use results "
00262 "in unspecified behavior", decl, decl);
00263
00264 declare_weak (decl);
00265 }
00266
00267 void
00268 maybe_apply_pragma_weak (tree decl)
00269 {
00270 tree *p, t, id;
00271
00272
00273
00274
00275 if (!pending_weaks)
00276 return;
00277
00278
00279 if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
00280 return;
00281
00282
00283
00284 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
00285 return;
00286
00287 id = DECL_ASSEMBLER_NAME (decl);
00288
00289 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t))
00290 if (id == TREE_PURPOSE (t))
00291 {
00292 apply_pragma_weak (decl, TREE_VALUE (t));
00293 *p = TREE_CHAIN (t);
00294 break;
00295 }
00296 }
00297
00298
00299
00300 void
00301 maybe_apply_pending_pragma_weaks (void)
00302 {
00303 tree *p, t, alias_id, id, decl, *next;
00304
00305 for (p = &pending_weaks; (t = *p) ; p = next)
00306 {
00307 next = &TREE_CHAIN (t);
00308 alias_id = TREE_PURPOSE (t);
00309 id = TREE_VALUE (t);
00310
00311 if (TREE_VALUE (t) == NULL)
00312 continue;
00313
00314 decl = build_decl (FUNCTION_DECL, alias_id, default_function_type);
00315
00316 DECL_ARTIFICIAL (decl) = 1;
00317 TREE_PUBLIC (decl) = 1;
00318 DECL_EXTERNAL (decl) = 1;
00319 DECL_WEAK (decl) = 1;
00320
00321 assemble_alias (decl, id);
00322 }
00323 }
00324
00325
00326 static void
00327 handle_pragma_weak (cpp_reader * ARG_UNUSED (dummy))
00328 {
00329 tree name, value, x, decl;
00330 enum cpp_ttype t;
00331
00332 value = 0;
00333
00334 if (c_lex (&name) != CPP_NAME)
00335 GCC_BAD ("malformed #pragma weak, ignored");
00336 t = c_lex (&x);
00337 if (t == CPP_EQ)
00338 {
00339 if (c_lex (&value) != CPP_NAME)
00340 GCC_BAD ("malformed #pragma weak, ignored");
00341 t = c_lex (&x);
00342 }
00343 if (t != CPP_EOF)
00344 warning ("junk at end of #pragma weak");
00345
00346 decl = identifier_global_value (name);
00347 if (decl && DECL_P (decl))
00348 {
00349 apply_pragma_weak (decl, value);
00350 if (value)
00351 assemble_alias (decl, value);
00352 }
00353 else
00354 pending_weaks = tree_cons (name, value, pending_weaks);
00355 }
00356 #else
00357 void
00358 maybe_apply_pragma_weak (tree ARG_UNUSED (decl))
00359 {
00360 }
00361
00362 void
00363 maybe_apply_pending_pragma_weaks (void)
00364 {
00365 }
00366 #endif
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 static GTY(()) tree pending_redefine_extname;
00401
00402 static void handle_pragma_redefine_extname (cpp_reader *);
00403
00404
00405 static void
00406 handle_pragma_redefine_extname (cpp_reader * ARG_UNUSED (dummy))
00407 {
00408 tree oldname, newname, decl, x;
00409 enum cpp_ttype t;
00410
00411 if (c_lex (&oldname) != CPP_NAME)
00412 GCC_BAD ("malformed #pragma redefine_extname, ignored");
00413 if (c_lex (&newname) != CPP_NAME)
00414 GCC_BAD ("malformed #pragma redefine_extname, ignored");
00415 t = c_lex (&x);
00416 if (t != CPP_EOF)
00417 warning ("junk at end of #pragma redefine_extname");
00418
00419 if (!flag_mudflap && !targetm.handle_pragma_redefine_extname)
00420 {
00421 if (warn_unknown_pragmas > in_system_header)
00422 warning ("#pragma redefine_extname not supported on this target");
00423 return;
00424 }
00425
00426 decl = identifier_global_value (oldname);
00427 if (decl
00428 && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
00429 && (TREE_CODE (decl) == FUNCTION_DECL
00430 || TREE_CODE (decl) == VAR_DECL)
00431 && has_c_linkage (decl))
00432 {
00433 if (DECL_ASSEMBLER_NAME_SET_P (decl))
00434 {
00435 const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
00436 name = targetm.strip_name_encoding (name);
00437
00438 if (strcmp (name, IDENTIFIER_POINTER (newname)))
00439 warning ("#pragma redefine_extname ignored due to conflict with "
00440 "previous rename");
00441 }
00442 else
00443 change_decl_assembler_name (decl, newname);
00444 }
00445 else
00446
00447
00448
00449
00450
00451 add_to_renaming_pragma_list (oldname, newname);
00452 }
00453
00454
00455 void
00456 add_to_renaming_pragma_list (tree oldname, tree newname)
00457 {
00458 tree previous = purpose_member (oldname, pending_redefine_extname);
00459 if (previous)
00460 {
00461 if (TREE_VALUE (previous) != newname)
00462 warning ("#pragma redefine_extname ignored due to conflict with "
00463 "previous #pragma redefine_extname");
00464 return;
00465 }
00466
00467 pending_redefine_extname
00468 = tree_cons (oldname, newname, pending_redefine_extname);
00469 }
00470
00471 static GTY(()) tree pragma_extern_prefix;
00472
00473
00474 static void
00475 handle_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
00476 {
00477 tree prefix, x;
00478 enum cpp_ttype t;
00479
00480 if (c_lex (&prefix) != CPP_STRING)
00481 GCC_BAD ("malformed #pragma extern_prefix, ignored");
00482 t = c_lex (&x);
00483 if (t != CPP_EOF)
00484 warning ("junk at end of #pragma extern_prefix");
00485
00486 if (targetm.handle_pragma_extern_prefix)
00487
00488 pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
00489 else if (warn_unknown_pragmas > in_system_header)
00490 warning ("#pragma extern_prefix not supported on this target");
00491 }
00492
00493
00494
00495
00496 tree
00497 maybe_apply_renaming_pragma (tree decl, tree asmname)
00498 {
00499 tree *p, t;
00500
00501
00502
00503 if ((TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
00504 || (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
00505 || !has_c_linkage (decl))
00506 return asmname;
00507
00508
00509
00510 if (DECL_ASSEMBLER_NAME_SET_P (decl))
00511 {
00512 const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
00513 oldname = targetm.strip_name_encoding (oldname);
00514
00515 if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname))
00516 warning ("asm declaration ignored due to "
00517 "conflict with previous rename");
00518
00519
00520 for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t))
00521 if (DECL_NAME (decl) == TREE_PURPOSE (t))
00522 {
00523
00524 if (strcmp (IDENTIFIER_POINTER (TREE_VALUE (t)), oldname))
00525 warning ("#pragma redefine_extname ignored due to "
00526 "conflict with previous rename");
00527
00528 *p = TREE_CHAIN (t);
00529 break;
00530 }
00531 return 0;
00532 }
00533
00534
00535 for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t))
00536 if (DECL_NAME (decl) == TREE_PURPOSE (t))
00537 {
00538 tree newname = TREE_VALUE (t);
00539 *p = TREE_CHAIN (t);
00540
00541
00542
00543 if (asmname)
00544 {
00545 if (strcmp (TREE_STRING_POINTER (asmname),
00546 IDENTIFIER_POINTER (newname)) != 0)
00547 warning ("#pragma redefine_extname ignored due to "
00548 "conflict with __asm__ declaration");
00549 return asmname;
00550 }
00551
00552
00553
00554 return build_string (IDENTIFIER_LENGTH (newname),
00555 IDENTIFIER_POINTER (newname));
00556 }
00557
00558
00559 if (asmname)
00560 return asmname;
00561
00562
00563 if (pragma_extern_prefix)
00564 {
00565 const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix);
00566 size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1;
00567
00568 const char *id = IDENTIFIER_POINTER (DECL_NAME (decl));
00569 size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl));
00570
00571 char *newname = (char *) alloca (plen + ilen + 1);
00572
00573 memcpy (newname, prefix, plen);
00574 memcpy (newname + plen, id, ilen + 1);
00575
00576 return build_string (plen + ilen, newname);
00577 }
00578
00579
00580 return 0;
00581 }
00582
00583
00584 #ifdef HANDLE_PRAGMA_VISIBILITY
00585 static void handle_pragma_visibility (cpp_reader *);
00586
00587
00588
00589 static void
00590 handle_pragma_visibility (cpp_reader *dummy ATTRIBUTE_UNUSED)
00591 {
00592 static int visstack [16], visidx;
00593 tree x;
00594 enum cpp_ttype token;
00595 enum { bad, push, pop } action = bad;
00596
00597 token = c_lex (&x);
00598 if (token == CPP_NAME)
00599 {
00600 const char *op = IDENTIFIER_POINTER (x);
00601 if (!strcmp (op, "push"))
00602 action = push;
00603 else if (!strcmp (op, "pop"))
00604 action = pop;
00605 }
00606 if (bad == action)
00607 GCC_BAD ("#pragma GCC visibility must be followed by push or pop");
00608 else
00609 {
00610 if (pop == action)
00611 {
00612 if (!visidx)
00613 {
00614 GCC_BAD ("No matching push for %<#pragma GCC visibility pop%>");
00615 }
00616 else
00617 {
00618 default_visibility = visstack[--visidx];
00619 visibility_options.inpragma = (visidx>0);
00620 }
00621 }
00622 else
00623 {
00624 if (c_lex (&x) != CPP_OPEN_PAREN)
00625 GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
00626 token = c_lex (&x);
00627 if (token != CPP_NAME)
00628 {
00629 GCC_BAD ("malformed #pragma GCC visibility push");
00630 }
00631 else if (visidx >= 16)
00632 {
00633 GCC_BAD ("No more than sixteen #pragma GCC visibility pushes allowed at once");
00634 }
00635 else
00636 {
00637 const char *str = IDENTIFIER_POINTER (x);
00638 visstack[visidx++] = default_visibility;
00639 if (!strcmp (str, "default"))
00640 default_visibility = VISIBILITY_DEFAULT;
00641 else if (!strcmp (str, "internal"))
00642 default_visibility = VISIBILITY_INTERNAL;
00643 else if (!strcmp (str, "hidden"))
00644 default_visibility = VISIBILITY_HIDDEN;
00645 else if (!strcmp (str, "protected"))
00646 default_visibility = VISIBILITY_PROTECTED;
00647 else
00648 {
00649 GCC_BAD ("#pragma GCC visibility push() must specify default, internal, hidden or protected");
00650 }
00651 visibility_options.inpragma = 1;
00652 }
00653 if (c_lex (&x) != CPP_CLOSE_PAREN)
00654 GCC_BAD ("missing %<(%> after %<#pragma GCC visibility push%> - ignored");
00655 }
00656 }
00657 if (c_lex (&x) != CPP_EOF)
00658 warning ("junk at end of %<#pragma GCC visibility%>");
00659 }
00660
00661 #endif
00662
00663
00664
00665 void
00666 c_register_pragma (const char *space, const char *name,
00667 void (*handler) (struct cpp_reader *))
00668 {
00669 cpp_register_pragma (parse_in, space, name, handler, 0);
00670 }
00671
00672 void
00673 c_register_pragma_with_expansion (const char *space, const char *name,
00674 void (*handler) (struct cpp_reader *))
00675 {
00676 cpp_register_pragma (parse_in, space, name, handler, 1);
00677 }
00678
00679
00680 void
00681 init_pragma (void)
00682 {
00683 #ifdef HANDLE_PRAGMA_PACK
00684 #ifdef HANDLE_PRAGMA_PACK_WITH_EXPANSION
00685 c_register_pragma_with_expansion (0, "pack", handle_pragma_pack);
00686 #else
00687 c_register_pragma (0, "pack", handle_pragma_pack);
00688 #endif
00689 #endif
00690 #ifdef HANDLE_PRAGMA_WEAK
00691 c_register_pragma (0, "weak", handle_pragma_weak);
00692 #endif
00693 #ifdef HANDLE_PRAGMA_VISIBILITY
00694 c_register_pragma ("GCC", "visibility", handle_pragma_visibility);
00695 #endif
00696
00697 c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname);
00698 c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix);
00699
00700 c_register_pragma ("GCC", "pch_preprocess", c_common_pch_pragma);
00701
00702 #ifdef REGISTER_TARGET_PRAGMAS
00703 REGISTER_TARGET_PRAGMAS ();
00704 #endif
00705 }
00706
00707 #include "gt-c-pragma.h"