1/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. 2 3 Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4 Contributed by Jason Merrill <jason@redhat.com> 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to the Free 20Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 2102110-1301, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "coretypes.h" 26#include "tm.h" 27#include "tree.h" 28#include "cp-tree.h" 29#include "c-common.h" 30#include "toplev.h" 31#include "tree-gimple.h" 32#include "hashtab.h" 33#include "pointer-set.h" 34#include "flags.h" 35 36/* Local declarations. */ 37 38enum bc_t { bc_break = 0, bc_continue = 1 }; 39 40/* Stack of labels which are targets for "break" or "continue", 41 linked through TREE_CHAIN. */ 42static tree bc_label[2]; 43 44/* Begin a scope which can be exited by a break or continue statement. BC 45 indicates which. 46 47 Just creates a label and pushes it into the current context. */ 48 49static tree 50begin_bc_block (enum bc_t bc) 51{ 52 tree label = create_artificial_label (); 53 TREE_CHAIN (label) = bc_label[bc]; 54 bc_label[bc] = label; 55 return label; 56} 57 58/* Finish a scope which can be exited by a break or continue statement. 59 LABEL was returned from the most recent call to begin_bc_block. BODY is 60 an expression for the contents of the scope. 61 62 If we saw a break (or continue) in the scope, append a LABEL_EXPR to 63 body. Otherwise, just forget the label. */ 64 65static tree 66finish_bc_block (enum bc_t bc, tree label, tree body) 67{ 68 gcc_assert (label == bc_label[bc]); 69 70 if (TREE_USED (label)) 71 { 72 tree t, sl = NULL; 73 74 t = build1 (LABEL_EXPR, void_type_node, label); 75 76 append_to_statement_list (body, &sl); 77 append_to_statement_list (t, &sl); 78 body = sl; 79 } 80 81 bc_label[bc] = TREE_CHAIN (label); 82 TREE_CHAIN (label) = NULL_TREE; 83 return body; 84} 85 86/* Build a GOTO_EXPR to represent a break or continue statement. BC 87 indicates which. */ 88 89static tree 90build_bc_goto (enum bc_t bc) 91{ 92 tree label = bc_label[bc]; 93 94 if (label == NULL_TREE) 95 { 96 if (bc == bc_break) 97 error ("break statement not within loop or switch"); 98 else 99 error ("continue statement not within loop or switch"); 100 101 return NULL_TREE; 102 } 103 104 /* Mark the label used for finish_bc_block. */ 105 TREE_USED (label) = 1; 106 return build1 (GOTO_EXPR, void_type_node, label); 107} 108 109/* Genericize a TRY_BLOCK. */ 110 111static void 112genericize_try_block (tree *stmt_p) 113{ 114 tree body = TRY_STMTS (*stmt_p); 115 tree cleanup = TRY_HANDLERS (*stmt_p); 116 117 gimplify_stmt (&body); 118 119 if (CLEANUP_P (*stmt_p)) 120 /* A cleanup is an expression, so it doesn't need to be genericized. */; 121 else 122 gimplify_stmt (&cleanup); 123 124 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); 125} 126 127/* Genericize a HANDLER by converting to a CATCH_EXPR. */ 128 129static void 130genericize_catch_block (tree *stmt_p) 131{ 132 tree type = HANDLER_TYPE (*stmt_p); 133 tree body = HANDLER_BODY (*stmt_p); 134 135 gimplify_stmt (&body); 136 137 /* FIXME should the caught type go in TREE_TYPE? */ 138 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); 139} 140 141/* Genericize an EH_SPEC_BLOCK by converting it to a 142 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ 143 144static void 145genericize_eh_spec_block (tree *stmt_p) 146{ 147 tree body = EH_SPEC_STMTS (*stmt_p); 148 tree allowed = EH_SPEC_RAISES (*stmt_p); 149 tree failure = build_call (call_unexpected_node, 150 tree_cons (NULL_TREE, build_exc_ptr (), 151 NULL_TREE)); 152 gimplify_stmt (&body); 153 154 *stmt_p = gimple_build_eh_filter (body, allowed, failure); 155} 156 157/* Genericize an IF_STMT by turning it into a COND_EXPR. */ 158 159static void 160gimplify_if_stmt (tree *stmt_p) 161{ 162 tree stmt, cond, then_, else_; 163 164 stmt = *stmt_p; 165 cond = IF_COND (stmt); 166 then_ = THEN_CLAUSE (stmt); 167 else_ = ELSE_CLAUSE (stmt); 168 169 if (!then_) 170 then_ = build_empty_stmt (); 171 if (!else_) 172 else_ = build_empty_stmt (); 173 174 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) 175 stmt = then_; 176 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) 177 stmt = else_; 178 else 179 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); 180 *stmt_p = stmt; 181} 182 183/* Build a generic representation of one of the C loop forms. COND is the 184 loop condition or NULL_TREE. BODY is the (possibly compound) statement 185 controlled by the loop. INCR is the increment expression of a for-loop, 186 or NULL_TREE. COND_IS_FIRST indicates whether the condition is 187 evaluated before the loop body as in while and for loops, or after the 188 loop body as in do-while loops. */ 189 190static tree 191/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 192gimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, 193 bool cond_is_first, tree inner_foreach) 194/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 195{ 196 tree top, entry, exit, cont_block, break_block, stmt_list, t; 197 location_t stmt_locus; 198 199 stmt_locus = input_location; 200 stmt_list = NULL_TREE; 201 entry = NULL_TREE; 202 203 /* APPLE LOCAL begin C* language */ 204 /* Order of label addition to stack is important for objc's foreach-stmt. */ 205 /* APPLE LOCAL radar 4667060 */ 206 if (inner_foreach == integer_zero_node) 207 { 208 cont_block = begin_bc_block (bc_continue); 209 break_block = begin_bc_block (bc_break); 210 } 211 else 212 { 213 break_block = begin_bc_block (bc_break); 214 cont_block = begin_bc_block (bc_continue); 215 } 216 /* APPLE LOCAL end C* language */ 217 218 /* If condition is zero don't generate a loop construct. */ 219 if (cond && integer_zerop (cond)) 220 { 221 top = NULL_TREE; 222 exit = NULL_TREE; 223 if (cond_is_first) 224 { 225 t = build_bc_goto (bc_break); 226 append_to_statement_list (t, &stmt_list); 227 } 228 } 229 else 230 { 231 /* If we use a LOOP_EXPR here, we have to feed the whole thing 232 back through the main gimplifier to lower it. Given that we 233 have to gimplify the loop body NOW so that we can resolve 234 break/continue stmts, seems easier to just expand to gotos. */ 235 top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 236 237 /* If we have an exit condition, then we build an IF with gotos either 238 out of the loop, or to the top of it. If there's no exit condition, 239 then we just build a jump back to the top. */ 240 exit = build_and_jump (&LABEL_EXPR_LABEL (top)); 241/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 242 243 /* Add the attributes to the 'top' label. */ 244 decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0); 245 246/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 247 if (cond && !integer_nonzerop (cond)) 248 { 249 t = build_bc_goto (bc_break); 250 exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); 251 gimplify_stmt (&exit); 252 253 if (cond_is_first) 254 { 255 if (incr) 256 { 257 entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 258 t = build_and_jump (&LABEL_EXPR_LABEL (entry)); 259 } 260 else 261 t = build_bc_goto (bc_continue); 262 append_to_statement_list (t, &stmt_list); 263 } 264 } 265 } 266 267 /* APPLE LOCAL begin radar 4547045 */ 268 /* Pop foreach's inner loop break label so outer loop's 269 break label becomes target of inner loop body's break statements. 270 */ 271 t = NULL_TREE; 272 gimplify_stmt (&body); 273 gimplify_stmt (&incr); 274 275 body = finish_bc_block (bc_continue, cont_block, body); 276 /* APPLE LOCAL begin radar 4547045 */ 277 /* Push back inner loop's own 'break' label so rest 278 of code works seemlessly. */ 279 /* APPLE LOCAL radar 4667060 */ 280 281 append_to_statement_list (top, &stmt_list); 282 append_to_statement_list (body, &stmt_list); 283 append_to_statement_list (incr, &stmt_list); 284 append_to_statement_list (entry, &stmt_list); 285 append_to_statement_list (exit, &stmt_list); 286 287 annotate_all_with_locus (&stmt_list, stmt_locus); 288 289 return finish_bc_block (bc_break, break_block, stmt_list); 290} 291 292/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the 293 prequeue and hand off to gimplify_cp_loop. */ 294 295static void 296gimplify_for_stmt (tree *stmt_p, tree *pre_p) 297{ 298 tree stmt = *stmt_p; 299 300 if (FOR_INIT_STMT (stmt)) 301 gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); 302 303/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 304 *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), 305 FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1, 306 NULL_TREE); 307/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 308} 309 310/* Gimplify a WHILE_STMT node. */ 311 312static void 313gimplify_while_stmt (tree *stmt_p) 314{ 315 tree stmt = *stmt_p; 316/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 317 *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), 318 NULL_TREE, WHILE_ATTRIBUTES (stmt), 1, 319 NULL_TREE); 320/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 321} 322 323/* Gimplify a DO_STMT node. */ 324 325static void 326gimplify_do_stmt (tree *stmt_p) 327{ 328 tree stmt = *stmt_p; 329/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 330 *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), 331 NULL_TREE, DO_ATTRIBUTES (stmt), 0, 332 DO_FOREACH (stmt)); 333/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 334} 335 336/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ 337 338static void 339gimplify_switch_stmt (tree *stmt_p) 340{ 341 tree stmt = *stmt_p; 342 tree break_block, body; 343 location_t stmt_locus = input_location; 344 345 break_block = begin_bc_block (bc_break); 346 347 body = SWITCH_STMT_BODY (stmt); 348 if (!body) 349 body = build_empty_stmt (); 350 351 *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), 352 SWITCH_STMT_COND (stmt), body, NULL_TREE); 353 SET_EXPR_LOCATION (*stmt_p, stmt_locus); 354 gimplify_stmt (stmt_p); 355 356 *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); 357} 358 359/* Hook into the middle of gimplifying an OMP_FOR node. This is required 360 in order to properly gimplify CONTINUE statements. Here we merely 361 manage the continue stack; the rest of the job is performed by the 362 regular gimplifier. */ 363 364static enum gimplify_status 365cp_gimplify_omp_for (tree *expr_p) 366{ 367 tree for_stmt = *expr_p; 368 tree cont_block; 369 370 /* Protect ourselves from recursion. */ 371 if (OMP_FOR_GIMPLIFYING_P (for_stmt)) 372 return GS_UNHANDLED; 373 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; 374 375 /* Note that while technically the continue label is enabled too soon 376 here, we should have already diagnosed invalid continues nested within 377 statement expressions within the INIT, COND, or INCR expressions. */ 378 cont_block = begin_bc_block (bc_continue); 379 380 gimplify_stmt (expr_p); 381 382 OMP_FOR_BODY (for_stmt) 383 = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt)); 384 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; 385 386 return GS_ALL_DONE; 387} 388 389/* Gimplify an EXPR_STMT node. */ 390 391static void 392gimplify_expr_stmt (tree *stmt_p) 393{ 394 tree stmt = EXPR_STMT_EXPR (*stmt_p); 395 396 if (stmt == error_mark_node) 397 stmt = NULL; 398 399 /* Gimplification of a statement expression will nullify the 400 statement if all its side effects are moved to *PRE_P and *POST_P. 401 402 In this case we will not want to emit the gimplified statement. 403 However, we may still want to emit a warning, so we do that before 404 gimplification. */ 405 if (stmt && (extra_warnings || warn_unused_value)) 406 { 407 if (!TREE_SIDE_EFFECTS (stmt)) 408 { 409 if (!IS_EMPTY_STMT (stmt) 410 && !VOID_TYPE_P (TREE_TYPE (stmt)) 411 && !TREE_NO_WARNING (stmt)) 412 warning (OPT_Wextra, "statement with no effect"); 413 } 414 else if (warn_unused_value) 415 warn_if_unused_value (stmt, input_location); 416 } 417 418 if (stmt == NULL_TREE) 419 stmt = alloc_stmt_list (); 420 421 *stmt_p = stmt; 422} 423 424/* Gimplify initialization from an AGGR_INIT_EXPR. */ 425 426static void 427cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) 428{ 429 tree from = TREE_OPERAND (*expr_p, 1); 430 tree to = TREE_OPERAND (*expr_p, 0); 431 tree sub; 432 433 /* What about code that pulls out the temp and uses it elsewhere? I 434 think that such code never uses the TARGET_EXPR as an initializer. If 435 I'm wrong, we'll abort because the temp won't have any RTL. In that 436 case, I guess we'll need to replace references somehow. */ 437 if (TREE_CODE (from) == TARGET_EXPR) 438 from = TARGET_EXPR_INITIAL (from); 439 440 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them 441 inside the TARGET_EXPR. */ 442 sub = expr_last (from); 443 444 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and 445 replace the slot operand with our target. 446 447 Should we add a target parm to gimplify_expr instead? No, as in this 448 case we want to replace the INIT_EXPR. */ 449 if (TREE_CODE (sub) == AGGR_INIT_EXPR) 450 { 451 gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); 452 TREE_OPERAND (sub, 2) = to; 453 *expr_p = from; 454 455 /* The initialization is now a side-effect, so the container can 456 become void. */ 457 if (from != sub) 458 TREE_TYPE (from) = void_type_node; 459 } 460} 461 462/* Gimplify a MUST_NOT_THROW_EXPR. */ 463 464static void 465gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) 466{ 467 tree stmt = *expr_p; 468 tree temp = voidify_wrapper_expr (stmt, NULL); 469 tree body = TREE_OPERAND (stmt, 0); 470 471 gimplify_stmt (&body); 472 473 stmt = gimple_build_eh_filter (body, NULL_TREE, 474 build_call (terminate_node, NULL_TREE)); 475 476 if (temp) 477 { 478 append_to_statement_list (stmt, pre_p); 479 *expr_p = temp; 480 } 481 else 482 *expr_p = stmt; 483} 484 485/* Do C++-specific gimplification. Args are as for gimplify_expr. */ 486 487int 488cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) 489{ 490 int saved_stmts_are_full_exprs_p = 0; 491 enum tree_code code = TREE_CODE (*expr_p); 492 enum gimplify_status ret; 493 494 if (STATEMENT_CODE_P (code)) 495 { 496 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); 497 current_stmt_tree ()->stmts_are_full_exprs_p 498 = STMT_IS_FULL_EXPR_P (*expr_p); 499 } 500 501 switch (code) 502 { 503 case PTRMEM_CST: 504 *expr_p = cplus_expand_constant (*expr_p); 505 ret = GS_OK; 506 break; 507 508 case AGGR_INIT_EXPR: 509 simplify_aggr_init_expr (expr_p); 510 ret = GS_OK; 511 break; 512 513 case THROW_EXPR: 514 /* FIXME communicate throw type to backend, probably by moving 515 THROW_EXPR into ../tree.def. */ 516 *expr_p = TREE_OPERAND (*expr_p, 0); 517 ret = GS_OK; 518 break; 519 520 case MUST_NOT_THROW_EXPR: 521 gimplify_must_not_throw_expr (expr_p, pre_p); 522 ret = GS_OK; 523 break; 524 525 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the 526 LHS of an assignment might also be involved in the RHS, as in bug 527 25979. */ 528 case INIT_EXPR: 529 cp_gimplify_init_expr (expr_p, pre_p, post_p); 530 ret = GS_OK; 531 break; 532 533 case EMPTY_CLASS_EXPR: 534 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ 535 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); 536 ret = GS_OK; 537 break; 538 539 case BASELINK: 540 *expr_p = BASELINK_FUNCTIONS (*expr_p); 541 ret = GS_OK; 542 break; 543 544 case TRY_BLOCK: 545 genericize_try_block (expr_p); 546 ret = GS_OK; 547 break; 548 549 case HANDLER: 550 genericize_catch_block (expr_p); 551 ret = GS_OK; 552 break; 553 554 case EH_SPEC_BLOCK: 555 genericize_eh_spec_block (expr_p); 556 ret = GS_OK; 557 break; 558 559 case USING_STMT: 560 /* Just ignore for now. Eventually we will want to pass this on to 561 the debugger. */ 562 *expr_p = build_empty_stmt (); 563 ret = GS_ALL_DONE; 564 break; 565 566 case IF_STMT: 567 gimplify_if_stmt (expr_p); 568 ret = GS_OK; 569 break; 570 571 case FOR_STMT: 572 gimplify_for_stmt (expr_p, pre_p); 573 ret = GS_ALL_DONE; 574 break; 575 576 case WHILE_STMT: 577 gimplify_while_stmt (expr_p); 578 ret = GS_ALL_DONE; 579 break; 580 581 case DO_STMT: 582 gimplify_do_stmt (expr_p); 583 ret = GS_ALL_DONE; 584 break; 585 586 case SWITCH_STMT: 587 gimplify_switch_stmt (expr_p); 588 ret = GS_ALL_DONE; 589 break; 590 591 case OMP_FOR: 592 ret = cp_gimplify_omp_for (expr_p); 593 break; 594 595 case CONTINUE_STMT: 596 *expr_p = build_bc_goto (bc_continue); 597 ret = GS_ALL_DONE; 598 break; 599 600 case BREAK_STMT: 601 *expr_p = build_bc_goto (bc_break); 602 ret = GS_ALL_DONE; 603 break; 604 605 case EXPR_STMT: 606 gimplify_expr_stmt (expr_p); 607 ret = GS_OK; 608 break; 609 610 case UNARY_PLUS_EXPR: 611 { 612 tree arg = TREE_OPERAND (*expr_p, 0); 613 tree type = TREE_TYPE (*expr_p); 614 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) 615 : arg; 616 ret = GS_OK; 617 } 618 break; 619 620 default: 621 ret = c_gimplify_expr (expr_p, pre_p, post_p); 622 break; 623 } 624 625 /* Restore saved state. */ 626 if (STATEMENT_CODE_P (code)) 627 current_stmt_tree ()->stmts_are_full_exprs_p 628 = saved_stmts_are_full_exprs_p; 629 630 return ret; 631} 632 633static inline bool 634is_invisiref_parm (tree t) 635{ 636 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) 637 && DECL_BY_REFERENCE (t)); 638} 639 640/* Return true if the uid in both int tree maps are equal. */ 641 642int 643cxx_int_tree_map_eq (const void *va, const void *vb) 644{ 645 const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; 646 const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; 647 return (a->uid == b->uid); 648} 649 650/* Hash a UID in a cxx_int_tree_map. */ 651 652unsigned int 653cxx_int_tree_map_hash (const void *item) 654{ 655 return ((const struct cxx_int_tree_map *)item)->uid; 656} 657 658/* Perform any pre-gimplification lowering of C++ front end trees to 659 GENERIC. */ 660 661static tree 662cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) 663{ 664 tree stmt = *stmt_p; 665 struct pointer_set_t *p_set = (struct pointer_set_t*) data; 666 667 if (is_invisiref_parm (stmt) 668 /* Don't dereference parms in a thunk, pass the references through. */ 669 && !(DECL_THUNK_P (current_function_decl) 670 && TREE_CODE (stmt) == PARM_DECL)) 671 { 672 *stmt_p = convert_from_reference (stmt); 673 *walk_subtrees = 0; 674 return NULL; 675 } 676 677 /* Map block scope extern declarations to visible declarations with the 678 same name and type in outer scopes if any. */ 679 if (cp_function_chain->extern_decl_map 680 && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) 681 && DECL_EXTERNAL (stmt)) 682 { 683 struct cxx_int_tree_map *h, in; 684 in.uid = DECL_UID (stmt); 685 h = (struct cxx_int_tree_map *) 686 htab_find_with_hash (cp_function_chain->extern_decl_map, 687 &in, in.uid); 688 if (h) 689 { 690 *stmt_p = h->to; 691 *walk_subtrees = 0; 692 return NULL; 693 } 694 } 695 696 /* Other than invisiref parms, don't walk the same tree twice. */ 697 if (pointer_set_contains (p_set, stmt)) 698 { 699 *walk_subtrees = 0; 700 return NULL_TREE; 701 } 702 703 if (TREE_CODE (stmt) == ADDR_EXPR 704 && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 705 { 706 *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); 707 *walk_subtrees = 0; 708 } 709 else if (TREE_CODE (stmt) == RETURN_EXPR 710 && TREE_OPERAND (stmt, 0) 711 && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 712 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ 713 *walk_subtrees = 0; 714 else if (TREE_CODE (stmt) == OMP_CLAUSE) 715 switch (OMP_CLAUSE_CODE (stmt)) 716 { 717 case OMP_CLAUSE_PRIVATE: 718 case OMP_CLAUSE_SHARED: 719 case OMP_CLAUSE_FIRSTPRIVATE: 720 case OMP_CLAUSE_LASTPRIVATE: 721 case OMP_CLAUSE_COPYIN: 722 case OMP_CLAUSE_COPYPRIVATE: 723 /* Don't dereference an invisiref in OpenMP clauses. */ 724 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) 725 *walk_subtrees = 0; 726 break; 727 case OMP_CLAUSE_REDUCTION: 728 gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); 729 break; 730 default: 731 break; 732 } 733 else if (IS_TYPE_OR_DECL_P (stmt)) 734 *walk_subtrees = 0; 735 736 /* Due to the way voidify_wrapper_expr is written, we don't get a chance 737 to lower this construct before scanning it, so we need to lower these 738 before doing anything else. */ 739 else if (TREE_CODE (stmt) == CLEANUP_STMT) 740 *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR 741 : TRY_FINALLY_EXPR, 742 void_type_node, 743 CLEANUP_BODY (stmt), 744 CLEANUP_EXPR (stmt)); 745 746 pointer_set_insert (p_set, *stmt_p); 747 748 return NULL; 749} 750 751void 752cp_genericize (tree fndecl) 753{ 754 tree t; 755 struct pointer_set_t *p_set; 756 757 /* Fix up the types of parms passed by invisible reference. */ 758 for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) 759 if (TREE_ADDRESSABLE (TREE_TYPE (t))) 760 { 761 /* If a function's arguments are copied to create a thunk, 762 then DECL_BY_REFERENCE will be set -- but the type of the 763 argument will be a pointer type, so we will never get 764 here. */ 765 gcc_assert (!DECL_BY_REFERENCE (t)); 766 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); 767 TREE_TYPE (t) = DECL_ARG_TYPE (t); 768 DECL_BY_REFERENCE (t) = 1; 769 TREE_ADDRESSABLE (t) = 0; 770 relayout_decl (t); 771 } 772 773 /* Do the same for the return value. */ 774 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) 775 { 776 t = DECL_RESULT (fndecl); 777 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); 778 DECL_BY_REFERENCE (t) = 1; 779 TREE_ADDRESSABLE (t) = 0; 780 relayout_decl (t); 781 } 782 783 /* If we're a clone, the body is already GIMPLE. */ 784 if (DECL_CLONED_FUNCTION_P (fndecl)) 785 return; 786 787 /* We do want to see every occurrence of the parms, so we can't just use 788 walk_tree's hash functionality. */ 789 p_set = pointer_set_create (); 790 walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); 791 pointer_set_destroy (p_set); 792 793 /* Do everything else. */ 794 c_genericize (fndecl); 795 796 gcc_assert (bc_label[bc_break] == NULL); 797 gcc_assert (bc_label[bc_continue] == NULL); 798} 799 800/* Build code to apply FN to each member of ARG1 and ARG2. FN may be 801 NULL if there is in fact nothing to do. ARG2 may be null if FN 802 actually only takes one argument. */ 803 804static tree 805cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) 806{ 807 tree defparm, parm; 808 int i; 809 810 if (fn == NULL) 811 return NULL; 812 813 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); 814 if (arg2) 815 defparm = TREE_CHAIN (defparm); 816 817 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) 818 { 819 tree inner_type = TREE_TYPE (arg1); 820 tree start1, end1, p1; 821 tree start2 = NULL, p2 = NULL; 822 tree ret = NULL, lab, t; 823 824 start1 = arg1; 825 start2 = arg2; 826 do 827 { 828 inner_type = TREE_TYPE (inner_type); 829 start1 = build4 (ARRAY_REF, inner_type, start1, 830 size_zero_node, NULL, NULL); 831 if (arg2) 832 start2 = build4 (ARRAY_REF, inner_type, start2, 833 size_zero_node, NULL, NULL); 834 } 835 while (TREE_CODE (inner_type) == ARRAY_TYPE); 836 start1 = build_fold_addr_expr (start1); 837 if (arg2) 838 start2 = build_fold_addr_expr (start2); 839 840 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); 841 end1 = fold_convert (TREE_TYPE (start1), end1); 842 end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); 843 844 p1 = create_tmp_var (TREE_TYPE (start1), NULL); 845 t = build2 (MODIFY_EXPR, void_type_node, p1, start1); 846 append_to_statement_list (t, &ret); 847 848 if (arg2) 849 { 850 p2 = create_tmp_var (TREE_TYPE (start2), NULL); 851 t = build2 (MODIFY_EXPR, void_type_node, p2, start2); 852 append_to_statement_list (t, &ret); 853 } 854 855 lab = create_artificial_label (); 856 t = build1 (LABEL_EXPR, void_type_node, lab); 857 append_to_statement_list (t, &ret); 858 859 t = tree_cons (NULL, p1, NULL); 860 if (arg2) 861 t = tree_cons (NULL, p2, t); 862 /* Handle default arguments. */ 863 i = 1 + (arg2 != NULL); 864 for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 865 t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 866 TREE_PURPOSE (parm), 867 fn, i++), t); 868 t = build_call (fn, nreverse (t)); 869 append_to_statement_list (t, &ret); 870 871 t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); 872 t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); 873 t = build2 (MODIFY_EXPR, void_type_node, p1, t); 874 append_to_statement_list (t, &ret); 875 876 if (arg2) 877 { 878 t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); 879 t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); 880 t = build2 (MODIFY_EXPR, void_type_node, p2, t); 881 append_to_statement_list (t, &ret); 882 } 883 884 t = build2 (NE_EXPR, boolean_type_node, p1, end1); 885 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); 886 append_to_statement_list (t, &ret); 887 888 return ret; 889 } 890 else 891 { 892 tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); 893 if (arg2) 894 t = tree_cons (NULL, build_fold_addr_expr (arg2), t); 895 /* Handle default arguments. */ 896 i = 1 + (arg2 != NULL); 897 for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 898 t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 899 TREE_PURPOSE (parm), 900 fn, i++), t); 901 return build_call (fn, nreverse (t)); 902 } 903} 904 905/* Return code to initialize DECL with its default constructor, or 906 NULL if there's nothing to do. */ 907 908tree 909cxx_omp_clause_default_ctor (tree clause, tree decl) 910{ 911 tree info = CP_OMP_CLAUSE_INFO (clause); 912 tree ret = NULL; 913 914 if (info) 915 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); 916 917 return ret; 918} 919 920/* Return code to initialize DST with a copy constructor from SRC. */ 921 922tree 923cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) 924{ 925 tree info = CP_OMP_CLAUSE_INFO (clause); 926 tree ret = NULL; 927 928 if (info) 929 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); 930 if (ret == NULL) 931 ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 932 933 return ret; 934} 935 936/* Similarly, except use an assignment operator instead. */ 937 938tree 939cxx_omp_clause_assign_op (tree clause, tree dst, tree src) 940{ 941 tree info = CP_OMP_CLAUSE_INFO (clause); 942 tree ret = NULL; 943 944 if (info) 945 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); 946 if (ret == NULL) 947 ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 948 949 return ret; 950} 951 952/* Return code to destroy DECL. */ 953 954tree 955cxx_omp_clause_dtor (tree clause, tree decl) 956{ 957 tree info = CP_OMP_CLAUSE_INFO (clause); 958 tree ret = NULL; 959 960 if (info) 961 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); 962 963 return ret; 964} 965 966/* True if OpenMP should privatize what this DECL points to rather 967 than the DECL itself. */ 968 969bool 970cxx_omp_privatize_by_reference (tree decl) 971{ 972 return is_invisiref_parm (decl); 973} 974