c-pragma.c revision 117395
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-common.h" 33#include "output.h" 34#include "tm_p.h" 35 36#define GCC_BAD(msgid) do { warning (msgid); return; } while (0) 37#define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) 38 39typedef struct align_stack GTY(()) 40{ 41 int alignment; 42 unsigned int num_pushes; 43 tree id; 44 struct align_stack * prev; 45} align_stack; 46 47static GTY(()) struct align_stack * alignment_stack; 48 49#ifdef HANDLE_PRAGMA_PACK 50static void handle_pragma_pack PARAMS ((cpp_reader *)); 51 52#ifdef HANDLE_PRAGMA_PACK_PUSH_POP 53/* If we have a "global" #pragma pack(<n>) in effect when the first 54 #pragma pack(push,<n>) is encountered, this stores the value of 55 maximum_field_alignment in effect. When the final pop_alignment() 56 happens, we restore the value to this, not to a value of 0 for 57 maximum_field_alignment. Value is in bits. */ 58static int default_alignment; 59#define SET_GLOBAL_ALIGNMENT(ALIGN) \ 60 (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 /* Copied from the check in set_decl_assembler_name. */ 292 if (TREE_CODE (decl) == FUNCTION_DECL 293 || (TREE_CODE (decl) == VAR_DECL 294 && (TREE_STATIC (decl) 295 || DECL_EXTERNAL (decl) 296 || TREE_PUBLIC (decl)))) 297 id = DECL_ASSEMBLER_NAME (decl); 298 else 299 return; 300 301 for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t)) 302 if (id == TREE_PURPOSE (t)) 303 { 304 apply_pragma_weak (decl, TREE_VALUE (t)); 305 *p = TREE_CHAIN (t); 306 break; 307 } 308} 309 310/* #pragma weak name [= value] */ 311static void 312handle_pragma_weak (dummy) 313 cpp_reader *dummy ATTRIBUTE_UNUSED; 314{ 315 tree name, value, x, decl; 316 enum cpp_ttype t; 317 318 value = 0; 319 320 if (c_lex (&name) != CPP_NAME) 321 GCC_BAD ("malformed #pragma weak, ignored"); 322 t = c_lex (&x); 323 if (t == CPP_EQ) 324 { 325 if (c_lex (&value) != CPP_NAME) 326 GCC_BAD ("malformed #pragma weak, ignored"); 327 t = c_lex (&x); 328 } 329 if (t != CPP_EOF) 330 warning ("junk at end of #pragma weak"); 331 332 decl = identifier_global_value (name); 333 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 334 { 335 apply_pragma_weak (decl, value); 336 if (value) 337 assemble_alias (decl, value); 338 } 339 else 340 pending_weaks = tree_cons (name, value, pending_weaks); 341} 342#else 343void 344maybe_apply_pragma_weak (decl) 345 tree decl ATTRIBUTE_UNUSED; 346{ 347} 348#endif /* HANDLE_PRAGMA_WEAK */ 349 350static GTY(()) tree pending_redefine_extname; 351 352#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 353static void handle_pragma_redefine_extname PARAMS ((cpp_reader *)); 354 355/* #pragma redefined_extname oldname newname */ 356static void 357handle_pragma_redefine_extname (dummy) 358 cpp_reader *dummy ATTRIBUTE_UNUSED; 359{ 360 tree oldname, newname, decl, x; 361 enum cpp_ttype t; 362 363 if (c_lex (&oldname) != CPP_NAME) 364 { 365 warning ("malformed #pragma redefine_extname, ignored"); 366 return; 367 } 368 if (c_lex (&newname) != CPP_NAME) 369 { 370 warning ("malformed #pragma redefine_extname, ignored"); 371 return; 372 } 373 t = c_lex (&x); 374 if (t != CPP_EOF) 375 warning ("junk at end of #pragma redefine_extname"); 376 377 decl = identifier_global_value (oldname); 378 if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') 379 { 380 if (DECL_ASSEMBLER_NAME_SET_P (decl) 381 && DECL_ASSEMBLER_NAME (decl) != newname) 382 warning ("#pragma redefine_extname conflicts with declaration"); 383 SET_DECL_ASSEMBLER_NAME (decl, newname); 384 } 385 else 386 add_to_renaming_pragma_list(oldname, newname); 387} 388#endif 389 390void 391add_to_renaming_pragma_list (oldname, newname) 392 tree oldname, newname; 393{ 394 pending_redefine_extname 395 = tree_cons (oldname, newname, pending_redefine_extname); 396} 397 398static GTY(()) tree pragma_extern_prefix; 399 400#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 401static void handle_pragma_extern_prefix PARAMS ((cpp_reader *)); 402 403/* #pragma extern_prefix "prefix" */ 404static void 405handle_pragma_extern_prefix (dummy) 406 cpp_reader *dummy ATTRIBUTE_UNUSED; 407{ 408 tree prefix, x; 409 enum cpp_ttype t; 410 411 if (c_lex (&prefix) != CPP_STRING) 412 { 413 warning ("malformed #pragma extern_prefix, ignored"); 414 return; 415 } 416 t = c_lex (&x); 417 if (t != CPP_EOF) 418 warning ("junk at end of #pragma extern_prefix"); 419 420 /* Note that the length includes the null terminator. */ 421 pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL); 422} 423#endif 424 425/* Hook from the front ends to apply the results of one of the preceeding 426 pragmas that rename variables. */ 427 428tree 429maybe_apply_renaming_pragma (decl, asmname) 430 tree decl, 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 484void 485init_pragma () 486{ 487#ifdef HANDLE_PRAGMA_PACK 488 cpp_register_pragma (parse_in, 0, "pack", handle_pragma_pack); 489#endif 490#ifdef HANDLE_PRAGMA_WEAK 491 cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak); 492#endif 493#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME 494 cpp_register_pragma (parse_in, 0, "redefine_extname", 495 handle_pragma_redefine_extname); 496#endif 497#ifdef HANDLE_PRAGMA_EXTERN_PREFIX 498 cpp_register_pragma (parse_in, 0, "extern_prefix", 499 handle_pragma_extern_prefix); 500#endif 501 502#ifdef REGISTER_TARGET_PRAGMAS 503 REGISTER_TARGET_PRAGMAS (parse_in); 504#endif 505} 506 507#include "gt-c-pragma.h" 508