c-pragma.c revision 132718
1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. 2 Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 3 Free Software Foundation, Inc. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it under 8the terms of the GNU General Public License as published by the Free 9Software Foundation; either version 2, or (at your option) any later 10version. 11 12GCC is distributed in the hope that it will be useful, but WITHOUT ANY 13WARRANTY; without even the implied warranty of MERCHANTABILITY or 14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING. If not, write to the Free 19Software Foundation, 59 Temple Place - Suite 330, Boston, MA 2002111-1307, USA. */ 21 22#include "config.h" 23#include "system.h" 24#include "coretypes.h" 25#include "tm.h" 26#include "rtl.h" 27#include "tree.h" 28#include "function.h" 29#include "cpplib.h" 30#include "c-pragma.h" 31#include "flags.h" 32#include "toplev.h" 33#include "ggc.h" 34#include "c-common.h" 35#include "output.h" 36#include "tm_p.h" 37 38#define GCC_BAD(msgid) do { warning (msgid); return; } while (0) 39#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) 40 41typedef struct align_stack GTY(()) 42{ 43 int alignment; 44 unsigned int num_pushes; 45 tree id; 46 struct align_stack * prev; 47} align_stack; 48 49static GTY(()) struct align_stack * alignment_stack; 50 51#ifdef HANDLE_PRAGMA_PACK 52static void handle_pragma_pack (cpp_reader *); 53 54#ifdef HANDLE_PRAGMA_PACK_PUSH_POP 55/* If we have a "global" #pragma pack(<n>) in effect when the first 56 #pragma pack(push,<n>) is encountered, this stores the value of 57 maximum_field_alignment in effect. When the final pop_alignment() 58 happens, we restore the value to this, not to a value of 0 for 59 maximum_field_alignment. Value is in bits. */ 60static int default_alignment; 61#define SET_GLOBAL_ALIGNMENT(ALIGN) \ 62 (default_alignment = maximum_field_alignment = (ALIGN)) 63 64static void push_alignment (int, tree); 65static void pop_alignment (tree); 66 67/* Push an alignment value onto the stack. */ 68static void 69push_alignment (int alignment, tree id) 70{ 71 if (alignment_stack == NULL 72 || alignment_stack->alignment != alignment 73 || id != NULL_TREE) 74 { 75 align_stack * entry; 76 77 entry = ggc_alloc (sizeof (* entry)); 78 79 entry->alignment = alignment; 80 entry->num_pushes = 1; 81 entry->id = id; 82 entry->prev = alignment_stack; 83 84 /* The current value of maximum_field_alignment is not necessarily 85 0 since there may be a #pragma pack(<n>) in effect; remember it 86 so that we can restore it after the final #pragma pop(). */ 87 if (alignment_stack == NULL) 88 default_alignment = maximum_field_alignment; 89 90 alignment_stack = entry; 91 92 maximum_field_alignment = alignment; 93 } 94 else 95 alignment_stack->num_pushes ++; 96} 97 98/* Undo a push of an alignment onto the stack. */ 99static void 100pop_alignment (tree id) 101{ 102 align_stack * entry; 103 104 if (alignment_stack == NULL) 105 { 106 warning ("\ 107#pragma pack (pop) encountered without matching #pragma pack (push, <n>)" 108 ); 109 return; 110 } 111 112 /* If we got an identifier, strip away everything above the target 113 entry so that the next step will restore the state just below it. */ 114 if (id) 115 { 116 for (entry = alignment_stack; entry; entry = entry->prev) 117 if (entry->id == id) 118 { 119 entry->num_pushes = 1; 120 alignment_stack = entry; 121 break; 122 } 123 if (entry == NULL) 124 warning ("\ 125#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)" 126 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id)); 127 } 128 129 if (-- alignment_stack->num_pushes == 0) 130 { 131 entry = alignment_stack->prev; 132 133 if (entry == NULL) 134 maximum_field_alignment = default_alignment; 135 else 136 maximum_field_alignment = entry->alignment; 137 138 alignment_stack = entry; 139 } 140} 141#else /* not HANDLE_PRAGMA_PACK_PUSH_POP */ 142#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN)) 143#define push_alignment(ID, N) \ 144 GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target") 145#define pop_alignment(ID) \ 146 GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target") 147#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */ 148 149/* #pragma pack () 150 #pragma pack (N) 151 152 #pragma pack (push, N) 153 #pragma pack (push, ID, N) 154 #pragma pack (pop) 155 #pragma pack (pop, ID) */ 156static void 157handle_pragma_pack (cpp_reader *dummy ATTRIBUTE_UNUSED) 158{ 159 tree x, id = 0; 160 int align = -1; 161 enum cpp_ttype token; 162 enum { set, push, pop } action; 163 164 if (c_lex (&x) != CPP_OPEN_PAREN) 165 GCC_BAD ("missing '(' after '#pragma pack' - ignored"); 166 167 token = c_lex (&x); 168 if (token == CPP_CLOSE_PAREN) 169 { 170 action = set; 171 align = 0; 172 } 173 else if (token == CPP_NUMBER) 174 { 175 align = TREE_INT_CST_LOW (x); 176 action = set; 177 if (c_lex (&x) != CPP_CLOSE_PAREN) 178 GCC_BAD ("malformed '#pragma pack' - ignored"); 179 } 180 else if (token == CPP_NAME) 181 { 182#define GCC_BAD_ACTION do { if (action == push) \ 183 GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \ 184 else \ 185 GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \ 186 } while (0) 187 188 const char *op = IDENTIFIER_POINTER (x); 189 if (!strcmp (op, "push")) 190 action = push; 191 else if (!strcmp (op, "pop")) 192 action = pop; 193 else 194 GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op); 195 196 token = c_lex (&x); 197 if (token != CPP_COMMA && action == push) 198 GCC_BAD_ACTION; 199 200 if (token == CPP_COMMA) 201 { 202 token = c_lex (&x); 203 if (token == CPP_NAME) 204 { 205 id = x; 206 if (action == push && c_lex (&x) != CPP_COMMA) 207 GCC_BAD_ACTION; 208 token = c_lex (&x); 209 } 210 211 if (action == push) 212 { 213 if (token == CPP_NUMBER) 214 { 215 align = TREE_INT_CST_LOW (x); 216 token = c_lex (&x); 217 } 218 else 219 GCC_BAD_ACTION; 220 } 221 } 222 223 if (token != CPP_CLOSE_PAREN) 224 GCC_BAD_ACTION; 225#undef GCC_BAD_ACTION 226 } 227 else 228 GCC_BAD ("malformed '#pragma pack' - ignored"); 229 230 if (c_lex (&x) != CPP_EOF) 231 warning ("junk at end of '#pragma pack'"); 232 233 if (action != pop) 234 switch (align) 235 { 236 case 0: 237 case 1: 238 case 2: 239 case 4: 240 case 8: 241 case 16: 242 align *= BITS_PER_UNIT; 243 break; 244 default: 245 GCC_BAD2 ("alignment must be a small power of two, not %d", align); 246 } 247 248 switch (action) 249 { 250 case set: SET_GLOBAL_ALIGNMENT (align); break; 251 case push: push_alignment (align, id); break; 252 case pop: pop_alignment (id); break; 253 } 254} 255#endif /* HANDLE_PRAGMA_PACK */ 256 257static GTY(()) tree pending_weaks; 258 259#ifdef HANDLE_PRAGMA_WEAK 260static void apply_pragma_weak (tree, tree); 261static void handle_pragma_weak (cpp_reader *); 262 263static void 264apply_pragma_weak (tree decl, tree value) 265{ 266 if (value) 267 { 268 value = build_string (IDENTIFIER_LENGTH (value), 269 IDENTIFIER_POINTER (value)); 270 decl_attributes (&decl, build_tree_list (get_identifier ("alias"), 271 build_tree_list (NULL, value)), 272 0); 273 } 274 275 if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl) 276 && !DECL_WEAK (decl) /* Don't complain about a redundant #pragma. */ 277 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 278 warning ("%Japplying #pragma weak '%D' after first use results " 279 "in unspecified behavior", decl, decl); 280 281 declare_weak (decl); 282} 283 284void 285maybe_apply_pragma_weak (tree decl) 286{ 287 tree *p, t, id; 288 289 /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */ 290 291 /* No weak symbols pending, take the short-cut. */ 292 if (!pending_weaks) 293 return; 294 /* If it's not visible outside this file, it doesn't matter whether 295 it's weak. */ 296 if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl)) 297 return; 298 /* If it's not a function or a variable, it can't be weak. 299 FIXME: what kinds of things are visible outside this file but 300 aren't functions or variables? Should this be an abort() instead? */ 301 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL) 302 return; 303 304 id = DECL_ASSEMBLER_NAME (decl); 305 306 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t)) 307 if (id == TREE_PURPOSE (t)) 308 { 309 apply_pragma_weak (decl, TREE_VALUE (t)); 310 *p = TREE_CHAIN (t); 311 break; 312 } 313} 314 315/* #pragma weak name [= value] */ 316static void 317handle_pragma_weak (cpp_reader *dummy ATTRIBUTE_UNUSED) 318{ 319 tree name, value, x, decl; 320 enum cpp_ttype t; 321 322 value = 0; 323 324 if (c_lex (&name) != CPP_NAME) 325 GCC_BAD ("malformed #pragma weak, ignored"); 326 t = c_lex (&x); 327 if (t == CPP_EQ) 328 { 329 if (c_lex (&value) != CPP_NAME) 330 GCC_BAD ("malformed #pragma weak, ignored"); 331 t = c_lex (&x); 332 } 333 if (t != CPP_EOF) 334 warning ("junk at end of #pragma weak"); 335 336 decl = identifier_global_value (name); 337 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 338 { 339 apply_pragma_weak (decl, value); 340 if (value) 341 assemble_alias (decl, value); 342 } 343 else 344 pending_weaks = tree_cons (name, value, pending_weaks); 345} 346#else 347void 348maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED) 349{ 350} 351#endif /* HANDLE_PRAGMA_WEAK */ 352 353static GTY(()) tree pending_redefine_extname; 354 355#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 356static void handle_pragma_redefine_extname (cpp_reader *); 357 358/* #pragma redefined_extname oldname newname */ 359static void 360handle_pragma_redefine_extname (cpp_reader *dummy ATTRIBUTE_UNUSED) 361{ 362 tree oldname, newname, decl, x; 363 enum cpp_ttype t; 364 365 if (c_lex (&oldname) != CPP_NAME) 366 { 367 warning ("malformed #pragma redefine_extname, ignored"); 368 return; 369 } 370 if (c_lex (&newname) != CPP_NAME) 371 { 372 warning ("malformed #pragma redefine_extname, ignored"); 373 return; 374 } 375 t = c_lex (&x); 376 if (t != CPP_EOF) 377 warning ("junk at end of #pragma redefine_extname"); 378 379 decl = identifier_global_value (oldname); 380 if (decl && (TREE_CODE (decl) == FUNCTION_DECL 381 || TREE_CODE (decl) == VAR_DECL)) 382 { 383 if (DECL_ASSEMBLER_NAME_SET_P (decl) 384 && DECL_ASSEMBLER_NAME (decl) != newname) 385 warning ("#pragma redefine_extname conflicts with declaration"); 386 change_decl_assembler_name (decl, newname); 387 } 388 else 389 add_to_renaming_pragma_list(oldname, newname); 390} 391#endif 392 393void 394add_to_renaming_pragma_list (tree oldname, tree newname) 395{ 396 pending_redefine_extname 397 = tree_cons (oldname, newname, pending_redefine_extname); 398} 399 400static GTY(()) tree pragma_extern_prefix; 401 402#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 403static void handle_pragma_extern_prefix (cpp_reader *); 404 405/* #pragma extern_prefix "prefix" */ 406static void 407handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED) 408{ 409 tree prefix, x; 410 enum cpp_ttype t; 411 412 if (c_lex (&prefix) != CPP_STRING) 413 { 414 warning ("malformed #pragma extern_prefix, ignored"); 415 return; 416 } 417 t = c_lex (&x); 418 if (t != CPP_EOF) 419 warning ("junk at end of #pragma extern_prefix"); 420 421 /* Note that the length includes the null terminator. */ 422 pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL); 423} 424#endif 425 426/* Hook from the front ends to apply the results of one of the preceding 427 pragmas that rename variables. */ 428 429tree 430maybe_apply_renaming_pragma (tree decl, tree asmname) 431{ 432 tree oldname; 433 434 /* Copied from the check in set_decl_assembler_name. */ 435 if (TREE_CODE (decl) == FUNCTION_DECL 436 || (TREE_CODE (decl) == VAR_DECL 437 && (TREE_STATIC (decl) 438 || DECL_EXTERNAL (decl) 439 || TREE_PUBLIC (decl)))) 440 oldname = DECL_ASSEMBLER_NAME (decl); 441 else 442 return asmname; 443 444 /* If the name begins with a *, that's a sign of an asmname attached to 445 a previous declaration. */ 446 if (IDENTIFIER_POINTER (oldname)[0] == '*') 447 { 448 const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1; 449 if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0) 450 warning ("asm declaration conflicts with previous rename"); 451 asmname = build_string (strlen (oldasmname), oldasmname); 452 } 453 454 { 455 tree *p, t; 456 457 for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t)) 458 if (oldname == TREE_PURPOSE (t)) 459 { 460 const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t)); 461 462 if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0) 463 warning ("#pragma redefine_extname conflicts with declaration"); 464 *p = TREE_CHAIN (t); 465 466 return build_string (strlen (newname), newname); 467 } 468 } 469 470#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 471 if (pragma_extern_prefix && !asmname) 472 { 473 char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix), 474 IDENTIFIER_POINTER (oldname), NULL); 475 asmname = build_string (strlen (x), x); 476 free (x); 477 return asmname; 478 } 479#endif 480 481 return asmname; 482} 483 484/* Front-end wrapper for pragma registration to avoid dragging 485 cpplib.h in almost everywhere. */ 486void 487c_register_pragma (const char *space, const char *name, 488 void (*handler) (struct cpp_reader *)) 489{ 490 cpp_register_pragma (parse_in, space, name, handler); 491} 492 493/* Set up front-end pragmas. */ 494void 495init_pragma (void) 496{ 497#ifdef HANDLE_PRAGMA_PACK 498 c_register_pragma (0, "pack", handle_pragma_pack); 499#endif 500#ifdef HANDLE_PRAGMA_WEAK 501 c_register_pragma (0, "weak", handle_pragma_weak); 502#endif 503#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 504 c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname); 505#endif 506#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 507 c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix); 508#endif 509 510#ifdef REGISTER_TARGET_PRAGMAS 511 REGISTER_TARGET_PRAGMAS (); 512#endif 513} 514 515#include "gt-c-pragma.h" 516