c-pragma.c revision 96263
1/* Handle #pragma, system V.4 style. Supports #pragma weak and #pragma pack. 2 Copyright (C) 1992, 1997, 1998, 1999, 2000, 2001, 2002 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 "rtl.h" 25#include "tree.h" 26#include "function.h" 27#include "cpplib.h" 28#include "c-pragma.h" 29#include "flags.h" 30#include "toplev.h" 31#include "ggc.h" 32#include "c-lex.h" 33#include "c-common.h" 34#include "output.h" 35#include "tm_p.h" 36 37#define GCC_BAD(msgid) do { warning (msgid); return; } while (0) 38#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) 39 40#ifdef HANDLE_PRAGMA_PACK 41static void handle_pragma_pack PARAMS ((cpp_reader *)); 42 43#ifdef HANDLE_PRAGMA_PACK_PUSH_POP 44typedef struct align_stack 45{ 46 int alignment; 47 unsigned int num_pushes; 48 tree id; 49 struct align_stack * prev; 50} align_stack; 51 52static struct align_stack * alignment_stack = NULL; 53 54/* If we have a "global" #pragma pack(<n>) in effect when the first 55 #pragma pack(push,<n>) is encountered, this stores the value of 56 maximum_field_alignment in effect. When the final pop_alignment() 57 happens, we restore the value to this, not to a value of 0 for 58 maximum_field_alignment. Value is in bits. */ 59static int default_alignment; 60#define SET_GLOBAL_ALIGNMENT(ALIGN) \ 61 (default_alignment = maximum_field_alignment = (ALIGN)) 62 63static void push_alignment PARAMS ((int, tree)); 64static void pop_alignment PARAMS ((tree)); 65static void mark_align_stack PARAMS ((void *)); 66 67/* Push an alignment value onto the stack. */ 68static void 69push_alignment (alignment, id) 70 int alignment; 71 tree id; 72{ 73 if (alignment_stack == NULL 74 || alignment_stack->alignment != alignment 75 || id != NULL_TREE) 76 { 77 align_stack * entry; 78 79 entry = (align_stack *) xmalloc (sizeof (* entry)); 80 81 entry->alignment = alignment; 82 entry->num_pushes = 1; 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 88 so that we can restore it after the final #pragma pop(). */ 89 if (alignment_stack == NULL) 90 default_alignment = maximum_field_alignment; 91 92 alignment_stack = entry; 93 94 maximum_field_alignment = alignment; 95 } 96 else 97 alignment_stack->num_pushes ++; 98} 99 100/* Undo a push of an alignment onto the stack. */ 101static void 102pop_alignment (id) 103 tree id; 104{ 105 align_stack * entry; 106 107 if (alignment_stack == NULL) 108 { 109 warning ("\ 110#pragma pack (pop) encountered without matching #pragma pack (push, <n>)" 111 ); 112 return; 113 } 114 115 /* If we got an identifier, strip away everything above the target 116 entry so that the next step will restore the state just below it. */ 117 if (id) 118 { 119 for (entry = alignment_stack; entry; entry = entry->prev) 120 if (entry->id == id) 121 { 122 entry->num_pushes = 1; 123 alignment_stack = entry; 124 break; 125 } 126 if (entry == NULL) 127 warning ("\ 128#pragma pack(pop, %s) encountered without matching #pragma pack(push, %s, <n>)" 129 , IDENTIFIER_POINTER (id), IDENTIFIER_POINTER (id)); 130 } 131 132 if (-- alignment_stack->num_pushes == 0) 133 { 134 entry = alignment_stack->prev; 135 136 if (entry == NULL) 137 maximum_field_alignment = default_alignment; 138 else 139 maximum_field_alignment = entry->alignment; 140 141 free (alignment_stack); 142 143 alignment_stack = entry; 144 } 145} 146 147static void 148mark_align_stack (p) 149 void *p; 150{ 151 align_stack *a = *(align_stack **) p; 152 153 while (a) 154 { 155 ggc_mark_tree (a->id); 156 a = a->prev; 157 } 158} 159#else /* not HANDLE_PRAGMA_PACK_PUSH_POP */ 160#define SET_GLOBAL_ALIGNMENT(ALIGN) (maximum_field_alignment = (ALIGN)) 161#define push_alignment(ID, N) \ 162 GCC_BAD("#pragma pack(push[, id], <n>) is not supported on this target") 163#define pop_alignment(ID) \ 164 GCC_BAD("#pragma pack(pop[, id], <n>) is not supported on this target") 165#endif /* HANDLE_PRAGMA_PACK_PUSH_POP */ 166 167/* #pragma pack () 168 #pragma pack (N) 169 170 #pragma pack (push, N) 171 #pragma pack (push, ID, N) 172 #pragma pack (pop) 173 #pragma pack (pop, ID) */ 174static void 175handle_pragma_pack (dummy) 176 cpp_reader *dummy ATTRIBUTE_UNUSED; 177{ 178 tree x, id = 0; 179 int align = -1; 180 enum cpp_ttype token; 181 enum { set, push, pop } action; 182 183 if (c_lex (&x) != CPP_OPEN_PAREN) 184 GCC_BAD ("missing '(' after '#pragma pack' - ignored"); 185 186 token = c_lex (&x); 187 if (token == CPP_CLOSE_PAREN) 188 { 189 action = set; 190 align = 0; 191 } 192 else if (token == CPP_NUMBER) 193 { 194 align = TREE_INT_CST_LOW (x); 195 action = set; 196 if (c_lex (&x) != CPP_CLOSE_PAREN) 197 GCC_BAD ("malformed '#pragma pack' - ignored"); 198 } 199 else if (token == CPP_NAME) 200 { 201#define GCC_BAD_ACTION do { if (action == push) \ 202 GCC_BAD ("malformed '#pragma pack(push[, id], <n>)' - ignored"); \ 203 else \ 204 GCC_BAD ("malformed '#pragma pack(pop[, id])' - ignored"); \ 205 } while (0) 206 207 const char *op = IDENTIFIER_POINTER (x); 208 if (!strcmp (op, "push")) 209 action = push; 210 else if (!strcmp (op, "pop")) 211 action = pop; 212 else 213 GCC_BAD2 ("unknown action '%s' for '#pragma pack' - ignored", op); 214 215 token = c_lex (&x); 216 if (token != CPP_COMMA && action == push) 217 GCC_BAD_ACTION; 218 219 if (token == CPP_COMMA) 220 { 221 token = c_lex (&x); 222 if (token == CPP_NAME) 223 { 224 id = x; 225 if (action == push && c_lex (&x) != CPP_COMMA) 226 GCC_BAD_ACTION; 227 token = c_lex (&x); 228 } 229 230 if (action == push) 231 { 232 if (token == CPP_NUMBER) 233 { 234 align = TREE_INT_CST_LOW (x); 235 token = c_lex (&x); 236 } 237 else 238 GCC_BAD_ACTION; 239 } 240 } 241 242 if (token != CPP_CLOSE_PAREN) 243 GCC_BAD_ACTION; 244#undef GCC_BAD_ACTION 245 } 246 else 247 GCC_BAD ("malformed '#pragma pack' - ignored"); 248 249 if (c_lex (&x) != CPP_EOF) 250 warning ("junk at end of '#pragma pack'"); 251 252 if (action != pop) 253 switch (align) 254 { 255 case 0: 256 case 1: 257 case 2: 258 case 4: 259 case 8: 260 case 16: 261 align *= BITS_PER_UNIT; 262 break; 263 default: 264 GCC_BAD2 ("alignment must be a small power of two, not %d", align); 265 } 266 267 switch (action) 268 { 269 case set: SET_GLOBAL_ALIGNMENT (align); break; 270 case push: push_alignment (align, id); break; 271 case pop: pop_alignment (id); break; 272 } 273} 274#endif /* HANDLE_PRAGMA_PACK */ 275 276#ifdef HANDLE_PRAGMA_WEAK 277static void apply_pragma_weak PARAMS ((tree, tree)); 278static void handle_pragma_weak PARAMS ((cpp_reader *)); 279 280static tree pending_weaks; 281 282static void 283apply_pragma_weak (decl, value) 284 tree decl, value; 285{ 286 if (value) 287 decl_attributes (&decl, build_tree_list (get_identifier ("alias"), 288 build_tree_list (NULL, value)), 289 0); 290 if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl) 291 && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) 292 warning_with_decl (decl, "applying #pragma weak `%s' after first use results in unspecified behavior"); 293 294 declare_weak (decl); 295} 296 297void 298maybe_apply_pragma_weak (decl) 299 tree decl; 300{ 301 tree *p, t, id; 302 303 /* Copied from the check in set_decl_assembler_name. */ 304 if (TREE_CODE (decl) == FUNCTION_DECL 305 || (TREE_CODE (decl) == VAR_DECL 306 && (TREE_STATIC (decl) 307 || DECL_EXTERNAL (decl) 308 || TREE_PUBLIC (decl)))) 309 id = DECL_ASSEMBLER_NAME (decl); 310 else 311 return; 312 313 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t)) 314 if (id == TREE_PURPOSE (t)) 315 { 316 apply_pragma_weak (decl, TREE_VALUE (t)); 317 *p = TREE_CHAIN (t); 318 break; 319 } 320} 321 322/* #pragma weak name [= value] */ 323static void 324handle_pragma_weak (dummy) 325 cpp_reader *dummy ATTRIBUTE_UNUSED; 326{ 327 tree name, value, x, decl; 328 enum cpp_ttype t; 329 330 value = 0; 331 332 if (c_lex (&name) != CPP_NAME) 333 GCC_BAD ("malformed #pragma weak, ignored"); 334 t = c_lex (&x); 335 if (t == CPP_EQ) 336 { 337 if (c_lex (&value) != CPP_NAME) 338 GCC_BAD ("malformed #pragma weak, ignored"); 339 t = c_lex (&x); 340 } 341 if (t != CPP_EOF) 342 warning ("junk at end of #pragma weak"); 343 344 decl = identifier_global_value (name); 345 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 346 apply_pragma_weak (decl, value); 347 else 348 pending_weaks = tree_cons (name, value, pending_weaks); 349} 350#else 351void 352maybe_apply_pragma_weak (decl) 353 tree decl ATTRIBUTE_UNUSED; 354{ 355} 356#endif /* HANDLE_PRAGMA_WEAK */ 357 358#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 359static void handle_pragma_redefine_extname PARAMS ((cpp_reader *)); 360 361static tree pending_redefine_extname; 362 363/* #pragma redefined_extname oldname newname */ 364static void 365handle_pragma_redefine_extname (dummy) 366 cpp_reader *dummy ATTRIBUTE_UNUSED; 367{ 368 tree oldname, newname, decl, x; 369 enum cpp_ttype t; 370 371 if (c_lex (&oldname) != CPP_NAME) 372 { 373 warning ("malformed #pragma redefine_extname, ignored"); 374 return; 375 } 376 if (c_lex (&newname) != CPP_NAME) 377 { 378 warning ("malformed #pragma redefine_extname, ignored"); 379 return; 380 } 381 t = c_lex (&x); 382 if (t != CPP_EOF) 383 warning ("junk at end of #pragma redefine_extname"); 384 385 decl = identifier_global_value (oldname); 386 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 387 { 388 if (DECL_ASSEMBLER_NAME_SET_P (decl) 389 && DECL_ASSEMBLER_NAME (decl) != newname) 390 warning ("#pragma redefine_extname conflicts with declaration"); 391 SET_DECL_ASSEMBLER_NAME (decl, newname); 392 } 393 else 394 pending_redefine_extname 395 = tree_cons (oldname, newname, pending_redefine_extname); 396} 397#endif 398 399#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 400static void handle_pragma_extern_prefix PARAMS ((cpp_reader *)); 401 402static tree pragma_extern_prefix; 403 404/* #pragma extern_prefix "prefix" */ 405static void 406handle_pragma_extern_prefix (dummy) 407 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 preceeding 427 pragmas that rename variables. */ 428 429tree 430maybe_apply_renaming_pragma (decl, asmname) 431 tree decl, asmname; 432{ 433 tree oldname; 434 435 /* Copied from the check in set_decl_assembler_name. */ 436 if (TREE_CODE (decl) == FUNCTION_DECL 437 || (TREE_CODE (decl) == VAR_DECL 438 && (TREE_STATIC (decl) 439 || DECL_EXTERNAL (decl) 440 || TREE_PUBLIC (decl)))) 441 oldname = DECL_ASSEMBLER_NAME (decl); 442 else 443 return asmname; 444 445 /* If the name begins with a *, that's a sign of an asmname attached to 446 a previous declaration. */ 447 if (IDENTIFIER_POINTER (oldname)[0] == '*') 448 { 449 const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1; 450 if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0) 451 warning ("asm declaration conficts with previous rename"); 452 asmname = build_string (strlen (oldasmname), oldasmname); 453 } 454 455#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 456 { 457 tree *p, t; 458 459 for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t)) 460 if (oldname == TREE_PURPOSE (t)) 461 { 462 const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t)); 463 464 if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0) 465 warning ("#pragma redefine_extname conflicts with declaration"); 466 *p = TREE_CHAIN (t); 467 468 return build_string (strlen (newname), newname); 469 } 470 } 471#endif 472 473#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 474 if (pragma_extern_prefix && !asmname) 475 { 476 char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix), 477 IDENTIFIER_POINTER (oldname), NULL); 478 asmname = build_string (strlen (x), x); 479 free (x); 480 return asmname; 481 } 482#endif 483 484 return asmname; 485} 486 487void 488init_pragma () 489{ 490#ifdef HANDLE_PRAGMA_PACK 491 cpp_register_pragma (parse_in, 0, "pack", handle_pragma_pack); 492#endif 493#ifdef HANDLE_PRAGMA_WEAK 494 cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak); 495 ggc_add_tree_root (&pending_weaks, 1); 496#endif 497#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 498 cpp_register_pragma (parse_in, 0, "redefine_extname", 499 handle_pragma_redefine_extname); 500 ggc_add_tree_root (&pending_redefine_extname, 1); 501#endif 502#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 503 cpp_register_pragma (parse_in, 0, "extern_prefix", 504 handle_pragma_extern_prefix); 505 ggc_add_tree_root (&pragma_extern_prefix, 1); 506#endif 507 508#ifdef REGISTER_TARGET_PRAGMAS 509 REGISTER_TARGET_PRAGMAS (parse_in); 510#endif 511 512#ifdef HANDLE_PRAGMA_PACK_PUSH_POP 513 ggc_add_root (&alignment_stack, 1, sizeof(alignment_stack), 514 mark_align_stack); 515#endif 516} 517