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 "rtl.h"
00025 #include "tree.h"
00026 #include "function.h"
00027 #include "cpplib.h"
00028 #include "c-pragma.h"
00029 #include "flags.h"
00030 #include "toplev.h"
00031 #include "ggc.h"
00032 #include "c-common.h"
00033 #include "output.h"
00034 #include "tm_p.h"
00035
00036 #define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
00037 #define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
00038
00039 typedef struct align_stack GTY(())
00040 {
00041 int alignment;
00042 unsigned int num_pushes;
00043 tree id;
00044 struct align_stack * prev;
00045 } align_stack;
00046
00047 static GTY(()) struct align_stack * alignment_stack;
00048
00049 #ifdef HANDLE_PRAGMA_PACK
00050 static void handle_pragma_pack PARAMS ((cpp_reader *));
00051
00052 #ifdef HANDLE_PRAGMA_PACK_PUSH_POP
00053
00054
00055
00056
00057
00058 static int default_alignment;
00059 #define SET_GLOBAL_ALIGNMENT(ALIGN) \
00060 (default_alignment = maximum_field_alignment = (ALIGN))
00061
00062 static void push_alignment PARAMS ((int, tree));
00063 static void pop_alignment PARAMS ((tree));
00064
00065
00066 static void
00067 push_alignment (alignment, id)
00068 int alignment;
00069 tree id;
00070 {
00071 if (alignment_stack == NULL
00072 || alignment_stack->alignment != alignment
00073 || id != NULL_TREE)
00074 {
00075 align_stack * entry;
00076
00077 entry = (align_stack *) ggc_alloc (sizeof (* entry));
00078
00079 entry->alignment = alignment;
00080 entry->num_pushes = 1;
00081 entry->id = id;
00082 entry->prev = alignment_stack;
00083
00084
00085
00086
00087 if (alignment_stack == NULL)
00088 default_alignment = maximum_field_alignment;
00089
00090 alignment_stack = entry;
00091
00092 maximum_field_alignment = alignment;
00093 }
00094 else
00095 alignment_stack->num_pushes ++;
00096 }
00097
00098
00099 static void
00100 pop_alignment (id)
00101 tree id;
00102 {
00103 align_stack * entry;
00104
00105 if (alignment_stack == NULL)
00106 {
00107 warning ("\
00108 #pragma pack (pop) encountered without matching #pragma pack (push, <n>)"
00109 );
00110 return;
00111 }
00112
00113
00114
00115 if (id)
00116 {
00117 for (entry = alignment_stack; entry; entry = entry->prev)
00118 if (entry->id == id)
00119 {
00120 entry->num_pushes = 1;
00121 alignment_stack = entry;
00122 break;
00123 }
00124 if (entry == NULL)
00125 warning ("\
00126 #pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)"
00127 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id));
00128 }
00129
00130 if (-- alignment_stack->num_pushes == 0)
00131 {
00132 entry = alignment_stack->prev;
00133
00134 if (entry == NULL)
00135 maximum_field_alignment = default_alignment;
00136 else
00137 maximum_field_alignment = entry->alignment;
00138
00139 alignment_stack = entry;
00140 }
00141 }
00142 #else
00143 #define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN))
00144 #define push_alignment(ID, N) \
00145 GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target")
00146 #define pop_alignment(ID) \
00147 GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target")
00148 #endif
00149
00150
00151
00152
00153
00154
00155
00156
00157 static void
00158 handle_pragma_pack (dummy)
00159 cpp_reader *dummy ATTRIBUTE_UNUSED;
00160 {
00161 tree x, id = 0;
00162 int align = -1;
00163 enum cpp_ttype token;
00164 enum { set, push, pop } action;
00165
00166 if (c_lex (&x) != CPP_OPEN_PAREN)
00167 GCC_BAD ("missing '(' after '#pragma pack' - ignored");
00168
00169 token = c_lex (&x);
00170 if (token == CPP_CLOSE_PAREN)
00171 {
00172 action = set;
00173 align = 0;
00174 }
00175 else if (token == CPP_NUMBER)
00176 {
00177 align = TREE_INT_CST_LOW (x);
00178 action = set;
00179 if (c_lex (&x) != CPP_CLOSE_PAREN)
00180 GCC_BAD ("malformed '#pragma pack' - ignored");
00181 }
00182 else if (token == CPP_NAME)
00183 {
00184 #define GCC_BAD_ACTION do { if (action == push) \
00185 GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \
00186 else \
00187 GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \
00188 } while (0)
00189
00190 const char *op = IDENTIFIER_POINTER (x);
00191 if (!strcmp (op, "push"))
00192 action = push;
00193 else if (!strcmp (op, "pop"))
00194 action = pop;
00195 else
00196 GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op);
00197
00198 token = c_lex (&x);
00199 if (token != CPP_COMMA && action == push)
00200 GCC_BAD_ACTION;
00201
00202 if (token == CPP_COMMA)
00203 {
00204 token = c_lex (&x);
00205 if (token == CPP_NAME)
00206 {
00207 id = x;
00208 if (action == push && c_lex (&x) != CPP_COMMA)
00209 GCC_BAD_ACTION;
00210 token = c_lex (&x);
00211 }
00212
00213 if (action == push)
00214 {
00215 if (token == CPP_NUMBER)
00216 {
00217 align = TREE_INT_CST_LOW (x);
00218 token = c_lex (&x);
00219 }
00220 else
00221 GCC_BAD_ACTION;
00222 }
00223 }
00224
00225 if (token != CPP_CLOSE_PAREN)
00226 GCC_BAD_ACTION;
00227 #undef GCC_BAD_ACTION
00228 }
00229 else
00230 GCC_BAD ("malformed '#pragma pack' - ignored");
00231
00232 if (c_lex (&x) != CPP_EOF)
00233 warning ("junk at end of '#pragma pack'");
00234
00235 if (action != pop)
00236 switch (align)
00237 {
00238 case 0:
00239 case 1:
00240 case 2:
00241 case 4:
00242 case 8:
00243 case 16:
00244 align *= BITS_PER_UNIT;
00245 break;
00246 default:
00247 GCC_BAD2 ("alignment must be a small power of two, not %d", align);
00248 }
00249
00250 switch (action)
00251 {
00252 case set: SET_GLOBAL_ALIGNMENT (align); break;
00253 case push: push_alignment (align, id); break;
00254 case pop: pop_alignment (id); break;
00255 }
00256 }
00257 #endif
00258
00259 static GTY(()) tree pending_weaks;
00260
00261 #ifdef HANDLE_PRAGMA_WEAK
00262 static void apply_pragma_weak PARAMS ((tree, tree));
00263 static void handle_pragma_weak PARAMS ((cpp_reader *));
00264
00265 static void
00266 apply_pragma_weak (decl, value)
00267 tree decl, value;
00268 {
00269 if (value)
00270 {
00271 value = build_string (IDENTIFIER_LENGTH (value),
00272 IDENTIFIER_POINTER (value));
00273 decl_attributes (&decl, build_tree_list (get_identifier ("alias"),
00274 build_tree_list (NULL, value)),
00275 0);
00276 }
00277
00278 if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl)
00279 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
00280 warning_with_decl (decl, "applying #pragma weak `%s' after first use results in unspecified behavior");
00281
00282 declare_weak (decl);
00283 }
00284
00285 void
00286 maybe_apply_pragma_weak (decl)
00287 tree decl;
00288 {
00289 tree *p, t, id;
00290
00291
00292
00293
00294 if (!pending_weaks)
00295 return;
00296
00297
00298 if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl))
00299 return;
00300
00301
00302
00303 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
00304 return;
00305
00306 id = DECL_ASSEMBLER_NAME (decl);
00307
00308 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t))
00309 if (id == TREE_PURPOSE (t))
00310 {
00311 apply_pragma_weak (decl, TREE_VALUE (t));
00312 *p = TREE_CHAIN (t);
00313 break;
00314 }
00315 }
00316
00317
00318 static void
00319 handle_pragma_weak (dummy)
00320 cpp_reader *dummy ATTRIBUTE_UNUSED;
00321 {
00322 tree name, value, x, decl;
00323 enum cpp_ttype t;
00324
00325 value = 0;
00326
00327 if (c_lex (&name) != CPP_NAME)
00328 GCC_BAD ("malformed #pragma weak, ignored");
00329 t = c_lex (&x);
00330 if (t == CPP_EQ)
00331 {
00332 if (c_lex (&value) != CPP_NAME)
00333 GCC_BAD ("malformed #pragma weak, ignored");
00334 t = c_lex (&x);
00335 }
00336 if (t != CPP_EOF)
00337 warning ("junk at end of #pragma weak");
00338
00339 decl = identifier_global_value (name);
00340 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
00341 {
00342 apply_pragma_weak (decl, value);
00343 if (value)
00344 assemble_alias (decl, value);
00345 }
00346 else
00347 pending_weaks = tree_cons (name, value, pending_weaks);
00348 }
00349 #else
00350 void
00351 maybe_apply_pragma_weak (decl)
00352 tree decl ATTRIBUTE_UNUSED;
00353 {
00354 }
00355 #endif
00356
00357 static GTY(()) tree pending_redefine_extname;
00358
00359 #ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
00360 static void handle_pragma_redefine_extname PARAMS ((cpp_reader *));
00361
00362
00363 static void
00364 handle_pragma_redefine_extname (dummy)
00365 cpp_reader *dummy ATTRIBUTE_UNUSED;
00366 {
00367 tree oldname, newname, decl, x;
00368 enum cpp_ttype t;
00369
00370 if (c_lex (&oldname) != CPP_NAME)
00371 {
00372 warning ("malformed #pragma redefine_extname, ignored");
00373 return;
00374 }
00375 if (c_lex (&newname) != CPP_NAME)
00376 {
00377 warning ("malformed #pragma redefine_extname, ignored");
00378 return;
00379 }
00380 t = c_lex (&x);
00381 if (t != CPP_EOF)
00382 warning ("junk at end of #pragma redefine_extname");
00383
00384 decl = identifier_global_value (oldname);
00385 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
00386 {
00387 if (DECL_ASSEMBLER_NAME_SET_P (decl)
00388 && DECL_ASSEMBLER_NAME (decl) != newname)
00389 warning ("#pragma redefine_extname conflicts with declaration");
00390 SET_DECL_ASSEMBLER_NAME (decl, newname);
00391 }
00392 else
00393 add_to_renaming_pragma_list(oldname, newname);
00394 }
00395 #endif
00396
00397 void
00398 add_to_renaming_pragma_list (oldname, newname)
00399 tree oldname, newname;
00400 {
00401 pending_redefine_extname
00402 = tree_cons (oldname, newname, pending_redefine_extname);
00403 }
00404
00405 static GTY(()) tree pragma_extern_prefix;
00406
00407 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
00408 static void handle_pragma_extern_prefix PARAMS ((cpp_reader *));
00409
00410
00411 static void
00412 handle_pragma_extern_prefix (dummy)
00413 cpp_reader *dummy ATTRIBUTE_UNUSED;
00414 {
00415 tree prefix, x;
00416 enum cpp_ttype t;
00417
00418 if (c_lex (&prefix) != CPP_STRING)
00419 {
00420 warning ("malformed #pragma extern_prefix, ignored");
00421 return;
00422 }
00423 t = c_lex (&x);
00424 if (t != CPP_EOF)
00425 warning ("junk at end of #pragma extern_prefix");
00426
00427
00428 pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
00429 }
00430 #endif
00431
00432
00433
00434
00435 tree
00436 maybe_apply_renaming_pragma (decl, asmname)
00437 tree decl, asmname;
00438 {
00439 tree oldname;
00440
00441
00442 if (TREE_CODE (decl) == FUNCTION_DECL
00443 || (TREE_CODE (decl) == VAR_DECL
00444 && (TREE_STATIC (decl)
00445 || DECL_EXTERNAL (decl)
00446 || TREE_PUBLIC (decl))))
00447 oldname = DECL_ASSEMBLER_NAME (decl);
00448 else
00449 return asmname;
00450
00451
00452
00453 if (IDENTIFIER_POINTER (oldname)[0] == '*')
00454 {
00455 const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1;
00456 if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0)
00457 warning ("asm declaration conflicts with previous rename");
00458 asmname = build_string (strlen (oldasmname), oldasmname);
00459 }
00460
00461 {
00462 tree *p, t;
00463
00464 for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t))
00465 if (oldname == TREE_PURPOSE (t))
00466 {
00467 const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t));
00468
00469 if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0)
00470 warning ("#pragma redefine_extname conflicts with declaration");
00471 *p = TREE_CHAIN (t);
00472
00473 return build_string (strlen (newname), newname);
00474 }
00475 }
00476
00477 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
00478 if (pragma_extern_prefix && !asmname)
00479 {
00480 char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix),
00481 IDENTIFIER_POINTER (oldname), NULL);
00482 asmname = build_string (strlen (x), x);
00483 free (x);
00484 return asmname;
00485 }
00486 #endif
00487
00488 return asmname;
00489 }
00490
00491 void
00492 init_pragma ()
00493 {
00494 #ifdef HANDLE_PRAGMA_PACK
00495 cpp_register_pragma (parse_in, 0, "pack", handle_pragma_pack);
00496 #endif
00497 #ifdef HANDLE_PRAGMA_WEAK
00498 cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak);
00499 #endif
00500 #ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
00501 cpp_register_pragma (parse_in, 0, "redefine_extname",
00502 handle_pragma_redefine_extname);
00503 #endif
00504 #ifdef HANDLE_PRAGMA_EXTERN_PREFIX
00505 cpp_register_pragma (parse_in, 0, "extern_prefix",
00506 handle_pragma_extern_prefix);
00507 #endif
00508
00509 #ifdef REGISTER_TARGET_PRAGMAS
00510 REGISTER_TARGET_PRAGMAS (parse_in);
00511 #endif
00512 }
00513
00514 #include "gt-c-pragma.h"