1169689Skan/* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. 2169689Skan 3169689Skan Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 4169689Skan Contributed by Jason Merrill <jason@redhat.com> 5169689Skan 6169689SkanThis file is part of GCC. 7169689Skan 8169689SkanGCC is free software; you can redistribute it and/or modify it under 9169689Skanthe terms of the GNU General Public License as published by the Free 10169689SkanSoftware Foundation; either version 2, or (at your option) any later 11169689Skanversion. 12169689Skan 13169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 15169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16169689Skanfor more details. 17169689Skan 18169689SkanYou should have received a copy of the GNU General Public License 19169689Skanalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 22169689Skan 23169689Skan#include "config.h" 24169689Skan#include "system.h" 25169689Skan#include "coretypes.h" 26169689Skan#include "tm.h" 27169689Skan#include "tree.h" 28169689Skan#include "cp-tree.h" 29169689Skan#include "c-common.h" 30169689Skan#include "toplev.h" 31169689Skan#include "tree-gimple.h" 32169689Skan#include "hashtab.h" 33169689Skan#include "pointer-set.h" 34169689Skan#include "flags.h" 35169689Skan 36169689Skan/* Local declarations. */ 37169689Skan 38169689Skanenum bc_t { bc_break = 0, bc_continue = 1 }; 39169689Skan 40169689Skan/* Stack of labels which are targets for "break" or "continue", 41169689Skan linked through TREE_CHAIN. */ 42169689Skanstatic tree bc_label[2]; 43169689Skan 44169689Skan/* Begin a scope which can be exited by a break or continue statement. BC 45169689Skan indicates which. 46169689Skan 47169689Skan Just creates a label and pushes it into the current context. */ 48169689Skan 49169689Skanstatic tree 50169689Skanbegin_bc_block (enum bc_t bc) 51169689Skan{ 52169689Skan tree label = create_artificial_label (); 53169689Skan TREE_CHAIN (label) = bc_label[bc]; 54169689Skan bc_label[bc] = label; 55169689Skan return label; 56169689Skan} 57169689Skan 58169689Skan/* Finish a scope which can be exited by a break or continue statement. 59169689Skan LABEL was returned from the most recent call to begin_bc_block. BODY is 60169689Skan an expression for the contents of the scope. 61169689Skan 62169689Skan If we saw a break (or continue) in the scope, append a LABEL_EXPR to 63169689Skan body. Otherwise, just forget the label. */ 64169689Skan 65169689Skanstatic tree 66169689Skanfinish_bc_block (enum bc_t bc, tree label, tree body) 67169689Skan{ 68169689Skan gcc_assert (label == bc_label[bc]); 69169689Skan 70169689Skan if (TREE_USED (label)) 71169689Skan { 72169689Skan tree t, sl = NULL; 73169689Skan 74169689Skan t = build1 (LABEL_EXPR, void_type_node, label); 75169689Skan 76169689Skan append_to_statement_list (body, &sl); 77169689Skan append_to_statement_list (t, &sl); 78169689Skan body = sl; 79169689Skan } 80169689Skan 81169689Skan bc_label[bc] = TREE_CHAIN (label); 82169689Skan TREE_CHAIN (label) = NULL_TREE; 83169689Skan return body; 84169689Skan} 85169689Skan 86169689Skan/* Build a GOTO_EXPR to represent a break or continue statement. BC 87169689Skan indicates which. */ 88169689Skan 89169689Skanstatic tree 90169689Skanbuild_bc_goto (enum bc_t bc) 91169689Skan{ 92169689Skan tree label = bc_label[bc]; 93169689Skan 94169689Skan if (label == NULL_TREE) 95169689Skan { 96169689Skan if (bc == bc_break) 97169689Skan error ("break statement not within loop or switch"); 98169689Skan else 99169689Skan error ("continue statement not within loop or switch"); 100169689Skan 101169689Skan return NULL_TREE; 102169689Skan } 103169689Skan 104169689Skan /* Mark the label used for finish_bc_block. */ 105169689Skan TREE_USED (label) = 1; 106169689Skan return build1 (GOTO_EXPR, void_type_node, label); 107169689Skan} 108169689Skan 109169689Skan/* Genericize a TRY_BLOCK. */ 110169689Skan 111169689Skanstatic void 112169689Skangenericize_try_block (tree *stmt_p) 113169689Skan{ 114169689Skan tree body = TRY_STMTS (*stmt_p); 115169689Skan tree cleanup = TRY_HANDLERS (*stmt_p); 116169689Skan 117169689Skan gimplify_stmt (&body); 118169689Skan 119169689Skan if (CLEANUP_P (*stmt_p)) 120169689Skan /* A cleanup is an expression, so it doesn't need to be genericized. */; 121169689Skan else 122169689Skan gimplify_stmt (&cleanup); 123169689Skan 124169689Skan *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); 125169689Skan} 126169689Skan 127169689Skan/* Genericize a HANDLER by converting to a CATCH_EXPR. */ 128169689Skan 129169689Skanstatic void 130169689Skangenericize_catch_block (tree *stmt_p) 131169689Skan{ 132169689Skan tree type = HANDLER_TYPE (*stmt_p); 133169689Skan tree body = HANDLER_BODY (*stmt_p); 134169689Skan 135169689Skan gimplify_stmt (&body); 136169689Skan 137169689Skan /* FIXME should the caught type go in TREE_TYPE? */ 138169689Skan *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); 139169689Skan} 140169689Skan 141169689Skan/* Genericize an EH_SPEC_BLOCK by converting it to a 142169689Skan TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ 143169689Skan 144169689Skanstatic void 145169689Skangenericize_eh_spec_block (tree *stmt_p) 146169689Skan{ 147169689Skan tree body = EH_SPEC_STMTS (*stmt_p); 148169689Skan tree allowed = EH_SPEC_RAISES (*stmt_p); 149169689Skan tree failure = build_call (call_unexpected_node, 150169689Skan tree_cons (NULL_TREE, build_exc_ptr (), 151169689Skan NULL_TREE)); 152169689Skan gimplify_stmt (&body); 153169689Skan 154169689Skan *stmt_p = gimple_build_eh_filter (body, allowed, failure); 155169689Skan} 156169689Skan 157169689Skan/* Genericize an IF_STMT by turning it into a COND_EXPR. */ 158169689Skan 159169689Skanstatic void 160169689Skangimplify_if_stmt (tree *stmt_p) 161169689Skan{ 162169689Skan tree stmt, cond, then_, else_; 163169689Skan 164169689Skan stmt = *stmt_p; 165169689Skan cond = IF_COND (stmt); 166169689Skan then_ = THEN_CLAUSE (stmt); 167169689Skan else_ = ELSE_CLAUSE (stmt); 168169689Skan 169169689Skan if (!then_) 170169689Skan then_ = build_empty_stmt (); 171169689Skan if (!else_) 172169689Skan else_ = build_empty_stmt (); 173169689Skan 174169689Skan if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) 175169689Skan stmt = then_; 176169689Skan else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) 177169689Skan stmt = else_; 178169689Skan else 179169689Skan stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); 180169689Skan *stmt_p = stmt; 181169689Skan} 182169689Skan 183169689Skan/* Build a generic representation of one of the C loop forms. COND is the 184169689Skan loop condition or NULL_TREE. BODY is the (possibly compound) statement 185169689Skan controlled by the loop. INCR is the increment expression of a for-loop, 186169689Skan or NULL_TREE. COND_IS_FIRST indicates whether the condition is 187169689Skan evaluated before the loop body as in while and for loops, or after the 188169689Skan loop body as in do-while loops. */ 189169689Skan 190169689Skanstatic tree 191169689Skangimplify_cp_loop (tree cond, tree body, tree incr, bool cond_is_first) 192169689Skan{ 193169689Skan tree top, entry, exit, cont_block, break_block, stmt_list, t; 194169689Skan location_t stmt_locus; 195169689Skan 196169689Skan stmt_locus = input_location; 197169689Skan stmt_list = NULL_TREE; 198169689Skan entry = NULL_TREE; 199169689Skan 200169689Skan break_block = begin_bc_block (bc_break); 201169689Skan cont_block = begin_bc_block (bc_continue); 202169689Skan 203169689Skan /* If condition is zero don't generate a loop construct. */ 204169689Skan if (cond && integer_zerop (cond)) 205169689Skan { 206169689Skan top = NULL_TREE; 207169689Skan exit = NULL_TREE; 208169689Skan if (cond_is_first) 209169689Skan { 210169689Skan t = build_bc_goto (bc_break); 211169689Skan append_to_statement_list (t, &stmt_list); 212169689Skan } 213169689Skan } 214169689Skan else 215169689Skan { 216169689Skan /* If we use a LOOP_EXPR here, we have to feed the whole thing 217169689Skan back through the main gimplifier to lower it. Given that we 218169689Skan have to gimplify the loop body NOW so that we can resolve 219169689Skan break/continue stmts, seems easier to just expand to gotos. */ 220169689Skan top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 221169689Skan 222169689Skan /* If we have an exit condition, then we build an IF with gotos either 223169689Skan out of the loop, or to the top of it. If there's no exit condition, 224169689Skan then we just build a jump back to the top. */ 225169689Skan exit = build_and_jump (&LABEL_EXPR_LABEL (top)); 226169689Skan if (cond && !integer_nonzerop (cond)) 227169689Skan { 228169689Skan t = build_bc_goto (bc_break); 229169689Skan exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); 230169689Skan gimplify_stmt (&exit); 231169689Skan 232169689Skan if (cond_is_first) 233169689Skan { 234169689Skan if (incr) 235169689Skan { 236169689Skan entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 237169689Skan t = build_and_jump (&LABEL_EXPR_LABEL (entry)); 238169689Skan } 239169689Skan else 240169689Skan t = build_bc_goto (bc_continue); 241169689Skan append_to_statement_list (t, &stmt_list); 242169689Skan } 243169689Skan } 244169689Skan } 245169689Skan 246169689Skan gimplify_stmt (&body); 247169689Skan gimplify_stmt (&incr); 248169689Skan 249169689Skan body = finish_bc_block (bc_continue, cont_block, body); 250169689Skan 251169689Skan append_to_statement_list (top, &stmt_list); 252169689Skan append_to_statement_list (body, &stmt_list); 253169689Skan append_to_statement_list (incr, &stmt_list); 254169689Skan append_to_statement_list (entry, &stmt_list); 255169689Skan append_to_statement_list (exit, &stmt_list); 256169689Skan 257169689Skan annotate_all_with_locus (&stmt_list, stmt_locus); 258169689Skan 259169689Skan return finish_bc_block (bc_break, break_block, stmt_list); 260169689Skan} 261169689Skan 262169689Skan/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the 263169689Skan prequeue and hand off to gimplify_cp_loop. */ 264169689Skan 265169689Skanstatic void 266169689Skangimplify_for_stmt (tree *stmt_p, tree *pre_p) 267169689Skan{ 268169689Skan tree stmt = *stmt_p; 269169689Skan 270169689Skan if (FOR_INIT_STMT (stmt)) 271169689Skan gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); 272169689Skan 273169689Skan *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), 274169689Skan FOR_EXPR (stmt), 1); 275169689Skan} 276169689Skan 277169689Skan/* Gimplify a WHILE_STMT node. */ 278169689Skan 279169689Skanstatic void 280169689Skangimplify_while_stmt (tree *stmt_p) 281169689Skan{ 282169689Skan tree stmt = *stmt_p; 283169689Skan *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), 284169689Skan NULL_TREE, 1); 285169689Skan} 286169689Skan 287169689Skan/* Gimplify a DO_STMT node. */ 288169689Skan 289169689Skanstatic void 290169689Skangimplify_do_stmt (tree *stmt_p) 291169689Skan{ 292169689Skan tree stmt = *stmt_p; 293169689Skan *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), 294169689Skan NULL_TREE, 0); 295169689Skan} 296169689Skan 297169689Skan/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ 298169689Skan 299169689Skanstatic void 300169689Skangimplify_switch_stmt (tree *stmt_p) 301169689Skan{ 302169689Skan tree stmt = *stmt_p; 303169689Skan tree break_block, body; 304169689Skan location_t stmt_locus = input_location; 305169689Skan 306169689Skan break_block = begin_bc_block (bc_break); 307169689Skan 308169689Skan body = SWITCH_STMT_BODY (stmt); 309169689Skan if (!body) 310169689Skan body = build_empty_stmt (); 311169689Skan 312169689Skan *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), 313169689Skan SWITCH_STMT_COND (stmt), body, NULL_TREE); 314169689Skan SET_EXPR_LOCATION (*stmt_p, stmt_locus); 315169689Skan gimplify_stmt (stmt_p); 316169689Skan 317169689Skan *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); 318169689Skan} 319169689Skan 320169689Skan/* Hook into the middle of gimplifying an OMP_FOR node. This is required 321169689Skan in order to properly gimplify CONTINUE statements. Here we merely 322169689Skan manage the continue stack; the rest of the job is performed by the 323169689Skan regular gimplifier. */ 324169689Skan 325169689Skanstatic enum gimplify_status 326169689Skancp_gimplify_omp_for (tree *expr_p) 327169689Skan{ 328169689Skan tree for_stmt = *expr_p; 329169689Skan tree cont_block; 330169689Skan 331169689Skan /* Protect ourselves from recursion. */ 332169689Skan if (OMP_FOR_GIMPLIFYING_P (for_stmt)) 333169689Skan return GS_UNHANDLED; 334169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; 335169689Skan 336169689Skan /* Note that while technically the continue label is enabled too soon 337169689Skan here, we should have already diagnosed invalid continues nested within 338169689Skan statement expressions within the INIT, COND, or INCR expressions. */ 339169689Skan cont_block = begin_bc_block (bc_continue); 340169689Skan 341169689Skan gimplify_stmt (expr_p); 342169689Skan 343169689Skan OMP_FOR_BODY (for_stmt) 344169689Skan = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt)); 345169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; 346169689Skan 347169689Skan return GS_ALL_DONE; 348169689Skan} 349169689Skan 350169689Skan/* Gimplify an EXPR_STMT node. */ 351169689Skan 352169689Skanstatic void 353169689Skangimplify_expr_stmt (tree *stmt_p) 354169689Skan{ 355169689Skan tree stmt = EXPR_STMT_EXPR (*stmt_p); 356169689Skan 357169689Skan if (stmt == error_mark_node) 358169689Skan stmt = NULL; 359169689Skan 360169689Skan /* Gimplification of a statement expression will nullify the 361169689Skan statement if all its side effects are moved to *PRE_P and *POST_P. 362169689Skan 363169689Skan In this case we will not want to emit the gimplified statement. 364169689Skan However, we may still want to emit a warning, so we do that before 365169689Skan gimplification. */ 366169689Skan if (stmt && (extra_warnings || warn_unused_value)) 367169689Skan { 368169689Skan if (!TREE_SIDE_EFFECTS (stmt)) 369169689Skan { 370169689Skan if (!IS_EMPTY_STMT (stmt) 371169689Skan && !VOID_TYPE_P (TREE_TYPE (stmt)) 372169689Skan && !TREE_NO_WARNING (stmt)) 373169689Skan warning (OPT_Wextra, "statement with no effect"); 374169689Skan } 375169689Skan else if (warn_unused_value) 376169689Skan warn_if_unused_value (stmt, input_location); 377169689Skan } 378169689Skan 379169689Skan if (stmt == NULL_TREE) 380169689Skan stmt = alloc_stmt_list (); 381169689Skan 382169689Skan *stmt_p = stmt; 383169689Skan} 384169689Skan 385169689Skan/* Gimplify initialization from an AGGR_INIT_EXPR. */ 386169689Skan 387169689Skanstatic void 388169689Skancp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) 389169689Skan{ 390169689Skan tree from = TREE_OPERAND (*expr_p, 1); 391169689Skan tree to = TREE_OPERAND (*expr_p, 0); 392169689Skan tree sub; 393169689Skan 394169689Skan /* What about code that pulls out the temp and uses it elsewhere? I 395169689Skan think that such code never uses the TARGET_EXPR as an initializer. If 396169689Skan I'm wrong, we'll abort because the temp won't have any RTL. In that 397169689Skan case, I guess we'll need to replace references somehow. */ 398169689Skan if (TREE_CODE (from) == TARGET_EXPR) 399169689Skan from = TARGET_EXPR_INITIAL (from); 400169689Skan 401169689Skan /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them 402169689Skan inside the TARGET_EXPR. */ 403169689Skan sub = expr_last (from); 404169689Skan 405169689Skan /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and 406169689Skan replace the slot operand with our target. 407169689Skan 408169689Skan Should we add a target parm to gimplify_expr instead? No, as in this 409169689Skan case we want to replace the INIT_EXPR. */ 410169689Skan if (TREE_CODE (sub) == AGGR_INIT_EXPR) 411169689Skan { 412169689Skan gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); 413169689Skan TREE_OPERAND (sub, 2) = to; 414169689Skan *expr_p = from; 415169689Skan 416169689Skan /* The initialization is now a side-effect, so the container can 417169689Skan become void. */ 418169689Skan if (from != sub) 419169689Skan TREE_TYPE (from) = void_type_node; 420169689Skan } 421169689Skan} 422169689Skan 423169689Skan/* Gimplify a MUST_NOT_THROW_EXPR. */ 424169689Skan 425169689Skanstatic void 426169689Skangimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) 427169689Skan{ 428169689Skan tree stmt = *expr_p; 429169689Skan tree temp = voidify_wrapper_expr (stmt, NULL); 430169689Skan tree body = TREE_OPERAND (stmt, 0); 431169689Skan 432169689Skan gimplify_stmt (&body); 433169689Skan 434169689Skan stmt = gimple_build_eh_filter (body, NULL_TREE, 435169689Skan build_call (terminate_node, NULL_TREE)); 436169689Skan 437169689Skan if (temp) 438169689Skan { 439169689Skan append_to_statement_list (stmt, pre_p); 440169689Skan *expr_p = temp; 441169689Skan } 442169689Skan else 443169689Skan *expr_p = stmt; 444169689Skan} 445169689Skan 446169689Skan/* Do C++-specific gimplification. Args are as for gimplify_expr. */ 447169689Skan 448169689Skanint 449169689Skancp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) 450169689Skan{ 451169689Skan int saved_stmts_are_full_exprs_p = 0; 452169689Skan enum tree_code code = TREE_CODE (*expr_p); 453169689Skan enum gimplify_status ret; 454169689Skan 455169689Skan if (STATEMENT_CODE_P (code)) 456169689Skan { 457169689Skan saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); 458169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 459169689Skan = STMT_IS_FULL_EXPR_P (*expr_p); 460169689Skan } 461169689Skan 462169689Skan switch (code) 463169689Skan { 464169689Skan case PTRMEM_CST: 465169689Skan *expr_p = cplus_expand_constant (*expr_p); 466169689Skan ret = GS_OK; 467169689Skan break; 468169689Skan 469169689Skan case AGGR_INIT_EXPR: 470169689Skan simplify_aggr_init_expr (expr_p); 471169689Skan ret = GS_OK; 472169689Skan break; 473169689Skan 474169689Skan case THROW_EXPR: 475169689Skan /* FIXME communicate throw type to backend, probably by moving 476169689Skan THROW_EXPR into ../tree.def. */ 477169689Skan *expr_p = TREE_OPERAND (*expr_p, 0); 478169689Skan ret = GS_OK; 479169689Skan break; 480169689Skan 481169689Skan case MUST_NOT_THROW_EXPR: 482169689Skan gimplify_must_not_throw_expr (expr_p, pre_p); 483169689Skan ret = GS_OK; 484169689Skan break; 485169689Skan 486169689Skan /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the 487169689Skan LHS of an assignment might also be involved in the RHS, as in bug 488169689Skan 25979. */ 489169689Skan case INIT_EXPR: 490169689Skan cp_gimplify_init_expr (expr_p, pre_p, post_p); 491169689Skan ret = GS_OK; 492169689Skan break; 493169689Skan 494169689Skan case EMPTY_CLASS_EXPR: 495169689Skan /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ 496169689Skan *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); 497169689Skan ret = GS_OK; 498169689Skan break; 499169689Skan 500169689Skan case BASELINK: 501169689Skan *expr_p = BASELINK_FUNCTIONS (*expr_p); 502169689Skan ret = GS_OK; 503169689Skan break; 504169689Skan 505169689Skan case TRY_BLOCK: 506169689Skan genericize_try_block (expr_p); 507169689Skan ret = GS_OK; 508169689Skan break; 509169689Skan 510169689Skan case HANDLER: 511169689Skan genericize_catch_block (expr_p); 512169689Skan ret = GS_OK; 513169689Skan break; 514169689Skan 515169689Skan case EH_SPEC_BLOCK: 516169689Skan genericize_eh_spec_block (expr_p); 517169689Skan ret = GS_OK; 518169689Skan break; 519169689Skan 520169689Skan case USING_STMT: 521169689Skan /* Just ignore for now. Eventually we will want to pass this on to 522169689Skan the debugger. */ 523169689Skan *expr_p = build_empty_stmt (); 524169689Skan ret = GS_ALL_DONE; 525169689Skan break; 526169689Skan 527169689Skan case IF_STMT: 528169689Skan gimplify_if_stmt (expr_p); 529169689Skan ret = GS_OK; 530169689Skan break; 531169689Skan 532169689Skan case FOR_STMT: 533169689Skan gimplify_for_stmt (expr_p, pre_p); 534169689Skan ret = GS_ALL_DONE; 535169689Skan break; 536169689Skan 537169689Skan case WHILE_STMT: 538169689Skan gimplify_while_stmt (expr_p); 539169689Skan ret = GS_ALL_DONE; 540169689Skan break; 541169689Skan 542169689Skan case DO_STMT: 543169689Skan gimplify_do_stmt (expr_p); 544169689Skan ret = GS_ALL_DONE; 545169689Skan break; 546169689Skan 547169689Skan case SWITCH_STMT: 548169689Skan gimplify_switch_stmt (expr_p); 549169689Skan ret = GS_ALL_DONE; 550169689Skan break; 551169689Skan 552169689Skan case OMP_FOR: 553169689Skan ret = cp_gimplify_omp_for (expr_p); 554169689Skan break; 555169689Skan 556169689Skan case CONTINUE_STMT: 557169689Skan *expr_p = build_bc_goto (bc_continue); 558169689Skan ret = GS_ALL_DONE; 559169689Skan break; 560169689Skan 561169689Skan case BREAK_STMT: 562169689Skan *expr_p = build_bc_goto (bc_break); 563169689Skan ret = GS_ALL_DONE; 564169689Skan break; 565169689Skan 566169689Skan case EXPR_STMT: 567169689Skan gimplify_expr_stmt (expr_p); 568169689Skan ret = GS_OK; 569169689Skan break; 570169689Skan 571169689Skan case UNARY_PLUS_EXPR: 572169689Skan { 573169689Skan tree arg = TREE_OPERAND (*expr_p, 0); 574169689Skan tree type = TREE_TYPE (*expr_p); 575169689Skan *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) 576169689Skan : arg; 577169689Skan ret = GS_OK; 578169689Skan } 579169689Skan break; 580169689Skan 581169689Skan default: 582169689Skan ret = c_gimplify_expr (expr_p, pre_p, post_p); 583169689Skan break; 584169689Skan } 585169689Skan 586169689Skan /* Restore saved state. */ 587169689Skan if (STATEMENT_CODE_P (code)) 588169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 589169689Skan = saved_stmts_are_full_exprs_p; 590169689Skan 591169689Skan return ret; 592169689Skan} 593169689Skan 594169689Skanstatic inline bool 595169689Skanis_invisiref_parm (tree t) 596169689Skan{ 597169689Skan return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) 598169689Skan && DECL_BY_REFERENCE (t)); 599169689Skan} 600169689Skan 601169689Skan/* Return true if the uid in both int tree maps are equal. */ 602169689Skan 603169689Skanint 604169689Skancxx_int_tree_map_eq (const void *va, const void *vb) 605169689Skan{ 606169689Skan const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; 607169689Skan const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; 608169689Skan return (a->uid == b->uid); 609169689Skan} 610169689Skan 611169689Skan/* Hash a UID in a cxx_int_tree_map. */ 612169689Skan 613169689Skanunsigned int 614169689Skancxx_int_tree_map_hash (const void *item) 615169689Skan{ 616169689Skan return ((const struct cxx_int_tree_map *)item)->uid; 617169689Skan} 618169689Skan 619169689Skan/* Perform any pre-gimplification lowering of C++ front end trees to 620169689Skan GENERIC. */ 621169689Skan 622169689Skanstatic tree 623169689Skancp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) 624169689Skan{ 625169689Skan tree stmt = *stmt_p; 626169689Skan struct pointer_set_t *p_set = (struct pointer_set_t*) data; 627169689Skan 628169689Skan if (is_invisiref_parm (stmt) 629169689Skan /* Don't dereference parms in a thunk, pass the references through. */ 630169689Skan && !(DECL_THUNK_P (current_function_decl) 631169689Skan && TREE_CODE (stmt) == PARM_DECL)) 632169689Skan { 633169689Skan *stmt_p = convert_from_reference (stmt); 634169689Skan *walk_subtrees = 0; 635169689Skan return NULL; 636169689Skan } 637169689Skan 638169689Skan /* Map block scope extern declarations to visible declarations with the 639169689Skan same name and type in outer scopes if any. */ 640169689Skan if (cp_function_chain->extern_decl_map 641169689Skan && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) 642169689Skan && DECL_EXTERNAL (stmt)) 643169689Skan { 644169689Skan struct cxx_int_tree_map *h, in; 645169689Skan in.uid = DECL_UID (stmt); 646169689Skan h = (struct cxx_int_tree_map *) 647169689Skan htab_find_with_hash (cp_function_chain->extern_decl_map, 648169689Skan &in, in.uid); 649169689Skan if (h) 650169689Skan { 651169689Skan *stmt_p = h->to; 652169689Skan *walk_subtrees = 0; 653169689Skan return NULL; 654169689Skan } 655169689Skan } 656169689Skan 657169689Skan /* Other than invisiref parms, don't walk the same tree twice. */ 658169689Skan if (pointer_set_contains (p_set, stmt)) 659169689Skan { 660169689Skan *walk_subtrees = 0; 661169689Skan return NULL_TREE; 662169689Skan } 663169689Skan 664169689Skan if (TREE_CODE (stmt) == ADDR_EXPR 665169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 666169689Skan { 667169689Skan *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); 668169689Skan *walk_subtrees = 0; 669169689Skan } 670169689Skan else if (TREE_CODE (stmt) == RETURN_EXPR 671169689Skan && TREE_OPERAND (stmt, 0) 672169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 673169689Skan /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ 674169689Skan *walk_subtrees = 0; 675169689Skan else if (TREE_CODE (stmt) == OMP_CLAUSE) 676169689Skan switch (OMP_CLAUSE_CODE (stmt)) 677169689Skan { 678169689Skan case OMP_CLAUSE_PRIVATE: 679169689Skan case OMP_CLAUSE_SHARED: 680169689Skan case OMP_CLAUSE_FIRSTPRIVATE: 681169689Skan case OMP_CLAUSE_LASTPRIVATE: 682169689Skan case OMP_CLAUSE_COPYIN: 683169689Skan case OMP_CLAUSE_COPYPRIVATE: 684169689Skan /* Don't dereference an invisiref in OpenMP clauses. */ 685169689Skan if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) 686169689Skan *walk_subtrees = 0; 687169689Skan break; 688169689Skan case OMP_CLAUSE_REDUCTION: 689169689Skan gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); 690169689Skan break; 691169689Skan default: 692169689Skan break; 693169689Skan } 694169689Skan else if (IS_TYPE_OR_DECL_P (stmt)) 695169689Skan *walk_subtrees = 0; 696169689Skan 697169689Skan /* Due to the way voidify_wrapper_expr is written, we don't get a chance 698169689Skan to lower this construct before scanning it, so we need to lower these 699169689Skan before doing anything else. */ 700169689Skan else if (TREE_CODE (stmt) == CLEANUP_STMT) 701169689Skan *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR 702169689Skan : TRY_FINALLY_EXPR, 703169689Skan void_type_node, 704169689Skan CLEANUP_BODY (stmt), 705169689Skan CLEANUP_EXPR (stmt)); 706169689Skan 707169689Skan pointer_set_insert (p_set, *stmt_p); 708169689Skan 709169689Skan return NULL; 710169689Skan} 711169689Skan 712169689Skanvoid 713169689Skancp_genericize (tree fndecl) 714169689Skan{ 715169689Skan tree t; 716169689Skan struct pointer_set_t *p_set; 717169689Skan 718169689Skan /* Fix up the types of parms passed by invisible reference. */ 719169689Skan for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) 720169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (t))) 721169689Skan { 722169689Skan /* If a function's arguments are copied to create a thunk, 723169689Skan then DECL_BY_REFERENCE will be set -- but the type of the 724169689Skan argument will be a pointer type, so we will never get 725169689Skan here. */ 726169689Skan gcc_assert (!DECL_BY_REFERENCE (t)); 727169689Skan gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); 728169689Skan TREE_TYPE (t) = DECL_ARG_TYPE (t); 729169689Skan DECL_BY_REFERENCE (t) = 1; 730169689Skan TREE_ADDRESSABLE (t) = 0; 731169689Skan relayout_decl (t); 732169689Skan } 733169689Skan 734169689Skan /* Do the same for the return value. */ 735169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) 736169689Skan { 737169689Skan t = DECL_RESULT (fndecl); 738169689Skan TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); 739169689Skan DECL_BY_REFERENCE (t) = 1; 740169689Skan TREE_ADDRESSABLE (t) = 0; 741169689Skan relayout_decl (t); 742169689Skan } 743169689Skan 744169689Skan /* If we're a clone, the body is already GIMPLE. */ 745169689Skan if (DECL_CLONED_FUNCTION_P (fndecl)) 746169689Skan return; 747169689Skan 748169689Skan /* We do want to see every occurrence of the parms, so we can't just use 749169689Skan walk_tree's hash functionality. */ 750169689Skan p_set = pointer_set_create (); 751169689Skan walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); 752169689Skan pointer_set_destroy (p_set); 753169689Skan 754169689Skan /* Do everything else. */ 755169689Skan c_genericize (fndecl); 756169689Skan 757169689Skan gcc_assert (bc_label[bc_break] == NULL); 758169689Skan gcc_assert (bc_label[bc_continue] == NULL); 759169689Skan} 760169689Skan 761169689Skan/* Build code to apply FN to each member of ARG1 and ARG2. FN may be 762169689Skan NULL if there is in fact nothing to do. ARG2 may be null if FN 763169689Skan actually only takes one argument. */ 764169689Skan 765169689Skanstatic tree 766169689Skancxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) 767169689Skan{ 768169689Skan tree defparm, parm; 769169689Skan int i; 770169689Skan 771169689Skan if (fn == NULL) 772169689Skan return NULL; 773169689Skan 774169689Skan defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); 775169689Skan if (arg2) 776169689Skan defparm = TREE_CHAIN (defparm); 777169689Skan 778169689Skan if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) 779169689Skan { 780169689Skan tree inner_type = TREE_TYPE (arg1); 781169689Skan tree start1, end1, p1; 782169689Skan tree start2 = NULL, p2 = NULL; 783169689Skan tree ret = NULL, lab, t; 784169689Skan 785169689Skan start1 = arg1; 786169689Skan start2 = arg2; 787169689Skan do 788169689Skan { 789169689Skan inner_type = TREE_TYPE (inner_type); 790169689Skan start1 = build4 (ARRAY_REF, inner_type, start1, 791169689Skan size_zero_node, NULL, NULL); 792169689Skan if (arg2) 793169689Skan start2 = build4 (ARRAY_REF, inner_type, start2, 794169689Skan size_zero_node, NULL, NULL); 795169689Skan } 796169689Skan while (TREE_CODE (inner_type) == ARRAY_TYPE); 797169689Skan start1 = build_fold_addr_expr (start1); 798169689Skan if (arg2) 799169689Skan start2 = build_fold_addr_expr (start2); 800169689Skan 801169689Skan end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); 802169689Skan end1 = fold_convert (TREE_TYPE (start1), end1); 803169689Skan end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); 804169689Skan 805169689Skan p1 = create_tmp_var (TREE_TYPE (start1), NULL); 806169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, start1); 807169689Skan append_to_statement_list (t, &ret); 808169689Skan 809169689Skan if (arg2) 810169689Skan { 811169689Skan p2 = create_tmp_var (TREE_TYPE (start2), NULL); 812169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, start2); 813169689Skan append_to_statement_list (t, &ret); 814169689Skan } 815169689Skan 816169689Skan lab = create_artificial_label (); 817169689Skan t = build1 (LABEL_EXPR, void_type_node, lab); 818169689Skan append_to_statement_list (t, &ret); 819169689Skan 820169689Skan t = tree_cons (NULL, p1, NULL); 821169689Skan if (arg2) 822169689Skan t = tree_cons (NULL, p2, t); 823169689Skan /* Handle default arguments. */ 824169689Skan i = 1 + (arg2 != NULL); 825169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 826169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 827169689Skan TREE_PURPOSE (parm), 828169689Skan fn, i++), t); 829169689Skan t = build_call (fn, nreverse (t)); 830169689Skan append_to_statement_list (t, &ret); 831169689Skan 832169689Skan t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); 833169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); 834169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, t); 835169689Skan append_to_statement_list (t, &ret); 836169689Skan 837169689Skan if (arg2) 838169689Skan { 839169689Skan t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); 840169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); 841169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, t); 842169689Skan append_to_statement_list (t, &ret); 843169689Skan } 844169689Skan 845169689Skan t = build2 (NE_EXPR, boolean_type_node, p1, end1); 846169689Skan t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); 847169689Skan append_to_statement_list (t, &ret); 848169689Skan 849169689Skan return ret; 850169689Skan } 851169689Skan else 852169689Skan { 853169689Skan tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); 854169689Skan if (arg2) 855169689Skan t = tree_cons (NULL, build_fold_addr_expr (arg2), t); 856169689Skan /* Handle default arguments. */ 857169689Skan i = 1 + (arg2 != NULL); 858169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 859169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 860169689Skan TREE_PURPOSE (parm), 861169689Skan fn, i++), t); 862169689Skan return build_call (fn, nreverse (t)); 863169689Skan } 864169689Skan} 865169689Skan 866169689Skan/* Return code to initialize DECL with its default constructor, or 867169689Skan NULL if there's nothing to do. */ 868169689Skan 869169689Skantree 870169689Skancxx_omp_clause_default_ctor (tree clause, tree decl) 871169689Skan{ 872169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 873169689Skan tree ret = NULL; 874169689Skan 875169689Skan if (info) 876169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); 877169689Skan 878169689Skan return ret; 879169689Skan} 880169689Skan 881169689Skan/* Return code to initialize DST with a copy constructor from SRC. */ 882169689Skan 883169689Skantree 884169689Skancxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) 885169689Skan{ 886169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 887169689Skan tree ret = NULL; 888169689Skan 889169689Skan if (info) 890169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); 891169689Skan if (ret == NULL) 892169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 893169689Skan 894169689Skan return ret; 895169689Skan} 896169689Skan 897169689Skan/* Similarly, except use an assignment operator instead. */ 898169689Skan 899169689Skantree 900169689Skancxx_omp_clause_assign_op (tree clause, tree dst, tree src) 901169689Skan{ 902169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 903169689Skan tree ret = NULL; 904169689Skan 905169689Skan if (info) 906169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); 907169689Skan if (ret == NULL) 908169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 909169689Skan 910169689Skan return ret; 911169689Skan} 912169689Skan 913169689Skan/* Return code to destroy DECL. */ 914169689Skan 915169689Skantree 916169689Skancxx_omp_clause_dtor (tree clause, tree decl) 917169689Skan{ 918169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 919169689Skan tree ret = NULL; 920169689Skan 921169689Skan if (info) 922169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); 923169689Skan 924169689Skan return ret; 925169689Skan} 926169689Skan 927169689Skan/* True if OpenMP should privatize what this DECL points to rather 928169689Skan than the DECL itself. */ 929169689Skan 930169689Skanbool 931169689Skancxx_omp_privatize_by_reference (tree decl) 932169689Skan{ 933169689Skan return is_invisiref_parm (decl); 934169689Skan} 935