static tree java_build_function_call_expr (tree fn, tree orig_call) { int nargs = call_expr_nargs (orig_call); switch (nargs) { /* Although we could handle the 0-3 argument cases using the general logic in the default case, splitting them out permits folding to be performed without constructing a temporary CALL_EXPR. */ case 0: return build_call_expr (fn, 0); case 1: return build_call_expr (fn, 1, CALL_EXPR_ARG (orig_call, 0)); case 2: return build_call_expr (fn, 2, CALL_EXPR_ARG (orig_call, 0), CALL_EXPR_ARG (orig_call, 1)); case 3: return build_call_expr (fn, 3, CALL_EXPR_ARG (orig_call, 0), CALL_EXPR_ARG (orig_call, 1), CALL_EXPR_ARG (orig_call, 2)); default: { tree fntype = TREE_TYPE (fn); fn = build1 (ADDR_EXPR, build_pointer_type (fntype), fn); return fold (build_call_array (TREE_TYPE (fntype), fn, nargs, CALL_EXPR_ARGP (orig_call))); } } }
tree convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain) { if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; if (!TREE_TYPE (expr)) return expr; if (invalid_nonstatic_memfn_p (expr, complain)) return error_mark_node; if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { if (complain & tf_error) error ("pseudo-destructor is not called"); return error_mark_node; } if (VOID_TYPE_P (TREE_TYPE (expr))) return expr; switch (TREE_CODE (expr)) { case COND_EXPR: { /* The two parts of a cond expr might be separate lvalues. */ tree op1 = TREE_OPERAND (expr,1); tree op2 = TREE_OPERAND (expr,2); tree new_op1 = convert_to_void (op1, (implicit && !TREE_SIDE_EFFECTS (op2) ? "second operand of conditional" : NULL), complain); tree new_op2 = convert_to_void (op2, (implicit && !TREE_SIDE_EFFECTS (op1) ? "third operand of conditional" : NULL), complain); expr = build3 (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); break; } case COMPOUND_EXPR: { /* The second part of a compound expr contains the value. */ tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void (op1, (implicit && !TREE_NO_WARNING (expr) ? "right-hand operand of comma" : NULL), complain); if (new_op1 != op1) { tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1); expr = t; } break; } case NON_LVALUE_EXPR: case NOP_EXPR: /* These have already decayed to rvalue. */ break; case CALL_EXPR: /* We have a special meaning for volatile void fn(). */ break; case INDIRECT_REF: { tree type = TREE_TYPE (expr); int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE; int is_volatile = TYPE_VOLATILE (type); int is_complete = COMPLETE_TYPE_P (complete_type (type)); /* Can't load the value if we don't know the type. */ if (is_volatile && !is_complete) { if (complain & tf_warning) warning (0, "object of incomplete type %qT will not be accessed in %s", type, implicit ? implicit : "void context"); } /* Don't load the value if this is an implicit dereference, or if the type needs to be handled by ctors/dtors. */ else if (is_volatile && (is_reference || TREE_ADDRESSABLE (type))) { if (complain & tf_warning) warning (0, "object of type %qT will not be accessed in %s", TREE_TYPE (TREE_OPERAND (expr, 0)), implicit ? implicit : "void context"); } if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type)) expr = TREE_OPERAND (expr, 0); break; } case VAR_DECL: { /* External variables might be incomplete. */ tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (complete_type (type)); if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning)) warning (0, "object %qE of incomplete type %qT will not be accessed in %s", expr, type, implicit ? implicit : "void context"); break; } case TARGET_EXPR: /* Don't bother with the temporary object returned from a function if we don't use it and don't need to destroy it. We'll still allocate space for it in expand_call or declare_return_variable, but we don't need to track it through all the tree phases. */ if (TARGET_EXPR_IMPLICIT_P (expr) && TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (expr))) { tree init = TARGET_EXPR_INITIAL (expr); if (TREE_CODE (init) == AGGR_INIT_EXPR && !AGGR_INIT_VIA_CTOR_P (init)) { tree fn = AGGR_INIT_EXPR_FN (init); expr = build_call_array (TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), fn, aggr_init_expr_nargs (init), AGGR_INIT_EXPR_ARGP (init)); } } break; default:; } { tree probe = expr; if (TREE_CODE (probe) == ADDR_EXPR) probe = TREE_OPERAND (expr, 0); if (type_unknown_p (probe)) { /* [over.over] enumerates the places where we can take the address of an overloaded function, and this is not one of them. */ if (complain & tf_error) error ("%s cannot resolve address of overloaded function", implicit ? implicit : "void cast"); else return error_mark_node; expr = void_zero_node; } else if (implicit && probe == expr && is_overloaded_fn (probe)) { /* Only warn when there is no &. */ if (complain & tf_warning) warning (OPT_Waddress, "%s is a reference, not call, to function %qE", implicit, expr); if (TREE_CODE (expr) == COMPONENT_REF) expr = TREE_OPERAND (expr, 0); } } if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr))) { if (implicit && warn_unused_value && !TREE_NO_WARNING (expr) && !processing_template_decl) { /* The middle end does not warn about expressions that have been explicitly cast to void, so we must do so here. */ if (!TREE_SIDE_EFFECTS (expr)) { if (complain & tf_warning) warning (OPT_Wunused_value, "%s has no effect", implicit); } else { tree e; enum tree_code code; enum tree_code_class tclass; e = expr; /* We might like to warn about (say) "(int) f()", as the cast has no effect, but the compiler itself will generate implicit conversions under some circumstances. (For example a block copy will be turned into a call to "__builtin_memcpy", with a conversion of the return value to an appropriate type.) So, to avoid false positives, we strip conversions. Do not use STRIP_NOPs because it will not strip conversions to "void", as that is not a mode-preserving conversion. */ while (TREE_CODE (e) == NOP_EXPR) e = TREE_OPERAND (e, 0); code = TREE_CODE (e); tclass = TREE_CODE_CLASS (code); if ((tclass == tcc_comparison || tclass == tcc_unary || (tclass == tcc_binary && !(code == MODIFY_EXPR || code == INIT_EXPR || code == PREDECREMENT_EXPR || code == PREINCREMENT_EXPR || code == POSTDECREMENT_EXPR || code == POSTINCREMENT_EXPR))) && (complain & tf_warning)) warning (OPT_Wunused_value, "value computed is not used"); } } expr = build1 (CONVERT_EXPR, void_type_node, expr); } if (! TREE_SIDE_EFFECTS (expr)) expr = void_zero_node; return expr; }