/* primary-expression: literal this :: identifier :: operator-function-id :: qualifier-id ( expression ) id-expression */ static void pp_cxx_primary_expression (cxx_pretty_printer *pp, tree t) { switch (TREE_CODE (t)) { case STRING_CST: case INTEGER_CST: case REAL_CST: pp_c_constant (pp_c_base (pp), t); break; case BASELINK: t = BASELINK_FUNCTIONS (t); case VAR_DECL: case PARM_DECL: case FIELD_DECL: case FUNCTION_DECL: case OVERLOAD: case CONST_DECL: case TEMPLATE_DECL: pp_cxx_id_expression (pp, t); break; case RESULT_DECL: case TEMPLATE_TYPE_PARM: case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, t); break; default: pp_c_primary_expression (pp_c_base (pp), t); break; } }
void cxx_print_xnode (FILE *file, tree node, int indent) { switch (TREE_CODE (node)) { case BASELINK: print_node (file, "functions", BASELINK_FUNCTIONS (node), indent + 4); print_node (file, "binfo", BASELINK_BINFO (node), indent + 4); print_node (file, "access_binfo", BASELINK_ACCESS_BINFO (node), indent + 4); break; case OVERLOAD: print_node (file, "function", OVL_FUNCTION (node), indent+4); print_node (file, "chain", TREE_CHAIN (node), indent+4); break; case TEMPLATE_PARM_INDEX: indent_to (file, indent + 3); fprintf (file, "index " HOST_WIDE_INT_PRINT_DEC " level " HOST_WIDE_INT_PRINT_DEC " orig_level " HOST_WIDE_INT_PRINT_DEC, TEMPLATE_PARM_IDX (node), TEMPLATE_PARM_LEVEL (node), TEMPLATE_PARM_ORIG_LEVEL (node)); break; default: break; } }
tree cxx_staticp (tree arg) { switch (TREE_CODE (arg)) { case BASELINK: return staticp (BASELINK_FUNCTIONS (arg)); default: break; } return NULL_TREE; }
void cxx_print_xnode (FILE *file, tree node, int indent) { switch (TREE_CODE (node)) { case BASELINK: print_node (file, "functions", BASELINK_FUNCTIONS (node), indent + 4); print_node (file, "binfo", BASELINK_BINFO (node), indent + 4); print_node (file, "access_binfo", BASELINK_ACCESS_BINFO (node), indent + 4); break; case OVERLOAD: print_node (file, "function", OVL_FUNCTION (node), indent+4); print_node (file, "chain", TREE_CHAIN (node), indent+4); break; case TEMPLATE_PARM_INDEX: indent_to (file, indent + 3); fprintf (file, "index %d level %d orig_level %d", TEMPLATE_PARM_IDX (node), TEMPLATE_PARM_LEVEL (node), TEMPLATE_PARM_ORIG_LEVEL (node)); break; case TEMPLATE_INFO: print_node (file, "template", TI_TEMPLATE (node), indent+4); print_node (file, "args", TI_ARGS (node), indent+4); if (TI_PENDING_TEMPLATE_FLAG (node)) { indent_to (file, indent + 3); fprintf (file, "pending_template"); } break; case ARGUMENT_PACK_SELECT: print_node (file, "pack", ARGUMENT_PACK_SELECT_FROM_PACK (node), indent+4); indent_to (file, indent + 3); fprintf (file, "index %d", ARGUMENT_PACK_SELECT_INDEX (node)); break; case DEFERRED_NOEXCEPT: print_node (file, "pattern", DEFERRED_NOEXCEPT_PATTERN (node), indent+4); print_node (file, "args", DEFERRED_NOEXCEPT_ARGS (node), indent+4); break; case LAMBDA_EXPR: cxx_print_lambda_node (file, node, indent); break; default: break; } }
rtx cxx_expand_expr (tree exp, rtx target, enum machine_mode tmode, int modifier, rtx *alt_rtl) { tree type = TREE_TYPE (exp); enum machine_mode mode = TYPE_MODE (type); enum tree_code code = TREE_CODE (exp); /* No sense saving up arithmetic to be done if it's all in the wrong mode to form part of an address. And force_operand won't know whether to sign-extend or zero-extend. */ if (mode != Pmode && modifier == EXPAND_SUM) modifier = EXPAND_NORMAL; switch (code) { case PTRMEM_CST: return expand_expr (cplus_expand_constant (exp), target, tmode, modifier); case OFFSET_REF: /* Offset refs should not make it through to here. */ abort (); case EMPTY_CLASS_EXPR: /* We don't need to generate any code for an empty class. */ return const0_rtx; case BASELINK: return expand_expr (BASELINK_FUNCTIONS (exp), target, tmode, modifier); default: return c_expand_expr (exp, target, tmode, modifier, alt_rtl); } }
tree build_throw (tree exp) { if (exp == error_mark_node) return exp; if (processing_template_decl) { if (cfun) current_function_returns_abnormally = 1; exp = build_min (THROW_EXPR, void_type_node, exp); SET_EXPR_LOCATION (exp, input_location); return exp; } if (exp && null_node_p (exp)) warning (0, "throwing NULL, which has integral, not pointer type"); if (exp != NULL_TREE) { if (!is_admissible_throw_operand_or_catch_parameter (exp, true)) return error_mark_node; } if (! doing_eh ()) return error_mark_node; if (exp) { tree throw_type; tree temp_type; tree cleanup; tree object, ptr; tree tmp; tree allocate_expr; /* The CLEANUP_TYPE is the internal type of a destructor. */ if (!cleanup_type) { tmp = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE); cleanup_type = build_pointer_type (tmp); } if (!throw_fn) { tree name = get_identifier ("__cxa_throw"); throw_fn = get_global_binding (name); if (!throw_fn) { /* Declare void __cxa_throw (void*, void*, void (*)(void*)). */ /* ??? Second argument is supposed to be "std::type_info*". */ tmp = build_function_type_list (void_type_node, ptr_type_node, ptr_type_node, cleanup_type, NULL_TREE); throw_fn = push_throw_library_fn (name, tmp); if (flag_tm) { tree itm_name = get_identifier ("_ITM_cxa_throw"); tree itm_fn = get_global_binding (itm_name); if (!itm_fn) itm_fn = push_throw_library_fn (itm_name, tmp); apply_tm_attr (itm_fn, get_identifier ("transaction_pure")); record_tm_replacement (throw_fn, itm_fn); } } } /* [except.throw] A throw-expression initializes a temporary object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from "array of T" or "function return T" to "pointer to T" or "pointer to function returning T" respectively. */ temp_type = is_bitfield_expr_with_lowered_type (exp); if (!temp_type) temp_type = cv_unqualified (type_decays_to (TREE_TYPE (exp))); /* OK, this is kind of wacky. The standard says that we call terminate when the exception handling mechanism, after completing evaluation of the expression to be thrown but before the exception is caught (_except.throw_), calls a user function that exits via an uncaught exception. So we have to protect the actual initialization of the exception object with terminate(), but evaluate the expression first. Since there could be temps in the expression, we need to handle that, too. We also expand the call to __cxa_allocate_exception first (which doesn't matter, since it can't throw). */ /* Allocate the space for the exception. */ allocate_expr = do_allocate_exception (temp_type); allocate_expr = get_target_expr (allocate_expr); ptr = TARGET_EXPR_SLOT (allocate_expr); TARGET_EXPR_CLEANUP (allocate_expr) = do_free_exception (ptr); CLEANUP_EH_ONLY (allocate_expr) = 1; object = build_nop (build_pointer_type (temp_type), ptr); object = cp_build_fold_indirect_ref (object); /* And initialize the exception object. */ if (CLASS_TYPE_P (temp_type)) { int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING; vec<tree, va_gc> *exp_vec; bool converted = false; /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes treated as an rvalue for the purposes of overload resolution to favor move constructors over copy constructors. */ if (/* Must be a local, automatic variable. */ VAR_P (exp) && DECL_CONTEXT (exp) == current_function_decl && ! TREE_STATIC (exp) /* The variable must not have the `volatile' qualifier. */ && !(cp_type_quals (TREE_TYPE (exp)) & TYPE_QUAL_VOLATILE)) { tree moved = move (exp); exp_vec = make_tree_vector_single (moved); moved = (build_special_member_call (object, complete_ctor_identifier, &exp_vec, TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE, tf_none)); release_tree_vector (exp_vec); if (moved != error_mark_node) { exp = moved; converted = true; } } /* Call the copy constructor. */ if (!converted) { exp_vec = make_tree_vector_single (exp); exp = (build_special_member_call (object, complete_ctor_identifier, &exp_vec, TREE_TYPE (object), flags, tf_warning_or_error)); release_tree_vector (exp_vec); } if (exp == error_mark_node) { error (" in thrown expression"); return error_mark_node; } } else { tmp = decay_conversion (exp, tf_warning_or_error); if (tmp == error_mark_node) return error_mark_node; exp = build2 (INIT_EXPR, temp_type, object, tmp); } /* Mark any cleanups from the initialization as MUST_NOT_THROW, since they are run after the exception object is initialized. */ cp_walk_tree_without_duplicates (&exp, wrap_cleanups_r, 0); /* Prepend the allocation. */ exp = build2 (COMPOUND_EXPR, TREE_TYPE (exp), allocate_expr, exp); /* Force all the cleanups to be evaluated here so that we don't have to do them during unwinding. */ exp = build1 (CLEANUP_POINT_EXPR, void_type_node, exp); throw_type = build_eh_type_type (prepare_eh_type (TREE_TYPE (object))); cleanup = NULL_TREE; if (type_build_dtor_call (TREE_TYPE (object))) { tree dtor_fn = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)), complete_dtor_identifier, 0); dtor_fn = BASELINK_FUNCTIONS (dtor_fn); mark_used (dtor_fn); if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (object))) { cxx_mark_addressable (dtor_fn); /* Pretend it's a normal function. */ cleanup = build1 (ADDR_EXPR, cleanup_type, dtor_fn); } } if (cleanup == NULL_TREE) cleanup = build_int_cst (cleanup_type, 0); /* ??? Indicate that this function call throws throw_type. */ tmp = cp_build_function_call_nary (throw_fn, tf_warning_or_error, ptr, throw_type, cleanup, NULL_TREE); /* Tack on the initialization stuff. */ exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); } else { /* Rethrow current exception. */ if (!rethrow_fn) { tree name = get_identifier ("__cxa_rethrow"); rethrow_fn = get_global_binding (name); if (!rethrow_fn) /* Declare void __cxa_rethrow (void). */ rethrow_fn = push_throw_library_fn (name, build_function_type_list (void_type_node, NULL_TREE)); if (flag_tm) apply_tm_attr (rethrow_fn, get_identifier ("transaction_pure")); } /* ??? Indicate that this function call allows exceptions of the type of the enclosing catch block (if known). */ exp = cp_build_function_call_vec (rethrow_fn, NULL, tf_warning_or_error); } exp = build1 (THROW_EXPR, void_type_node, exp); SET_EXPR_LOCATION (exp, input_location); return exp; }
int cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case THROW_EXPR: /* FIXME communicate throw type to backend, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: gimplify_must_not_throw_expr (expr_p, pre_p); ret = GS_OK; break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: /* Just ignore for now. Eventually we will want to pass this on to the debugger. */ *expr_p = build_empty_stmt (); ret = GS_ALL_DONE; break; case IF_STMT: gimplify_if_stmt (expr_p); ret = GS_OK; break; case FOR_STMT: gimplify_for_stmt (expr_p, pre_p); ret = GS_ALL_DONE; break; case WHILE_STMT: gimplify_while_stmt (expr_p); ret = GS_ALL_DONE; break; case DO_STMT: gimplify_do_stmt (expr_p); ret = GS_ALL_DONE; break; case SWITCH_STMT: gimplify_switch_stmt (expr_p); ret = GS_ALL_DONE; break; case CONTINUE_STMT: *expr_p = build_bc_goto (bc_continue); ret = GS_ALL_DONE; break; case BREAK_STMT: *expr_p = build_bc_goto (bc_break); ret = GS_ALL_DONE; break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
int cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; tree block = NULL; VEC(gimple, heap) *bind_expr_stack = NULL; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case THROW_EXPR: /* FIXME communicate throw type to back end, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: ret = gimplify_must_not_throw_expr (expr_p, pre_p); break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: /* Get the innermost inclosing GIMPLE_BIND that has a non NULL BLOCK, and append an IMPORTED_DECL to its BLOCK_VARS chained list. */ bind_expr_stack = gimple_bind_expr_stack (); if (bind_expr_stack) { int i; for (i = VEC_length (gimple, bind_expr_stack) - 1; i >= 0; i--) if ((block = gimple_bind_block (VEC_index (gimple, bind_expr_stack, i)))) break; } if (block) { tree using_directive; gcc_assert (TREE_OPERAND (*expr_p, 0)); using_directive = make_node (IMPORTED_DECL); TREE_TYPE (using_directive) = void_type_node; IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = TREE_OPERAND (*expr_p, 0); TREE_CHAIN (using_directive) = BLOCK_VARS (block); BLOCK_VARS (block) = using_directive; } /* The USING_STMT won't appear in GIMPLE. */ *expr_p = NULL; ret = GS_ALL_DONE; break; case FOR_STMT: gimplify_for_stmt (expr_p, pre_p); ret = GS_OK; break; case WHILE_STMT: gimplify_while_stmt (expr_p, pre_p); ret = GS_OK; break; case DO_STMT: gimplify_do_stmt (expr_p, pre_p); ret = GS_OK; break; case SWITCH_STMT: gimplify_switch_stmt (expr_p, pre_p); ret = GS_OK; break; case OMP_FOR: ret = cp_gimplify_omp_for (expr_p, pre_p); break; case CONTINUE_STMT: gimple_seq_add_stmt (pre_p, gimple_build_predict (PRED_CONTINUE, NOT_TAKEN)); gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_continue))); *expr_p = NULL_TREE; ret = GS_ALL_DONE; break; case BREAK_STMT: gimple_seq_add_stmt (pre_p, gimple_build_goto (get_bc_label (bc_break))); *expr_p = NULL_TREE; ret = GS_ALL_DONE; break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
int cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case THROW_EXPR: /* FIXME communicate throw type to backend, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: gimplify_must_not_throw_expr (expr_p, pre_p); ret = GS_OK; break; case INIT_EXPR: case MODIFY_EXPR: cp_gimplify_init_expr (expr_p, pre_p, post_p); ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an INTEGER_CST with RECORD_TYPE and value zero. */ *expr_p = build_int_cst (TREE_TYPE (*expr_p), 0); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: /* Just ignore for now. Eventually we will want to pass this on to the debugger. */ *expr_p = build_empty_stmt (); ret = GS_ALL_DONE; break; case IF_STMT: gimplify_if_stmt (expr_p); ret = GS_OK; break; default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
int cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) { int saved_stmts_are_full_exprs_p = 0; enum tree_code code = TREE_CODE (*expr_p); enum gimplify_status ret; if (STATEMENT_CODE_P (code)) { saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (*expr_p); } switch (code) { case PTRMEM_CST: *expr_p = cplus_expand_constant (*expr_p); ret = GS_OK; break; case AGGR_INIT_EXPR: simplify_aggr_init_expr (expr_p); ret = GS_OK; break; case VEC_INIT_EXPR: { location_t loc = input_location; tree init = VEC_INIT_EXPR_INIT (*expr_p); int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE); gcc_assert (EXPR_HAS_LOCATION (*expr_p)); input_location = EXPR_LOCATION (*expr_p); *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, init, VEC_INIT_EXPR_VALUE_INIT (*expr_p), from_array, tf_warning_or_error); cp_genericize_tree (expr_p); ret = GS_OK; input_location = loc; } break; case THROW_EXPR: /* FIXME communicate throw type to back end, probably by moving THROW_EXPR into ../tree.def. */ *expr_p = TREE_OPERAND (*expr_p, 0); ret = GS_OK; break; case MUST_NOT_THROW_EXPR: ret = gimplify_must_not_throw_expr (expr_p, pre_p); break; /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the LHS of an assignment might also be involved in the RHS, as in bug 25979. */ case INIT_EXPR: if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); cp_gimplify_init_expr (expr_p); if (TREE_CODE (*expr_p) != INIT_EXPR) return GS_OK; /* Otherwise fall through. */ case MODIFY_EXPR: { if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); /* If the back end isn't clever enough to know that the lhs and rhs types are the same, add an explicit conversion. */ tree op0 = TREE_OPERAND (*expr_p, 0); tree op1 = TREE_OPERAND (*expr_p, 1); if (!error_operand_p (op0) && !error_operand_p (op1) && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0)) || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1))) && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (op0), op1); else if ((is_gimple_lvalue (op1) || INDIRECT_REF_P (op1) || (TREE_CODE (op1) == CONSTRUCTOR && CONSTRUCTOR_NELTS (op1) == 0 && !TREE_CLOBBER_P (op1)) || (TREE_CODE (op1) == CALL_EXPR && !CALL_EXPR_RETURN_SLOT_OPT (op1))) && is_really_empty_class (TREE_TYPE (op0))) { /* Remove any copies of empty classes. We check that the RHS has a simple form so that TARGET_EXPRs and non-empty CONSTRUCTORs get reduced properly, and we leave the return slot optimization alone because it isn't a copy (FIXME so it shouldn't be represented as one). Also drop volatile variables on the RHS to avoid infinite recursion from gimplify_expr trying to load the value. */ if (!TREE_SIDE_EFFECTS (op1) || (DECL_P (op1) && TREE_THIS_VOLATILE (op1))) *expr_p = op0; else if (TREE_CODE (op1) == MEM_REF && TREE_THIS_VOLATILE (op1)) { /* Similarly for volatile MEM_REFs on the RHS. */ if (!TREE_SIDE_EFFECTS (TREE_OPERAND (op1, 0))) *expr_p = op0; else *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), TREE_OPERAND (op1, 0), op0); } else *expr_p = build2 (COMPOUND_EXPR, TREE_TYPE (*expr_p), op0, op1); } } ret = GS_OK; break; case EMPTY_CLASS_EXPR: /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); ret = GS_OK; break; case BASELINK: *expr_p = BASELINK_FUNCTIONS (*expr_p); ret = GS_OK; break; case TRY_BLOCK: genericize_try_block (expr_p); ret = GS_OK; break; case HANDLER: genericize_catch_block (expr_p); ret = GS_OK; break; case EH_SPEC_BLOCK: genericize_eh_spec_block (expr_p); ret = GS_OK; break; case USING_STMT: gcc_unreachable (); case FOR_STMT: case WHILE_STMT: case DO_STMT: case SWITCH_STMT: case CONTINUE_STMT: case BREAK_STMT: gcc_unreachable (); case OMP_FOR: case OMP_SIMD: case OMP_DISTRIBUTE: ret = cp_gimplify_omp_for (expr_p, pre_p); break; case EXPR_STMT: gimplify_expr_stmt (expr_p); ret = GS_OK; break; case UNARY_PLUS_EXPR: { tree arg = TREE_OPERAND (*expr_p, 0); tree type = TREE_TYPE (*expr_p); *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) : arg; ret = GS_OK; } break; case CILK_SPAWN_STMT: gcc_assert (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p)); /* If errors are seen, then just process it as a CALL_EXPR. */ if (!seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); case CALL_EXPR: if (fn_contains_cilk_spawn_p (cfun) && cilk_detect_spawn_and_unwrap (expr_p) && !seen_error ()) return (enum gimplify_status) gimplify_cilk_spawn (expr_p); default: ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); break; } /* Restore saved state. */ if (STATEMENT_CODE_P (code)) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; return ret; }
static void pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t) { enum tree_code code = TREE_CODE (t); switch (code) { case RESULT_DECL: pp_cxx_identifier (pp, "<return-value>"); break; case OVERLOAD: t = OVL_CURRENT (t); case VAR_DECL: case PARM_DECL: case CONST_DECL: case TYPE_DECL: case FUNCTION_DECL: case NAMESPACE_DECL: case FIELD_DECL: case LABEL_DECL: case USING_DECL: case TEMPLATE_DECL: t = DECL_NAME (t); case IDENTIFIER_NODE: if (t == NULL) pp_cxx_identifier (pp, "<unnamed>"); else if (IDENTIFIER_TYPENAME_P (t)) pp_cxx_conversion_function_id (pp, t); else { if (is_destructor_name (t)) { pp_complement (pp); /* FIXME: Why is this necessary? */ if (TREE_TYPE (t)) t = constructor_name (TREE_TYPE (t)); } pp_cxx_tree_identifier (pp, t); } break; case TEMPLATE_ID_EXPR: pp_cxx_template_id (pp, t); break; case BASELINK: pp_cxx_unqualified_id (pp, BASELINK_FUNCTIONS (t)); break; case RECORD_TYPE: case UNION_TYPE: case ENUMERAL_TYPE: pp_cxx_unqualified_id (pp, TYPE_NAME (t)); break; case TEMPLATE_TYPE_PARM: case TEMPLATE_TEMPLATE_PARM: if (TYPE_IDENTIFIER (t)) pp_cxx_unqualified_id (pp, TYPE_IDENTIFIER (t)); else pp_cxx_canonical_template_parameter (pp, t); break; case TEMPLATE_PARM_INDEX: pp_cxx_unqualified_id (pp, TEMPLATE_PARM_DECL (t)); break; default: pp_unsupported_tree (pp, t); break; } }
void cxx_print_xnode (FILE *file, tree node, int indent) { switch (TREE_CODE (node)) { case BASELINK: print_node (file, "functions", BASELINK_FUNCTIONS (node), indent + 4); print_node (file, "binfo", BASELINK_BINFO (node), indent + 4); print_node (file, "access_binfo", BASELINK_ACCESS_BINFO (node), indent + 4); break; case OVERLOAD: print_node (file, "function", OVL_FUNCTION (node), indent+4); print_node (file, "chain", TREE_CHAIN (node), indent+4); break; case TEMPLATE_PARM_INDEX: indent_to (file, indent + 3); fprintf (file, "index %d level %d orig_level %d", TEMPLATE_PARM_IDX (node), TEMPLATE_PARM_LEVEL (node), TEMPLATE_PARM_ORIG_LEVEL (node)); break; case TEMPLATE_INFO: print_node (file, "template", TI_TEMPLATE (node), indent+4); print_node (file, "args", TI_ARGS (node), indent+4); if (TI_PENDING_TEMPLATE_FLAG (node)) { indent_to (file, indent + 3); fprintf (file, "pending_template"); } break; case CONSTRAINT_INFO: { tree_constraint_info *cinfo = (tree_constraint_info *)node; if (cinfo->template_reqs) print_node (file, "template_reqs", cinfo->template_reqs, indent+4); if (cinfo->declarator_reqs) print_node (file, "declarator_reqs", cinfo->declarator_reqs, indent+4); print_node (file, "associated_constr", cinfo->associated_constr, indent+4); print_node_brief (file, "assumptions", cinfo->assumptions, indent+4); break; } case ARGUMENT_PACK_SELECT: print_node (file, "pack", ARGUMENT_PACK_SELECT_FROM_PACK (node), indent+4); indent_to (file, indent + 3); fprintf (file, "index %d", ARGUMENT_PACK_SELECT_INDEX (node)); break; case DEFERRED_NOEXCEPT: print_node (file, "pattern", DEFERRED_NOEXCEPT_PATTERN (node), indent+4); print_node (file, "args", DEFERRED_NOEXCEPT_ARGS (node), indent+4); break; case TRAIT_EXPR: indent_to (file, indent+4); fprintf (file, "kind %d", TRAIT_EXPR_KIND (node)); print_node (file, "type 1", TRAIT_EXPR_TYPE1 (node), indent+4); if (TRAIT_EXPR_TYPE2 (node)) print_node (file, "type 2", TRAIT_EXPR_TYPE2 (node), indent+4); break; case LAMBDA_EXPR: cxx_print_lambda_node (file, node, indent); break; default: break; } }