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 191260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 192260918Spfggimplify_cp_loop (tree cond, tree body, tree incr, tree attrs, 193260918Spfg bool cond_is_first, tree inner_foreach) 194260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 195169689Skan{ 196169689Skan tree top, entry, exit, cont_block, break_block, stmt_list, t; 197169689Skan location_t stmt_locus; 198169689Skan 199169689Skan stmt_locus = input_location; 200169689Skan stmt_list = NULL_TREE; 201169689Skan entry = NULL_TREE; 202169689Skan 203261188Spfg /* APPLE LOCAL begin C* language */ 204261188Spfg /* Order of label addition to stack is important for objc's foreach-stmt. */ 205261188Spfg /* APPLE LOCAL radar 4667060 */ 206261188Spfg if (inner_foreach == integer_zero_node) 207261188Spfg { 208261188Spfg cont_block = begin_bc_block (bc_continue); 209261188Spfg break_block = begin_bc_block (bc_break); 210261188Spfg } 211261188Spfg else 212261188Spfg { 213261188Spfg break_block = begin_bc_block (bc_break); 214261188Spfg cont_block = begin_bc_block (bc_continue); 215261188Spfg } 216261188Spfg /* APPLE LOCAL end C* language */ 217169689Skan 218169689Skan /* If condition is zero don't generate a loop construct. */ 219169689Skan if (cond && integer_zerop (cond)) 220169689Skan { 221169689Skan top = NULL_TREE; 222169689Skan exit = NULL_TREE; 223169689Skan if (cond_is_first) 224169689Skan { 225169689Skan t = build_bc_goto (bc_break); 226169689Skan append_to_statement_list (t, &stmt_list); 227169689Skan } 228169689Skan } 229169689Skan else 230169689Skan { 231169689Skan /* If we use a LOOP_EXPR here, we have to feed the whole thing 232169689Skan back through the main gimplifier to lower it. Given that we 233169689Skan have to gimplify the loop body NOW so that we can resolve 234169689Skan break/continue stmts, seems easier to just expand to gotos. */ 235169689Skan top = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 236169689Skan 237169689Skan /* If we have an exit condition, then we build an IF with gotos either 238169689Skan out of the loop, or to the top of it. If there's no exit condition, 239169689Skan then we just build a jump back to the top. */ 240169689Skan exit = build_and_jump (&LABEL_EXPR_LABEL (top)); 241260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 242260918Spfg 243260918Spfg /* Add the attributes to the 'top' label. */ 244260918Spfg decl_attributes (&LABEL_EXPR_LABEL (top), attrs, 0); 245260918Spfg 246260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 247169689Skan if (cond && !integer_nonzerop (cond)) 248169689Skan { 249169689Skan t = build_bc_goto (bc_break); 250169689Skan exit = fold_build3 (COND_EXPR, void_type_node, cond, exit, t); 251169689Skan gimplify_stmt (&exit); 252169689Skan 253169689Skan if (cond_is_first) 254169689Skan { 255169689Skan if (incr) 256169689Skan { 257169689Skan entry = build1 (LABEL_EXPR, void_type_node, NULL_TREE); 258169689Skan t = build_and_jump (&LABEL_EXPR_LABEL (entry)); 259169689Skan } 260169689Skan else 261169689Skan t = build_bc_goto (bc_continue); 262169689Skan append_to_statement_list (t, &stmt_list); 263169689Skan } 264169689Skan } 265169689Skan } 266169689Skan 267261188Spfg /* APPLE LOCAL begin radar 4547045 */ 268261188Spfg /* Pop foreach's inner loop break label so outer loop's 269261188Spfg break label becomes target of inner loop body's break statements. 270261188Spfg */ 271261188Spfg t = NULL_TREE; 272169689Skan gimplify_stmt (&body); 273169689Skan gimplify_stmt (&incr); 274169689Skan 275169689Skan body = finish_bc_block (bc_continue, cont_block, body); 276261188Spfg /* APPLE LOCAL begin radar 4547045 */ 277261188Spfg /* Push back inner loop's own 'break' label so rest 278261188Spfg of code works seemlessly. */ 279261188Spfg /* APPLE LOCAL radar 4667060 */ 280169689Skan 281169689Skan append_to_statement_list (top, &stmt_list); 282169689Skan append_to_statement_list (body, &stmt_list); 283169689Skan append_to_statement_list (incr, &stmt_list); 284169689Skan append_to_statement_list (entry, &stmt_list); 285169689Skan append_to_statement_list (exit, &stmt_list); 286169689Skan 287169689Skan annotate_all_with_locus (&stmt_list, stmt_locus); 288169689Skan 289169689Skan return finish_bc_block (bc_break, break_block, stmt_list); 290169689Skan} 291169689Skan 292169689Skan/* Gimplify a FOR_STMT node. Move the stuff in the for-init-stmt into the 293169689Skan prequeue and hand off to gimplify_cp_loop. */ 294169689Skan 295169689Skanstatic void 296169689Skangimplify_for_stmt (tree *stmt_p, tree *pre_p) 297169689Skan{ 298169689Skan tree stmt = *stmt_p; 299169689Skan 300169689Skan if (FOR_INIT_STMT (stmt)) 301169689Skan gimplify_and_add (FOR_INIT_STMT (stmt), pre_p); 302169689Skan 303260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 304169689Skan *stmt_p = gimplify_cp_loop (FOR_COND (stmt), FOR_BODY (stmt), 305260918Spfg FOR_EXPR (stmt), FOR_ATTRIBUTES (stmt), 1, 306260918Spfg NULL_TREE); 307260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 308169689Skan} 309169689Skan 310169689Skan/* Gimplify a WHILE_STMT node. */ 311169689Skan 312169689Skanstatic void 313169689Skangimplify_while_stmt (tree *stmt_p) 314169689Skan{ 315169689Skan tree stmt = *stmt_p; 316260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 317169689Skan *stmt_p = gimplify_cp_loop (WHILE_COND (stmt), WHILE_BODY (stmt), 318260918Spfg NULL_TREE, WHILE_ATTRIBUTES (stmt), 1, 319260918Spfg NULL_TREE); 320260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 321169689Skan} 322169689Skan 323169689Skan/* Gimplify a DO_STMT node. */ 324169689Skan 325169689Skanstatic void 326169689Skangimplify_do_stmt (tree *stmt_p) 327169689Skan{ 328169689Skan tree stmt = *stmt_p; 329260918Spfg/* APPLE LOCAL begin for-fsf-4_4 3274130 5295549 */ \ 330169689Skan *stmt_p = gimplify_cp_loop (DO_COND (stmt), DO_BODY (stmt), 331260918Spfg NULL_TREE, DO_ATTRIBUTES (stmt), 0, 332260918Spfg DO_FOREACH (stmt)); 333260918Spfg/* APPLE LOCAL end for-fsf-4_4 3274130 5295549 */ \ 334169689Skan} 335169689Skan 336169689Skan/* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ 337169689Skan 338169689Skanstatic void 339169689Skangimplify_switch_stmt (tree *stmt_p) 340169689Skan{ 341169689Skan tree stmt = *stmt_p; 342169689Skan tree break_block, body; 343169689Skan location_t stmt_locus = input_location; 344169689Skan 345169689Skan break_block = begin_bc_block (bc_break); 346169689Skan 347169689Skan body = SWITCH_STMT_BODY (stmt); 348169689Skan if (!body) 349169689Skan body = build_empty_stmt (); 350169689Skan 351169689Skan *stmt_p = build3 (SWITCH_EXPR, SWITCH_STMT_TYPE (stmt), 352169689Skan SWITCH_STMT_COND (stmt), body, NULL_TREE); 353169689Skan SET_EXPR_LOCATION (*stmt_p, stmt_locus); 354169689Skan gimplify_stmt (stmt_p); 355169689Skan 356169689Skan *stmt_p = finish_bc_block (bc_break, break_block, *stmt_p); 357169689Skan} 358169689Skan 359169689Skan/* Hook into the middle of gimplifying an OMP_FOR node. This is required 360169689Skan in order to properly gimplify CONTINUE statements. Here we merely 361169689Skan manage the continue stack; the rest of the job is performed by the 362169689Skan regular gimplifier. */ 363169689Skan 364169689Skanstatic enum gimplify_status 365169689Skancp_gimplify_omp_for (tree *expr_p) 366169689Skan{ 367169689Skan tree for_stmt = *expr_p; 368169689Skan tree cont_block; 369169689Skan 370169689Skan /* Protect ourselves from recursion. */ 371169689Skan if (OMP_FOR_GIMPLIFYING_P (for_stmt)) 372169689Skan return GS_UNHANDLED; 373169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; 374169689Skan 375169689Skan /* Note that while technically the continue label is enabled too soon 376169689Skan here, we should have already diagnosed invalid continues nested within 377169689Skan statement expressions within the INIT, COND, or INCR expressions. */ 378169689Skan cont_block = begin_bc_block (bc_continue); 379169689Skan 380169689Skan gimplify_stmt (expr_p); 381169689Skan 382169689Skan OMP_FOR_BODY (for_stmt) 383169689Skan = finish_bc_block (bc_continue, cont_block, OMP_FOR_BODY (for_stmt)); 384169689Skan OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; 385169689Skan 386169689Skan return GS_ALL_DONE; 387169689Skan} 388169689Skan 389169689Skan/* Gimplify an EXPR_STMT node. */ 390169689Skan 391169689Skanstatic void 392169689Skangimplify_expr_stmt (tree *stmt_p) 393169689Skan{ 394169689Skan tree stmt = EXPR_STMT_EXPR (*stmt_p); 395169689Skan 396169689Skan if (stmt == error_mark_node) 397169689Skan stmt = NULL; 398169689Skan 399169689Skan /* Gimplification of a statement expression will nullify the 400169689Skan statement if all its side effects are moved to *PRE_P and *POST_P. 401169689Skan 402169689Skan In this case we will not want to emit the gimplified statement. 403169689Skan However, we may still want to emit a warning, so we do that before 404169689Skan gimplification. */ 405169689Skan if (stmt && (extra_warnings || warn_unused_value)) 406169689Skan { 407169689Skan if (!TREE_SIDE_EFFECTS (stmt)) 408169689Skan { 409169689Skan if (!IS_EMPTY_STMT (stmt) 410169689Skan && !VOID_TYPE_P (TREE_TYPE (stmt)) 411169689Skan && !TREE_NO_WARNING (stmt)) 412169689Skan warning (OPT_Wextra, "statement with no effect"); 413169689Skan } 414169689Skan else if (warn_unused_value) 415169689Skan warn_if_unused_value (stmt, input_location); 416169689Skan } 417169689Skan 418169689Skan if (stmt == NULL_TREE) 419169689Skan stmt = alloc_stmt_list (); 420169689Skan 421169689Skan *stmt_p = stmt; 422169689Skan} 423169689Skan 424169689Skan/* Gimplify initialization from an AGGR_INIT_EXPR. */ 425169689Skan 426169689Skanstatic void 427169689Skancp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p) 428169689Skan{ 429169689Skan tree from = TREE_OPERAND (*expr_p, 1); 430169689Skan tree to = TREE_OPERAND (*expr_p, 0); 431169689Skan tree sub; 432169689Skan 433169689Skan /* What about code that pulls out the temp and uses it elsewhere? I 434169689Skan think that such code never uses the TARGET_EXPR as an initializer. If 435169689Skan I'm wrong, we'll abort because the temp won't have any RTL. In that 436169689Skan case, I guess we'll need to replace references somehow. */ 437169689Skan if (TREE_CODE (from) == TARGET_EXPR) 438169689Skan from = TARGET_EXPR_INITIAL (from); 439169689Skan 440169689Skan /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them 441169689Skan inside the TARGET_EXPR. */ 442169689Skan sub = expr_last (from); 443169689Skan 444169689Skan /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and 445169689Skan replace the slot operand with our target. 446169689Skan 447169689Skan Should we add a target parm to gimplify_expr instead? No, as in this 448169689Skan case we want to replace the INIT_EXPR. */ 449169689Skan if (TREE_CODE (sub) == AGGR_INIT_EXPR) 450169689Skan { 451169689Skan gimplify_expr (&to, pre_p, post_p, is_gimple_lvalue, fb_lvalue); 452169689Skan TREE_OPERAND (sub, 2) = to; 453169689Skan *expr_p = from; 454169689Skan 455169689Skan /* The initialization is now a side-effect, so the container can 456169689Skan become void. */ 457169689Skan if (from != sub) 458169689Skan TREE_TYPE (from) = void_type_node; 459169689Skan } 460169689Skan} 461169689Skan 462169689Skan/* Gimplify a MUST_NOT_THROW_EXPR. */ 463169689Skan 464169689Skanstatic void 465169689Skangimplify_must_not_throw_expr (tree *expr_p, tree *pre_p) 466169689Skan{ 467169689Skan tree stmt = *expr_p; 468169689Skan tree temp = voidify_wrapper_expr (stmt, NULL); 469169689Skan tree body = TREE_OPERAND (stmt, 0); 470169689Skan 471169689Skan gimplify_stmt (&body); 472169689Skan 473169689Skan stmt = gimple_build_eh_filter (body, NULL_TREE, 474169689Skan build_call (terminate_node, NULL_TREE)); 475169689Skan 476169689Skan if (temp) 477169689Skan { 478169689Skan append_to_statement_list (stmt, pre_p); 479169689Skan *expr_p = temp; 480169689Skan } 481169689Skan else 482169689Skan *expr_p = stmt; 483169689Skan} 484169689Skan 485169689Skan/* Do C++-specific gimplification. Args are as for gimplify_expr. */ 486169689Skan 487169689Skanint 488169689Skancp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) 489169689Skan{ 490169689Skan int saved_stmts_are_full_exprs_p = 0; 491169689Skan enum tree_code code = TREE_CODE (*expr_p); 492169689Skan enum gimplify_status ret; 493169689Skan 494169689Skan if (STATEMENT_CODE_P (code)) 495169689Skan { 496169689Skan saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); 497169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 498169689Skan = STMT_IS_FULL_EXPR_P (*expr_p); 499169689Skan } 500169689Skan 501169689Skan switch (code) 502169689Skan { 503169689Skan case PTRMEM_CST: 504169689Skan *expr_p = cplus_expand_constant (*expr_p); 505169689Skan ret = GS_OK; 506169689Skan break; 507169689Skan 508169689Skan case AGGR_INIT_EXPR: 509169689Skan simplify_aggr_init_expr (expr_p); 510169689Skan ret = GS_OK; 511169689Skan break; 512169689Skan 513169689Skan case THROW_EXPR: 514169689Skan /* FIXME communicate throw type to backend, probably by moving 515169689Skan THROW_EXPR into ../tree.def. */ 516169689Skan *expr_p = TREE_OPERAND (*expr_p, 0); 517169689Skan ret = GS_OK; 518169689Skan break; 519169689Skan 520169689Skan case MUST_NOT_THROW_EXPR: 521169689Skan gimplify_must_not_throw_expr (expr_p, pre_p); 522169689Skan ret = GS_OK; 523169689Skan break; 524169689Skan 525169689Skan /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the 526169689Skan LHS of an assignment might also be involved in the RHS, as in bug 527169689Skan 25979. */ 528169689Skan case INIT_EXPR: 529169689Skan cp_gimplify_init_expr (expr_p, pre_p, post_p); 530169689Skan ret = GS_OK; 531169689Skan break; 532169689Skan 533169689Skan case EMPTY_CLASS_EXPR: 534169689Skan /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ 535169689Skan *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); 536169689Skan ret = GS_OK; 537169689Skan break; 538169689Skan 539169689Skan case BASELINK: 540169689Skan *expr_p = BASELINK_FUNCTIONS (*expr_p); 541169689Skan ret = GS_OK; 542169689Skan break; 543169689Skan 544169689Skan case TRY_BLOCK: 545169689Skan genericize_try_block (expr_p); 546169689Skan ret = GS_OK; 547169689Skan break; 548169689Skan 549169689Skan case HANDLER: 550169689Skan genericize_catch_block (expr_p); 551169689Skan ret = GS_OK; 552169689Skan break; 553169689Skan 554169689Skan case EH_SPEC_BLOCK: 555169689Skan genericize_eh_spec_block (expr_p); 556169689Skan ret = GS_OK; 557169689Skan break; 558169689Skan 559169689Skan case USING_STMT: 560169689Skan /* Just ignore for now. Eventually we will want to pass this on to 561169689Skan the debugger. */ 562169689Skan *expr_p = build_empty_stmt (); 563169689Skan ret = GS_ALL_DONE; 564169689Skan break; 565169689Skan 566169689Skan case IF_STMT: 567169689Skan gimplify_if_stmt (expr_p); 568169689Skan ret = GS_OK; 569169689Skan break; 570169689Skan 571169689Skan case FOR_STMT: 572169689Skan gimplify_for_stmt (expr_p, pre_p); 573169689Skan ret = GS_ALL_DONE; 574169689Skan break; 575169689Skan 576169689Skan case WHILE_STMT: 577169689Skan gimplify_while_stmt (expr_p); 578169689Skan ret = GS_ALL_DONE; 579169689Skan break; 580169689Skan 581169689Skan case DO_STMT: 582169689Skan gimplify_do_stmt (expr_p); 583169689Skan ret = GS_ALL_DONE; 584169689Skan break; 585169689Skan 586169689Skan case SWITCH_STMT: 587169689Skan gimplify_switch_stmt (expr_p); 588169689Skan ret = GS_ALL_DONE; 589169689Skan break; 590169689Skan 591169689Skan case OMP_FOR: 592169689Skan ret = cp_gimplify_omp_for (expr_p); 593169689Skan break; 594169689Skan 595169689Skan case CONTINUE_STMT: 596169689Skan *expr_p = build_bc_goto (bc_continue); 597169689Skan ret = GS_ALL_DONE; 598169689Skan break; 599169689Skan 600169689Skan case BREAK_STMT: 601169689Skan *expr_p = build_bc_goto (bc_break); 602169689Skan ret = GS_ALL_DONE; 603169689Skan break; 604169689Skan 605169689Skan case EXPR_STMT: 606169689Skan gimplify_expr_stmt (expr_p); 607169689Skan ret = GS_OK; 608169689Skan break; 609169689Skan 610169689Skan case UNARY_PLUS_EXPR: 611169689Skan { 612169689Skan tree arg = TREE_OPERAND (*expr_p, 0); 613169689Skan tree type = TREE_TYPE (*expr_p); 614169689Skan *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) 615169689Skan : arg; 616169689Skan ret = GS_OK; 617169689Skan } 618169689Skan break; 619169689Skan 620169689Skan default: 621169689Skan ret = c_gimplify_expr (expr_p, pre_p, post_p); 622169689Skan break; 623169689Skan } 624169689Skan 625169689Skan /* Restore saved state. */ 626169689Skan if (STATEMENT_CODE_P (code)) 627169689Skan current_stmt_tree ()->stmts_are_full_exprs_p 628169689Skan = saved_stmts_are_full_exprs_p; 629169689Skan 630169689Skan return ret; 631169689Skan} 632169689Skan 633169689Skanstatic inline bool 634169689Skanis_invisiref_parm (tree t) 635169689Skan{ 636169689Skan return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) 637169689Skan && DECL_BY_REFERENCE (t)); 638169689Skan} 639169689Skan 640169689Skan/* Return true if the uid in both int tree maps are equal. */ 641169689Skan 642169689Skanint 643169689Skancxx_int_tree_map_eq (const void *va, const void *vb) 644169689Skan{ 645169689Skan const struct cxx_int_tree_map *a = (const struct cxx_int_tree_map *) va; 646169689Skan const struct cxx_int_tree_map *b = (const struct cxx_int_tree_map *) vb; 647169689Skan return (a->uid == b->uid); 648169689Skan} 649169689Skan 650169689Skan/* Hash a UID in a cxx_int_tree_map. */ 651169689Skan 652169689Skanunsigned int 653169689Skancxx_int_tree_map_hash (const void *item) 654169689Skan{ 655169689Skan return ((const struct cxx_int_tree_map *)item)->uid; 656169689Skan} 657169689Skan 658169689Skan/* Perform any pre-gimplification lowering of C++ front end trees to 659169689Skan GENERIC. */ 660169689Skan 661169689Skanstatic tree 662169689Skancp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) 663169689Skan{ 664169689Skan tree stmt = *stmt_p; 665169689Skan struct pointer_set_t *p_set = (struct pointer_set_t*) data; 666169689Skan 667169689Skan if (is_invisiref_parm (stmt) 668169689Skan /* Don't dereference parms in a thunk, pass the references through. */ 669169689Skan && !(DECL_THUNK_P (current_function_decl) 670169689Skan && TREE_CODE (stmt) == PARM_DECL)) 671169689Skan { 672169689Skan *stmt_p = convert_from_reference (stmt); 673169689Skan *walk_subtrees = 0; 674169689Skan return NULL; 675169689Skan } 676169689Skan 677169689Skan /* Map block scope extern declarations to visible declarations with the 678169689Skan same name and type in outer scopes if any. */ 679169689Skan if (cp_function_chain->extern_decl_map 680169689Skan && (TREE_CODE (stmt) == FUNCTION_DECL || TREE_CODE (stmt) == VAR_DECL) 681169689Skan && DECL_EXTERNAL (stmt)) 682169689Skan { 683169689Skan struct cxx_int_tree_map *h, in; 684169689Skan in.uid = DECL_UID (stmt); 685169689Skan h = (struct cxx_int_tree_map *) 686169689Skan htab_find_with_hash (cp_function_chain->extern_decl_map, 687169689Skan &in, in.uid); 688169689Skan if (h) 689169689Skan { 690169689Skan *stmt_p = h->to; 691169689Skan *walk_subtrees = 0; 692169689Skan return NULL; 693169689Skan } 694169689Skan } 695169689Skan 696169689Skan /* Other than invisiref parms, don't walk the same tree twice. */ 697169689Skan if (pointer_set_contains (p_set, stmt)) 698169689Skan { 699169689Skan *walk_subtrees = 0; 700169689Skan return NULL_TREE; 701169689Skan } 702169689Skan 703169689Skan if (TREE_CODE (stmt) == ADDR_EXPR 704169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 705169689Skan { 706169689Skan *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); 707169689Skan *walk_subtrees = 0; 708169689Skan } 709169689Skan else if (TREE_CODE (stmt) == RETURN_EXPR 710169689Skan && TREE_OPERAND (stmt, 0) 711169689Skan && is_invisiref_parm (TREE_OPERAND (stmt, 0))) 712169689Skan /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ 713169689Skan *walk_subtrees = 0; 714169689Skan else if (TREE_CODE (stmt) == OMP_CLAUSE) 715169689Skan switch (OMP_CLAUSE_CODE (stmt)) 716169689Skan { 717169689Skan case OMP_CLAUSE_PRIVATE: 718169689Skan case OMP_CLAUSE_SHARED: 719169689Skan case OMP_CLAUSE_FIRSTPRIVATE: 720169689Skan case OMP_CLAUSE_LASTPRIVATE: 721169689Skan case OMP_CLAUSE_COPYIN: 722169689Skan case OMP_CLAUSE_COPYPRIVATE: 723169689Skan /* Don't dereference an invisiref in OpenMP clauses. */ 724169689Skan if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) 725169689Skan *walk_subtrees = 0; 726169689Skan break; 727169689Skan case OMP_CLAUSE_REDUCTION: 728169689Skan gcc_assert (!is_invisiref_parm (OMP_CLAUSE_DECL (stmt))); 729169689Skan break; 730169689Skan default: 731169689Skan break; 732169689Skan } 733169689Skan else if (IS_TYPE_OR_DECL_P (stmt)) 734169689Skan *walk_subtrees = 0; 735169689Skan 736169689Skan /* Due to the way voidify_wrapper_expr is written, we don't get a chance 737169689Skan to lower this construct before scanning it, so we need to lower these 738169689Skan before doing anything else. */ 739169689Skan else if (TREE_CODE (stmt) == CLEANUP_STMT) 740169689Skan *stmt_p = build2 (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR 741169689Skan : TRY_FINALLY_EXPR, 742169689Skan void_type_node, 743169689Skan CLEANUP_BODY (stmt), 744169689Skan CLEANUP_EXPR (stmt)); 745169689Skan 746169689Skan pointer_set_insert (p_set, *stmt_p); 747169689Skan 748169689Skan return NULL; 749169689Skan} 750169689Skan 751169689Skanvoid 752169689Skancp_genericize (tree fndecl) 753169689Skan{ 754169689Skan tree t; 755169689Skan struct pointer_set_t *p_set; 756169689Skan 757169689Skan /* Fix up the types of parms passed by invisible reference. */ 758169689Skan for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t)) 759169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (t))) 760169689Skan { 761169689Skan /* If a function's arguments are copied to create a thunk, 762169689Skan then DECL_BY_REFERENCE will be set -- but the type of the 763169689Skan argument will be a pointer type, so we will never get 764169689Skan here. */ 765169689Skan gcc_assert (!DECL_BY_REFERENCE (t)); 766169689Skan gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); 767169689Skan TREE_TYPE (t) = DECL_ARG_TYPE (t); 768169689Skan DECL_BY_REFERENCE (t) = 1; 769169689Skan TREE_ADDRESSABLE (t) = 0; 770169689Skan relayout_decl (t); 771169689Skan } 772169689Skan 773169689Skan /* Do the same for the return value. */ 774169689Skan if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) 775169689Skan { 776169689Skan t = DECL_RESULT (fndecl); 777169689Skan TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); 778169689Skan DECL_BY_REFERENCE (t) = 1; 779169689Skan TREE_ADDRESSABLE (t) = 0; 780169689Skan relayout_decl (t); 781169689Skan } 782169689Skan 783169689Skan /* If we're a clone, the body is already GIMPLE. */ 784169689Skan if (DECL_CLONED_FUNCTION_P (fndecl)) 785169689Skan return; 786169689Skan 787169689Skan /* We do want to see every occurrence of the parms, so we can't just use 788169689Skan walk_tree's hash functionality. */ 789169689Skan p_set = pointer_set_create (); 790169689Skan walk_tree (&DECL_SAVED_TREE (fndecl), cp_genericize_r, p_set, NULL); 791169689Skan pointer_set_destroy (p_set); 792169689Skan 793169689Skan /* Do everything else. */ 794169689Skan c_genericize (fndecl); 795169689Skan 796169689Skan gcc_assert (bc_label[bc_break] == NULL); 797169689Skan gcc_assert (bc_label[bc_continue] == NULL); 798169689Skan} 799169689Skan 800169689Skan/* Build code to apply FN to each member of ARG1 and ARG2. FN may be 801169689Skan NULL if there is in fact nothing to do. ARG2 may be null if FN 802169689Skan actually only takes one argument. */ 803169689Skan 804169689Skanstatic tree 805169689Skancxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) 806169689Skan{ 807169689Skan tree defparm, parm; 808169689Skan int i; 809169689Skan 810169689Skan if (fn == NULL) 811169689Skan return NULL; 812169689Skan 813169689Skan defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); 814169689Skan if (arg2) 815169689Skan defparm = TREE_CHAIN (defparm); 816169689Skan 817169689Skan if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) 818169689Skan { 819169689Skan tree inner_type = TREE_TYPE (arg1); 820169689Skan tree start1, end1, p1; 821169689Skan tree start2 = NULL, p2 = NULL; 822169689Skan tree ret = NULL, lab, t; 823169689Skan 824169689Skan start1 = arg1; 825169689Skan start2 = arg2; 826169689Skan do 827169689Skan { 828169689Skan inner_type = TREE_TYPE (inner_type); 829169689Skan start1 = build4 (ARRAY_REF, inner_type, start1, 830169689Skan size_zero_node, NULL, NULL); 831169689Skan if (arg2) 832169689Skan start2 = build4 (ARRAY_REF, inner_type, start2, 833169689Skan size_zero_node, NULL, NULL); 834169689Skan } 835169689Skan while (TREE_CODE (inner_type) == ARRAY_TYPE); 836169689Skan start1 = build_fold_addr_expr (start1); 837169689Skan if (arg2) 838169689Skan start2 = build_fold_addr_expr (start2); 839169689Skan 840169689Skan end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); 841169689Skan end1 = fold_convert (TREE_TYPE (start1), end1); 842169689Skan end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); 843169689Skan 844169689Skan p1 = create_tmp_var (TREE_TYPE (start1), NULL); 845169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, start1); 846169689Skan append_to_statement_list (t, &ret); 847169689Skan 848169689Skan if (arg2) 849169689Skan { 850169689Skan p2 = create_tmp_var (TREE_TYPE (start2), NULL); 851169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, start2); 852169689Skan append_to_statement_list (t, &ret); 853169689Skan } 854169689Skan 855169689Skan lab = create_artificial_label (); 856169689Skan t = build1 (LABEL_EXPR, void_type_node, lab); 857169689Skan append_to_statement_list (t, &ret); 858169689Skan 859169689Skan t = tree_cons (NULL, p1, NULL); 860169689Skan if (arg2) 861169689Skan t = tree_cons (NULL, p2, t); 862169689Skan /* Handle default arguments. */ 863169689Skan i = 1 + (arg2 != NULL); 864169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 865169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 866169689Skan TREE_PURPOSE (parm), 867169689Skan fn, i++), t); 868169689Skan t = build_call (fn, nreverse (t)); 869169689Skan append_to_statement_list (t, &ret); 870169689Skan 871169689Skan t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); 872169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); 873169689Skan t = build2 (MODIFY_EXPR, void_type_node, p1, t); 874169689Skan append_to_statement_list (t, &ret); 875169689Skan 876169689Skan if (arg2) 877169689Skan { 878169689Skan t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); 879169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); 880169689Skan t = build2 (MODIFY_EXPR, void_type_node, p2, t); 881169689Skan append_to_statement_list (t, &ret); 882169689Skan } 883169689Skan 884169689Skan t = build2 (NE_EXPR, boolean_type_node, p1, end1); 885169689Skan t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); 886169689Skan append_to_statement_list (t, &ret); 887169689Skan 888169689Skan return ret; 889169689Skan } 890169689Skan else 891169689Skan { 892169689Skan tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); 893169689Skan if (arg2) 894169689Skan t = tree_cons (NULL, build_fold_addr_expr (arg2), t); 895169689Skan /* Handle default arguments. */ 896169689Skan i = 1 + (arg2 != NULL); 897169689Skan for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) 898169689Skan t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), 899169689Skan TREE_PURPOSE (parm), 900169689Skan fn, i++), t); 901169689Skan return build_call (fn, nreverse (t)); 902169689Skan } 903169689Skan} 904169689Skan 905169689Skan/* Return code to initialize DECL with its default constructor, or 906169689Skan NULL if there's nothing to do. */ 907169689Skan 908169689Skantree 909169689Skancxx_omp_clause_default_ctor (tree clause, tree decl) 910169689Skan{ 911169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 912169689Skan tree ret = NULL; 913169689Skan 914169689Skan if (info) 915169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); 916169689Skan 917169689Skan return ret; 918169689Skan} 919169689Skan 920169689Skan/* Return code to initialize DST with a copy constructor from SRC. */ 921169689Skan 922169689Skantree 923169689Skancxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) 924169689Skan{ 925169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 926169689Skan tree ret = NULL; 927169689Skan 928169689Skan if (info) 929169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); 930169689Skan if (ret == NULL) 931169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 932169689Skan 933169689Skan return ret; 934169689Skan} 935169689Skan 936169689Skan/* Similarly, except use an assignment operator instead. */ 937169689Skan 938169689Skantree 939169689Skancxx_omp_clause_assign_op (tree clause, tree dst, tree src) 940169689Skan{ 941169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 942169689Skan tree ret = NULL; 943169689Skan 944169689Skan if (info) 945169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); 946169689Skan if (ret == NULL) 947169689Skan ret = build2 (MODIFY_EXPR, void_type_node, dst, src); 948169689Skan 949169689Skan return ret; 950169689Skan} 951169689Skan 952169689Skan/* Return code to destroy DECL. */ 953169689Skan 954169689Skantree 955169689Skancxx_omp_clause_dtor (tree clause, tree decl) 956169689Skan{ 957169689Skan tree info = CP_OMP_CLAUSE_INFO (clause); 958169689Skan tree ret = NULL; 959169689Skan 960169689Skan if (info) 961169689Skan ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); 962169689Skan 963169689Skan return ret; 964169689Skan} 965169689Skan 966169689Skan/* True if OpenMP should privatize what this DECL points to rather 967169689Skan than the DECL itself. */ 968169689Skan 969169689Skanbool 970169689Skancxx_omp_privatize_by_reference (tree decl) 971169689Skan{ 972169689Skan return is_invisiref_parm (decl); 973169689Skan} 974