c-pragma.c revision 119256
185597Speter/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. 285597Speter Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002 385597Speter Free Software Foundation, Inc. 485597Speter 585597SpeterThis file is part of GCC. 685597Speter 785597SpeterGCC is free software; you can redistribute it and/or modify it under 885597Speterthe terms of the GNU General Public License as published by the Free 985597SpeterSoftware Foundation; either version 2, or (at your option) any later 1085597Speterversion. 1185597Speter 1285597SpeterGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1385597SpeterWARRANTY; without even the implied warranty of MERCHANTABILITY or 1485597SpeterFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1585597Speterfor more details. 1685597Speter 1785597SpeterYou should have received a copy of the GNU General Public License 1885597Speteralong with GCC; see the file COPYING. If not, write to the Free 1985597SpeterSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2085597Speter02111-1307, USA. */ 2185597Speter 2285597Speter#include "config.h" 2385597Speter#include "system.h" 2485597Speter#include "rtl.h" 2585597Speter#include "tree.h" 2685597Speter#include "function.h" 2785597Speter#include "cpplib.h" 2885597Speter#include "c-pragma.h" 29216338Sdim#include "flags.h" 30216338Sdim#include "toplev.h" 31216338Sdim#include "ggc.h" 3285597Speter#include "c-common.h" 3385597Speter#include "output.h" 3485597Speter#include "tm_p.h" 3585597Speter 3685597Speter#define GCC_BAD(msgid) do { warning (msgid); return; } while (0) 3785597Speter#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) 3885679Speter 3985679Spetertypedef struct align_stack GTY(()) 4085679Speter{ 4185597Speter int alignment; 4285952Speter unsigned int num_pushes; 4385952Speter tree id; 4485952Speter struct align_stack * prev; 4585679Speter} align_stack; 4685679Speter 4785952Speterstatic GTY(()) struct align_stack * alignment_stack; 4885679Speter 4985597Speter#ifdef HANDLE_PRAGMA_PACK 5085679Speterstatic void handle_pragma_pack PARAMS ((cpp_reader *)); 5185679Speter 5285679Speter#ifdef HANDLE_PRAGMA_PACK_PUSH_POP 5385597Speter/* If we have a "global" #pragma pack(<n>) in effect when the first 5485952Speter #pragma pack(push,<n>) is encountered, this stores the value of 5585952Speter maximum_field_alignment in effect. When the final pop_alignment() 5685952Speter happens, we restore the value to this, not to a value of 0 for 5785679Speter maximum_field_alignment. Value is in bits. */ 5885679Speterstatic int default_alignment; 5985952Speter#define SET_GLOBAL_ALIGNMENT(ALIGN) \ 6085679Speter (default_alignment = maximum_field_alignment = (ALIGN)) 61 62static void push_alignment PARAMS ((int, tree)); 63static void pop_alignment PARAMS ((tree)); 64 65/* Push an alignment value onto the stack. */ 66static void 67push_alignment (alignment, id) 68 int alignment; 69 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 = (align_stack *) 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 (id) 101 tree id; 102{ 103 align_stack * entry; 104 105 if (alignment_stack == NULL) 106 { 107 warning ("\ 108#pragma pack (pop) encountered without matching #pragma pack (push, <n>)" 109 ); 110 return; 111 } 112 113 /* If we got an identifier, strip away everything above the target 114 entry so that the next step will restore the state just below it. */ 115 if (id) 116 { 117 for (entry = alignment_stack; entry; entry = entry->prev) 118 if (entry->id == id) 119 { 120 entry->num_pushes = 1; 121 alignment_stack = entry; 122 break; 123 } 124 if (entry == NULL) 125 warning ("\ 126#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)" 127 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id)); 128 } 129 130 if (-- alignment_stack->num_pushes == 0) 131 { 132 entry = alignment_stack->prev; 133 134 if (entry == NULL) 135 maximum_field_alignment = default_alignment; 136 else 137 maximum_field_alignment = entry->alignment; 138 139 alignment_stack = entry; 140 } 141} 142#else /* not HANDLE_PRAGMA_PACK_PUSH_POP */ 143#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN)) 144#define push_alignment(ID, N) \ 145 GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target") 146#define pop_alignment(ID) \ 147 GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target") 148#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */ 149 150/* #pragma pack () 151 #pragma pack (N) 152 153 #pragma pack (push, N) 154 #pragma pack (push, ID, N) 155 #pragma pack (pop) 156 #pragma pack (pop, ID) */ 157static void 158handle_pragma_pack (dummy) 159 cpp_reader *dummy ATTRIBUTE_UNUSED; 160{ 161 tree x, id = 0; 162 int align = -1; 163 enum cpp_ttype token; 164 enum { set, push, pop } action; 165 166 if (c_lex (&x) != CPP_OPEN_PAREN) 167 GCC_BAD ("missing '(' after '#pragma pack' - ignored"); 168 169 token = c_lex (&x); 170 if (token == CPP_CLOSE_PAREN) 171 { 172 action = set; 173 align = 0; 174 } 175 else if (token == CPP_NUMBER) 176 { 177 align = TREE_INT_CST_LOW (x); 178 action = set; 179 if (c_lex (&x) != CPP_CLOSE_PAREN) 180 GCC_BAD ("malformed '#pragma pack' - ignored"); 181 } 182 else if (token == CPP_NAME) 183 { 184#define GCC_BAD_ACTION do { if (action == push) \ 185 GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \ 186 else \ 187 GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \ 188 } while (0) 189 190 const char *op = IDENTIFIER_POINTER (x); 191 if (!strcmp (op, "push")) 192 action = push; 193 else if (!strcmp (op, "pop")) 194 action = pop; 195 else 196 GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op); 197 198 token = c_lex (&x); 199 if (token != CPP_COMMA && action == push) 200 GCC_BAD_ACTION; 201 202 if (token == CPP_COMMA) 203 { 204 token = c_lex (&x); 205 if (token == CPP_NAME) 206 { 207 id = x; 208 if (action == push && c_lex (&x) != CPP_COMMA) 209 GCC_BAD_ACTION; 210 token = c_lex (&x); 211 } 212 213 if (action == push) 214 { 215 if (token == CPP_NUMBER) 216 { 217 align = TREE_INT_CST_LOW (x); 218 token = c_lex (&x); 219 } 220 else 221 GCC_BAD_ACTION; 222 } 223 } 224 225 if (token != CPP_CLOSE_PAREN) 226 GCC_BAD_ACTION; 227#undef GCC_BAD_ACTION 228 } 229 else 230 GCC_BAD ("malformed '#pragma pack' - ignored"); 231 232 if (c_lex (&x) != CPP_EOF) 233 warning ("junk at end of '#pragma pack'"); 234 235 if (action != pop) 236 switch (align) 237 { 238 case 0: 239 case 1: 240 case 2: 241 case 4: 242 case 8: 243 case 16: 244 align *= BITS_PER_UNIT; 245 break; 246 default: 247 GCC_BAD2 ("alignment must be a small power of two, not %d", align); 248 } 249 250 switch (action) 251 { 252 case set: SET_GLOBAL_ALIGNMENT (align); break; 253 case push: push_alignment (align, id); break; 254 case pop: pop_alignment (id); break; 255 } 256} 257#endif /* HANDLE_PRAGMA_PACK */ 258 259static GTY(()) tree pending_weaks; 260 261#ifdef HANDLE_PRAGMA_WEAK 262static void apply_pragma_weak PARAMS ((tree, tree)); 263static void handle_pragma_weak PARAMS ((cpp_reader *)); 264 265static void 266apply_pragma_weak (decl, value) 267 tree decl, value; 268{ 269 if (value) 270 { 271 value = build_string (IDENTIFIER_LENGTH (value), 272 IDENTIFIER_POINTER (value)); 273 decl_attributes (&decl, build_tree_list (get_identifier ("alias"), 274 build_tree_list (NULL, value)), 275 0); 276 } 277 278 if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl) 279 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 280 warning_with_decl (decl, "applying #pragma weak `%s' after first use results in unspecified behavior"); 281 282 declare_weak (decl); 283} 284 285void 286maybe_apply_pragma_weak (decl) 287 tree decl; 288{ 289 tree *p, t, id; 290 291 /* Avoid asking for DECL_ASSEMBLER_NAME when it's not needed. */ 292 293 /* No weak symbols pending, take the short-cut. */ 294 if (!pending_weaks) 295 return; 296 /* If it's not visible outside this file, it doesn't matter whether 297 it's weak. */ 298 if (!DECL_EXTERNAL (decl) && !TREE_PUBLIC (decl)) 299 return; 300 /* If it's not a function or a variable, it can't be weak. 301 FIXME: what kinds of things are visible outside this file but 302 aren't functions or variables? Should this be an abort() instead? */ 303 if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL) 304 return; 305 306 id = DECL_ASSEMBLER_NAME (decl); 307 308 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t)) 309 if (id == TREE_PURPOSE (t)) 310 { 311 apply_pragma_weak (decl, TREE_VALUE (t)); 312 *p = TREE_CHAIN (t); 313 break; 314 } 315} 316 317/* #pragma weak name [= value] */ 318static void 319handle_pragma_weak (dummy) 320 cpp_reader *dummy ATTRIBUTE_UNUSED; 321{ 322 tree name, value, x, decl; 323 enum cpp_ttype t; 324 325 value = 0; 326 327 if (c_lex (&name) != CPP_NAME) 328 GCC_BAD ("malformed #pragma weak, ignored"); 329 t = c_lex (&x); 330 if (t == CPP_EQ) 331 { 332 if (c_lex (&value) != CPP_NAME) 333 GCC_BAD ("malformed #pragma weak, ignored"); 334 t = c_lex (&x); 335 } 336 if (t != CPP_EOF) 337 warning ("junk at end of #pragma weak"); 338 339 decl = identifier_global_value (name); 340 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 341 { 342 apply_pragma_weak (decl, value); 343 if (value) 344 assemble_alias (decl, value); 345 } 346 else 347 pending_weaks = tree_cons (name, value, pending_weaks); 348} 349#else 350void 351maybe_apply_pragma_weak (decl) 352 tree decl ATTRIBUTE_UNUSED; 353{ 354} 355#endif /* HANDLE_PRAGMA_WEAK */ 356 357static GTY(()) tree pending_redefine_extname; 358 359#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 360static void handle_pragma_redefine_extname PARAMS ((cpp_reader *)); 361 362/* #pragma redefined_extname oldname newname */ 363static void 364handle_pragma_redefine_extname (dummy) 365 cpp_reader *dummy ATTRIBUTE_UNUSED; 366{ 367 tree oldname, newname, decl, x; 368 enum cpp_ttype t; 369 370 if (c_lex (&oldname) != CPP_NAME) 371 { 372 warning ("malformed #pragma redefine_extname, ignored"); 373 return; 374 } 375 if (c_lex (&newname) != CPP_NAME) 376 { 377 warning ("malformed #pragma redefine_extname, ignored"); 378 return; 379 } 380 t = c_lex (&x); 381 if (t != CPP_EOF) 382 warning ("junk at end of #pragma redefine_extname"); 383 384 decl = identifier_global_value (oldname); 385 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 386 { 387 if (DECL_ASSEMBLER_NAME_SET_P (decl) 388 && DECL_ASSEMBLER_NAME (decl) != newname) 389 warning ("#pragma redefine_extname conflicts with declaration"); 390 SET_DECL_ASSEMBLER_NAME (decl, newname); 391 } 392 else 393 add_to_renaming_pragma_list(oldname, newname); 394} 395#endif 396 397void 398add_to_renaming_pragma_list (oldname, newname) 399 tree oldname, newname; 400{ 401 pending_redefine_extname 402 = tree_cons (oldname, newname, pending_redefine_extname); 403} 404 405static GTY(()) tree pragma_extern_prefix; 406 407#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 408static void handle_pragma_extern_prefix PARAMS ((cpp_reader *)); 409 410/* #pragma extern_prefix "prefix" */ 411static void 412handle_pragma_extern_prefix (dummy) 413 cpp_reader *dummy ATTRIBUTE_UNUSED; 414{ 415 tree prefix, x; 416 enum cpp_ttype t; 417 418 if (c_lex (&prefix) != CPP_STRING) 419 { 420 warning ("malformed #pragma extern_prefix, ignored"); 421 return; 422 } 423 t = c_lex (&x); 424 if (t != CPP_EOF) 425 warning ("junk at end of #pragma extern_prefix"); 426 427 /* Note that the length includes the null terminator. */ 428 pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL); 429} 430#endif 431 432/* Hook from the front ends to apply the results of one of the preceeding 433 pragmas that rename variables. */ 434 435tree 436maybe_apply_renaming_pragma (decl, asmname) 437 tree decl, asmname; 438{ 439 tree oldname; 440 441 /* Copied from the check in set_decl_assembler_name. */ 442 if (TREE_CODE (decl) == FUNCTION_DECL 443 || (TREE_CODE (decl) == VAR_DECL 444 && (TREE_STATIC (decl) 445 || DECL_EXTERNAL (decl) 446 || TREE_PUBLIC (decl)))) 447 oldname = DECL_ASSEMBLER_NAME (decl); 448 else 449 return asmname; 450 451 /* If the name begins with a *, that's a sign of an asmname attached to 452 a previous declaration. */ 453 if (IDENTIFIER_POINTER (oldname)[0] == '*') 454 { 455 const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1; 456 if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0) 457 warning ("asm declaration conflicts with previous rename"); 458 asmname = build_string (strlen (oldasmname), oldasmname); 459 } 460 461 { 462 tree *p, t; 463 464 for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t)) 465 if (oldname == TREE_PURPOSE (t)) 466 { 467 const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t)); 468 469 if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0) 470 warning ("#pragma redefine_extname conflicts with declaration"); 471 *p = TREE_CHAIN (t); 472 473 return build_string (strlen (newname), newname); 474 } 475 } 476 477#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 478 if (pragma_extern_prefix && !asmname) 479 { 480 char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix), 481 IDENTIFIER_POINTER (oldname), NULL); 482 asmname = build_string (strlen (x), x); 483 free (x); 484 return asmname; 485 } 486#endif 487 488 return asmname; 489} 490 491void 492init_pragma () 493{ 494#ifdef HANDLE_PRAGMA_PACK 495 cpp_register_pragma (parse_in, 0, "pack", handle_pragma_pack); 496#endif 497#ifdef HANDLE_PRAGMA_WEAK 498 cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak); 499#endif 500#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 501 cpp_register_pragma (parse_in, 0, "redefine_extname", 502 handle_pragma_redefine_extname); 503#endif 504#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 505 cpp_register_pragma (parse_in, 0, "extern_prefix", 506 handle_pragma_extern_prefix); 507#endif 508 509#ifdef REGISTER_TARGET_PRAGMAS 510 REGISTER_TARGET_PRAGMAS (parse_in); 511#endif 512} 513 514#include "gt-c-pragma.h" 515