From b9c74b4dc40904cbb3882d1c245d4eeae24139f4 Mon Sep 17 00:00:00 2001 From: ian Date: Mon, 20 Apr 2009 19:35:00 +0000 Subject: gcc/: Fix enum conversions which are invalid in C++: * auto-inc-dec.c (attempt_change): Change 0 to SET in function call. * calls.c (store_one_arg): Change 0 to EXPAND_NORMAL in function call. * cse.c (hash_rtx_cb): Change 0 to VOIDmode in function call. * dbgcnt.c (dbg_cnt_set_limit_by_name): Add cast to enum type. * dbxout.c (dbxout_symbol): Change 0 to VOIDmode in function call. (dbxout_parms): Likewise. * df-core.c (df_set_flags): Change changeable_flags parameter to int. (df_clear_flags): Likewise. * df-problems.c (df_rd_bb_local_compute_process_def): Change top_flag parameter to int. (df_chain_create_bb_process_use): Likewise. (df_chain_add_problem): Change chain_flags parameter to unsigned int. Remove cast. * df-scan.c (df_ref_create): Change ref_flags parameter to int. (df_ref_create_structure, df_def_record_1): Likewise. (df_defs_record, df_uses_record, df_get_call_refs): Likewise. (df_notes_rescan): Change 0 to VOIDmode in function call. (df_get_call_refs, df_insn_refs_collect): Likewise. (df_bb_regs_collect): Likewise. (df_entry_block_defs_collect): Likewise. (df_exit_block_uses_collect): Likewise. * df.h: Update declarations. * double-int.c (double_int_divmod): Add cast to enum type. * dse.c (replace_inc_dec): Reverse parameters to gen_int_mode. * dwarf2out.c (new_reg_loc_descr): Add casts to enum type. (based_loc_descr): Likewise. (loc_descriptor_from_tree_1): Change first_op and second_op to enum dwarf_location_atom. Add cast to enum type. * expmed.c (init_expmed): Change 0 to SET in function call. * expr.c (init_expr_target): Change 0 to VOIDmode in function call. (expand_expr_real_1): Change 0 to EXPAND_NORMAL in function call. (do_store_flag): Likewise. * fixed-value.h (struct fixed_value): Change mode to enum machine_mode. * function.c (assign_parms): Change 0 to VOIDmode in function call. * genautomata.c (insert_automaton_decl): Change 1 to INSERT in function call. (insert_insn_decl, insert_decl, insert_state): Likewise. (automata_list_finish): Likewise. * genrecog.c (process_define_predicate): Add cast to enum type. * gensupport.c (init_predicate_table): Add cast to enum type. * gimple.c (gimple_build_return): Change 0 to ERROR_MARK in function call. (gimple_build_call_1, gimple_build_label): Likewise. (gimple_build_goto, gimple_build_asm_1): Likewise. (gimple_build_switch_1, gimple_build_cdt): Likewise. * gimple.h (GIMPLE_CHECK): Change 0 to ERROR_MARK in function call. (enum fallback): Rename from enum fallback_t. (fallback_t): Typedef as int. * gimple-low.c (lower_builtin_setjmp): Change TSI_SAME_STMT to GSI_SAME_STMT in function call. * ira.c (setup_class_subset_and_memory_move_costs): Add casts to enum type. (setup_reg_class_relations): Likewise. (setup_reg_class_nregs): Change cl to int. Add casts to enum type. (setup_prohibited_class_mode_regs): Add cast to enum type. (setup_prohibited_mode_move_regs): Likewise. * ira-costs.c (record_reg_classes): Change rclass to enum reg_class. (record_address_regs): Change i to enum reg_class. * lists.c (alloc_EXPR_LIST): Add cast to enum type. * machmode.h (GET_MODE_CLASS): Cast value to enum mode_class. (GET_MODE_WIDER_MODE): Cast value to enum machine_mode. (GET_MODE_2XWIDER_MODE): Likewise. (GET_CLASS_NARROWEST_MODE): Likewise. * omp-low.c (expand_omp_for): Add cast to enum type. * optabs.c (debug_optab_libfuncs): Add casts to enum type. * opts.c (enable_warning_as_error): Change kind to diagostic_t. * postreload.c (reload_cse_simplify_operands): Change rclass local to enum reg_class. * predict.c (combine_predictions_for_insn): Change best_predictor and predictor to enum br_predictor. (combine_predictions_for_bb): Likewise. (build_predict_expr): Change assignment to PREDICT_EXPR_OUTCOME to use SET_PREDICT_EXPR_OUTCOME. * real.c (real_arithmetic): Change icode to code in function call. * reginfo.c (init_move_cost): Add casts to enum type. (init_reg_sets_1, init_fake_stack_mems): Likewise. * regmove.c (regclass_compatible_p): Change class0 and class1 to enum reg_class. * reload.c (find_valid_class): Add casts to enum type. (push_reload): Change 0 to NO_REGS in function call. (find_reloads): Change this_alternative to array of enum reg_class. Remove some now-unnecessary casts. (make_memloc): Change 0 to VOIDmode in function call. * reload1.c (reload): Change 0 to VOIDmode in function call. (eliminate_regs_1, elimination_effects): Likewise. (eliminate_regs_in_insn): Likewise. (emit_input_reload_insns): Add cast to enum type. (delete_output_reload): Change 0 to VOIDmode in function call. * reorg.c (insn_sets_resource_p): Convert include_delayed_effects to enum type in function call. * tree.h (PREDICT_EXPR_OUTCOME): Add cast to enum type. (SET_PREDICT_EXPR_OUTCOME): Define. * tree-dump.c (get_dump_file_info): Change phase parameter to int. (get_dump_file_name, dump_begin, dump_enabled_p): Likewise. (dump_initialized_p, dump_flag_name, dump_end): Likewise. (dump_function): Likewise. * tree-dump.h: Update declarations. * tree-pass.h: Update declarations. * varasm.c (assemble_integer): Change mclass to enum mode_class. * config/arm/arm.c (thumb_legitimize_reload_address): Add cast to enum type. (arm_rtx_costs_1): Correct parenthesization. (arm_rtx_costs): Add casts to enum type. (adjacent_mem_locations): Reverse arguments to const_ok_for_op. (vfp_emit_fstmd): Use add_rg_note. (emit_multi_reg_push, emit_sfm): Likewise. (thumb_set_frame_pointer): Likewise. (arm_expand_prologue): Likewise. (arm_regno_class): Change return type to enum reg_class. (thumb1_expand_prologue): Use add_reg_note. * config/arm/arm-protos.h (arm_regno_class): Update declaration. * config/arm/arm.h (INITIALIZE_TRAMPOLINE): Change 0 to LCT_NORMAL in function call. * config/arm/gentune.sh: Add cast to enum type. * config/arm/arm-tune.md: Rebuild. * config/i386/i386.c (ix86_expand_prologue): Use add_reg_note. (ix86_split_fp_branch, predict_jump): Likewise. (ix86_expand_multi_arg_builtin): Change sub_code from enum insn_code to enum rtx_code. (ix86_builtin_vectorized_function): Add cast to enum type. * config/i386/i386.md (truncdfsf2): Change slot to enum ix86_stack_slot. (truncxf2, isinf2): Likewise. * config/i386/i386-c.c (ix86_pragma_target_parse): Add cast to enum type. * config/ia64/ia64.c (ia64_split_tmode_move): Use add_reg_note. (spill_restore_mem, do_spill, ia64_expand_prologue): Likewise. (insert_bundle_state): Change 1 to INSERT in function call. (ia64_add_bundle_selector_before): Likewise. * config/ia64/ia64.md (cpu attr): Add cast to enum type. (save_stack_nonlocal): Change 0 to LCT_NORMAL in function call. (restore_stack_nonlocal): Likewise. * config/mips/mips.h (MIPS_ICACHE_SYNC): Change 0 to LCT_NORMAL in function call. * config/mips/mips.c (mips_binary_cost): Change 0 to SET in function call. (mips_rtx_costs): Likewise. (mips_override_options): Add casts to enum type. * config/mips/sdemtk.h (MIPS_ICACHE_SYNC): Change 0 to LCT_NORMAL in function call. * config/pa/pa.c (legitimize_pic_address): Use add_reg_note. (store_reg, set_reg_plus_d): Likewise. (hppa_expand_prologue, hppa_profile_hook): Likewise. * config/rs6000/rs6000.c (rs6000_init_hard_regno_mode_ok): Add cast to enum type. (altivec_expand_vec_set_builtin): Change 0 to EXPAND_NORMAL in function call. (emit_unlikely_jump): Use add_reg_note. (rs6000_emit_allocate_stack): Likewise. (rs6000_frame_related, rs6000_emit_prologue): Likewise. (output_toc): Change 1 to INSERT in function call. (output_profile_hook): Change 0 to LCT_NORMAL in function call. (rs6000_initialize_trampoline): Likewise. (rs6000_init_dwarf_reg_sizes_extra): Change 0 to EXPAND_NORMAL in function call. * config/s390/s390.c (s390_rtx_costs): Add cast to enum type. (s390_expand_movmem): Change 0 to OPTAB_DIRECT in function call. (s390_expand_setmem, s390_expand_cmpmem): Likewise. (save_gprs): Use add_reg_note. (s390_emit_prologue): Likewise. (s390_expand_builtin): Change 0 to EXPAND_NORMAL in function call. * config/sparc/sparc.c (sparc_expand_prologue): Use add_reg_note. (sparc_fold_builtin): Add cast to enum type. * config/spu/spu.c (spu_emit_branch_or_set): Change ior_code to enum insn_code. (spu_expand_prologue): Use add_reg_note. (expand_builtin_args): Change 0 to EXPAND_NORMAL in function call. * c-parser.c (c_parser_attributes): Change VEC back to tree list. (c_parser_postfix_expression_after_primary): Get VEC for list of arguments. Get original types of arguments. Call build_function_call_vec. (cached_expr_list_1, cached_expr_list_2): New static variables. (c_parser_expr_list): Change return type to VEC *. Add p_orig_types parameter. Change all callers. (c_parser_release_expr): New static function. (c_parser_vec_to_tree_list): New static function. * c-typeck.c (build_function_call): Rewrite to build a VEC and call build_function_call_vec. (build_function_call_vec): New function, based on old build_function_call. (convert_arguments): Remove nargs and argarray parameters. Change values to a VEC. Add origtypes parameter. (build_modify_expr): Add rhs_origtype parameter. Change all callers. (convert_for_assignment): Add origtype parameter. Change all callers. If warn_cxx_compat, check for conversion to an enum type when calling a function. (store_init_value): Add origtype parameter. Change all callers. (digest_init): Likewise. (struct init_node): Add origtype field. (add_pending_init): Add origtype parameter. Change all callers. (output_init_element): Likewise. (output_pending_init_elements): Pass origtype from init_node to output_init_element. (process_init_elemnt): Pass origtype from c_expr to output_init_element. (c_finish_return): Add origtype parameter. Change all callers. * c-common.c (sync_resolve_size): Change params to VEC *. Change caller. (sync_resolve_params): Likewise. (sync_resolve_return): Change params to first_param. Change caller. (resolve_overloaded_builtins): Change params to VEC *. Change callers. Save first parameter around call to build_function_call_vec. * c-decl.c (finish_decl): Add origtype parameter. Change all callers. Call build_function_call_vec rather than build_function_call for cleanup. * c-tree.h: Update declarations. * c-common.h: Update declarations. * stub-objc.c (objc_rewrite_function_call): Change parameter from params to first_param. * target.h (struct gcc_target): Change resolve_overloaded_builtin params parameter from tree to void *. * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): Change arglist parameter to have type void *, and to be a pointer to a VEC. * config/rs6000/rs6000-protos.h (altivec_resolve_overloaded_builtin): Update declaration. * config/spu/spu-c.c (spu_resolved_overloaded_builtin): Change fnargs parameter to have type void *, and to be a pointer to a VEC. Call build_function_call_vec instead of build_function_call. * config/spu/spu-protos.h (spu_expand_builtin): Update declaration. gcc/cp/: * typeck.c (build_function_call_vec): New function. (cp_build_function_call): Only pass first parameter to objc_rewrite_function_call. (build_modify_expr): Add rhs_origtype parameter. Change all callers. * decl.c (finish_decl): Add origtype parameter. Change all callers. * semantics.c (finish_call_expr): Pass VEC to resolve_overloaded_builtin. gcc/objc: * objc-act.c (objc_rewrite_function_call): Change parameter from params to first_param. Change all callers. gcc/testsuite: * gcc.dg/Wcxx-compat-3.c: New testcase. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@146451 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/c-typeck.c | 242 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 81 deletions(-) (limited to 'gcc/c-typeck.c') diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index 96b1a5da599..7fc55e230e4 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -87,9 +87,10 @@ static int comp_target_types (tree, tree); static int function_types_compatible_p (const_tree, const_tree); static int type_lists_compatible_p (const_tree, const_tree); static tree lookup_field (tree, tree); -static int convert_arguments (int, tree *, tree, tree, tree, tree); +static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree, + tree); static tree pointer_diff (tree, tree); -static tree convert_for_assignment (tree, tree, enum impl_conv, bool, +static tree convert_for_assignment (tree, tree, tree, enum impl_conv, bool, tree, tree, int); static tree valid_compound_expr_initializer (tree, tree); static void push_string (const char *); @@ -97,12 +98,12 @@ static void push_member_name (tree); static int spelling_length (void); static char *print_spelling (char *); static void warning_init (int, const char *); -static tree digest_init (tree, tree, bool, bool, int); -static void output_init_element (tree, bool, tree, tree, int, bool); +static tree digest_init (tree, tree, tree, bool, bool, int); +static void output_init_element (tree, tree, bool, tree, tree, int, bool); static void output_pending_init_elements (int); static int set_designator (int); static void push_range_stack (tree); -static void add_pending_init (tree, tree, bool); +static void add_pending_init (tree, tree, tree, bool); static void set_nonincremental_init (void); static void set_nonincremental_init_from_string (tree); static tree find_init_member (tree); @@ -2409,6 +2410,29 @@ c_expr_sizeof_type (struct c_type_name *t) tree build_function_call (tree function, tree params) +{ + VEC(tree,gc) *vec; + tree ret; + + vec = VEC_alloc (tree, gc, list_length (params)); + for (; params; params = TREE_CHAIN (params)) + VEC_quick_push (tree, vec, TREE_VALUE (params)); + ret = build_function_call_vec (function, vec, NULL); + VEC_free (tree, gc, vec); + return ret; +} + +/* Build a function call to function FUNCTION with parameters PARAMS. + ORIGTYPES, if not NULL, is a vector of types; each element is + either NULL or the original type of the corresponding element in + PARAMS. The original type may differ from TREE_TYPE of the + parameter for enums. FUNCTION's data type may be a function type + or pointer-to-function. This function changes the elements of + PARAMS. */ + +tree +build_function_call_vec (tree function, VEC(tree,gc) *params, + VEC(tree,gc) *origtypes) { tree fntype, fundecl = 0; tree name = NULL_TREE, result; @@ -2439,7 +2463,9 @@ build_function_call (tree function, tree params) /* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF expressions, like those used for ObjC messenger dispatches. */ - function = objc_rewrite_function_call (function, params); + if (!VEC_empty (tree, params)) + function = objc_rewrite_function_call (function, + VEC_index (tree, params, 0)); function = c_fully_fold (function, false, NULL); @@ -2464,10 +2490,8 @@ build_function_call (tree function, tree params) /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ - nargs = list_length (params); - argarray = (tree *) alloca (nargs * sizeof (tree)); - nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype), - params, function, fundecl); + nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes, + function, fundecl); if (nargs < 0) return error_mark_node; @@ -2496,7 +2520,8 @@ build_function_call (tree function, tree params) /* Before the abort, allow the function arguments to exit or call longjmp. */ for (i = 0; i < nargs; i++) - trap = build2 (COMPOUND_EXPR, void_type_node, argarray[i], trap); + trap = build2 (COMPOUND_EXPR, void_type_node, + VEC_index (tree, params, i), trap); if (VOID_TYPE_P (return_type)) { @@ -2521,6 +2546,8 @@ build_function_call (tree function, tree params) } } + argarray = VEC_address (tree, params); + /* Check that arguments to builtin functions match the expectations. */ if (fundecl && DECL_BUILT_IN (fundecl) @@ -2559,34 +2586,31 @@ build_function_call (tree function, tree params) return require_complete_type (result); } -/* Convert the argument expressions in the list VALUES - to the types in the list TYPELIST. The resulting arguments are - stored in the array ARGARRAY which has size NARGS. +/* Convert the argument expressions in the vector VALUES + to the types in the list TYPELIST. If TYPELIST is exhausted, or when an element has NULL as its type, perform the default conversions. - PARMLIST is the chain of parm decls for the function being called. - It may be 0, if that info is not available. - It is used only for generating error messages. + ORIGTYPES is the original types of the expressions in VALUES. This + holds the type of enum values which have been converted to integral + types. It may be NULL. FUNCTION is a tree for the called function. It is used only for error messages, where it is formatted with %qE. This is also where warnings about wrong number of args are generated. - VALUES is a chain of TREE_LIST nodes with the elements of the list - in the TREE_VALUE slots of those nodes. - Returns the actual number of arguments processed (which may be less - than NARGS in some error situations), or -1 on failure. */ + than the length of VALUES in some error situations), or -1 on + failure. */ static int -convert_arguments (int nargs, tree *argarray, - tree typelist, tree values, tree function, tree fundecl) +convert_arguments (tree typelist, VEC(tree,gc) *values, + VEC(tree,gc) *origtypes, tree function, tree fundecl) { - tree typetail, valtail; - int parmnum; + tree typetail, val; + unsigned int parmnum; const bool type_generic = fundecl && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl))); bool type_generic_remove_excess_precision = false; @@ -2626,20 +2650,20 @@ convert_arguments (int nargs, tree *argarray, } /* Scan the given expressions and types, producing individual - converted arguments and storing them in ARGARRAY. */ + converted arguments. */ - for (valtail = values, typetail = typelist, parmnum = 0; - valtail; - valtail = TREE_CHAIN (valtail), parmnum++) + for (typetail = typelist, parmnum = 0; + VEC_iterate (tree, values, parmnum, val); + ++parmnum) { tree type = typetail ? TREE_VALUE (typetail) : 0; - tree val = TREE_VALUE (valtail); tree valtype = TREE_TYPE (val); tree rname = function; int argnum = parmnum + 1; const char *invalid_func_diag; bool excess_precision = false; bool npc; + tree parmval; if (type == void_type_node) { @@ -2675,7 +2699,6 @@ convert_arguments (int nargs, tree *argarray, if (type != 0) { /* Formal parm type is specified by a function prototype. */ - tree parmval; if (type == error_mark_node || !COMPLETE_TYPE_P (type)) { @@ -2684,6 +2707,8 @@ convert_arguments (int nargs, tree *argarray, } else { + tree origtype; + /* Optionally warn about conversions that differ from the default conversions. */ if (warn_traditional_conversion || warn_traditional) @@ -2812,7 +2837,11 @@ convert_arguments (int nargs, tree *argarray, sake of better warnings from convert_and_check. */ if (excess_precision) val = build1 (EXCESS_PRECISION_EXPR, valtype, val); - parmval = convert_for_assignment (type, val, ic_argpass, npc, + origtype = (origtypes == NULL + ? NULL_TREE + : VEC_index (tree, origtypes, parmnum)); + parmval = convert_for_assignment (type, val, origtype, + ic_argpass, npc, fundecl, function, parmnum + 1); @@ -2821,7 +2850,6 @@ convert_arguments (int nargs, tree *argarray, && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))) parmval = default_conversion (parmval); } - argarray[parmnum] = parmval; } else if (TREE_CODE (valtype) == REAL_TYPE && (TYPE_PRECISION (valtype) @@ -2829,15 +2857,15 @@ convert_arguments (int nargs, tree *argarray, && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (valtype))) { if (type_generic) - argarray[parmnum] = val; + parmval = val; else /* Convert `float' to `double'. */ - argarray[parmnum] = convert (double_type_node, val); + parmval = convert (double_type_node, val); } else if (excess_precision && !type_generic) /* A "double" argument with excess precision being passed without a prototype or in variable arguments. */ - argarray[parmnum] = convert (valtype, val); + parmval = convert (valtype, val); else if ((invalid_func_diag = targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val))) { @@ -2846,13 +2874,15 @@ convert_arguments (int nargs, tree *argarray, } else /* Convert `short' and `char' to full-size `int'. */ - argarray[parmnum] = default_conversion (val); + parmval = default_conversion (val); + + VEC_replace (tree, values, parmnum, parmval); if (typetail) typetail = TREE_CHAIN (typetail); } - gcc_assert (parmnum == nargs); + gcc_assert (parmnum == VEC_length (tree, values)); if (typetail != 0 && TREE_VALUE (typetail) != void_type_node) { @@ -4069,7 +4099,7 @@ build_c_cast (tree type, tree expr) "ISO C forbids casts to union type"); t = digest_init (type, build_constructor_single (type, field, value), - false, true, 0); + NULL_TREE, false, true, 0); TREE_CONSTANT (t) = TREE_CONSTANT (value); return t; } @@ -4263,12 +4293,15 @@ c_cast_expr (struct c_type_name *type_name, tree expr) MODIFYCODE is the code for a binary operator that we use to combine the old value of LHS with RHS to get the new value. Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. + If RHS_ORIGTYPE is not NULL_TREE, it is the original type of RHS, + which may differ from TREE_TYPE (RHS) for an enum value. LOCATION is the location of the MODIFYCODE operator. */ tree build_modify_expr (location_t location, - tree lhs, enum tree_code modifycode, tree rhs) + tree lhs, enum tree_code modifycode, tree rhs, + tree rhs_origtype) { tree result; tree newrhs; @@ -4298,7 +4331,7 @@ build_modify_expr (location_t location, if (TREE_CODE (lhs) == C_MAYBE_CONST_EXPR) { tree inner = build_modify_expr (location, C_MAYBE_CONST_EXPR_EXPR (lhs), - modifycode, rhs); + modifycode, rhs, rhs_origtype); if (inner == error_mark_node) return error_mark_node; result = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (inner), @@ -4318,6 +4351,10 @@ build_modify_expr (location_t location, lhs = stabilize_reference (lhs); newrhs = build_binary_op (location, modifycode, lhs, rhs, 1); + + /* The original type of the right hand side is no longer + meaningful. */ + rhs_origtype = NULL_TREE; } /* Give an error for storing in something that is 'const'. */ @@ -4362,8 +4399,8 @@ build_modify_expr (location_t location, newrhs = c_fully_fold (newrhs, false, NULL); if (rhs_semantic_type) newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs); - newrhs = convert_for_assignment (lhstype, newrhs, ic_assign, npc, - NULL_TREE, NULL_TREE, 0); + newrhs = convert_for_assignment (lhstype, newrhs, rhs_origtype, ic_assign, + npc, NULL_TREE, NULL_TREE, 0); if (TREE_CODE (newrhs) == ERROR_MARK) return error_mark_node; @@ -4392,15 +4429,17 @@ build_modify_expr (location_t location, if (olhstype == TREE_TYPE (result)) return result; - result = convert_for_assignment (olhstype, result, ic_assign, false, - NULL_TREE, NULL_TREE, 0); + result = convert_for_assignment (olhstype, result, rhs_origtype, ic_assign, + false, NULL_TREE, NULL_TREE, 0); protected_set_expr_location (result, location); return result; } -/* Convert value RHS to type TYPE as preparation for an assignment - to an lvalue of type TYPE. NULL_POINTER_CONSTANT says whether RHS - was a null pointer constant before any folding. +/* Convert value RHS to type TYPE as preparation for an assignment to + an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the + original type of RHS; this differs from TREE_TYPE (RHS) for enum + types. NULL_POINTER_CONSTANT says whether RHS was a null pointer + constant before any folding. The real work of conversion is done by `convert'. The purpose of this function is to generate error messages for assignments that are not allowed in C. @@ -4411,8 +4450,8 @@ build_modify_expr (location_t location, PARMNUM is the number of the argument, for printing in error messages. */ static tree -convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, - bool null_pointer_constant, +convert_for_assignment (tree type, tree rhs, tree origtype, + enum impl_conv errtype, bool null_pointer_constant, tree fundecl, tree function, int parmnum) { enum tree_code codel = TREE_CODE (type); @@ -4504,6 +4543,31 @@ convert_for_assignment (tree type, tree rhs, enum impl_conv errtype, objc_ok = objc_compare_types (type, rhstype, parmno, rname); } + if (warn_cxx_compat) + { + tree checktype = origtype != NULL_TREE ? origtype : rhstype; + if (checktype != error_mark_node + && TREE_CODE (type) == ENUMERAL_TYPE + && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type)) + { + /* FIXME: Until the gcc source code is converted, we only + warn about parameter passing. We will add the other + cases when bootstrap succeeds with them. */ + if (errtype == ic_argpass) + { + WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat, + G_("enum conversion when passing argument " + "%d of %qE is invalid in C++"), + G_("enum conversion in assignment is " + "invalid in C++"), + G_("enum conversion in initialization is " + "invalid in C++"), + G_("enum conversion in return is " + "invalid in C++")); + } + } + } + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) return rhs; @@ -4945,10 +5009,11 @@ valid_compound_expr_initializer (tree value, tree endtype) /* Perform appropriate conversions on the initial value of a variable, store it in the declaration DECL, and print any error messages that are appropriate. + If ORIGTYPE is not NULL_TREE, it is the original type of INIT. If the init is invalid, store an ERROR_MARK. */ void -store_init_value (tree decl, tree init) +store_init_value (tree decl, tree init, tree origtype) { tree value, type; bool npc = false; @@ -4963,7 +5028,7 @@ store_init_value (tree decl, tree init) if (init) npc = null_pointer_constant_p (init); - value = digest_init (type, init, npc, true, TREE_STATIC (decl)); + value = digest_init (type, init, origtype, npc, true, TREE_STATIC (decl)); /* Store the expression if valid; else report error. */ @@ -5194,6 +5259,8 @@ maybe_warn_string_init (tree type, struct c_expr expr) /* Digest the parser output INIT as an initializer for type TYPE. Return a C expression of type TYPE to represent the initial value. + If ORIGTYPE is not NULL_TREE, it is the original type of INIT. + NULL_POINTER_CONSTANT is true if INIT is a null pointer constant. If INIT is a string constant, STRICT_STRING is true if it is @@ -5204,7 +5271,7 @@ maybe_warn_string_init (tree type, struct c_expr expr) elements are seen. */ static tree -digest_init (tree type, tree init, bool null_pointer_constant, +digest_init (tree type, tree init, tree origtype, bool null_pointer_constant, bool strict_string, int require_constant) { enum tree_code code = TREE_CODE (type); @@ -5431,8 +5498,8 @@ digest_init (tree type, tree init, bool null_pointer_constant, /* Added to enable additional -Wmissing-format-attribute warnings. */ if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE) - inside_init = convert_for_assignment (type, inside_init, ic_init, - null_pointer_constant, + inside_init = convert_for_assignment (type, inside_init, origtype, + ic_init, null_pointer_constant, NULL_TREE, NULL_TREE, 0); return inside_init; } @@ -5451,7 +5518,7 @@ digest_init (tree type, tree init, bool null_pointer_constant, inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type, inside_init); inside_init - = convert_for_assignment (type, inside_init, ic_init, + = convert_for_assignment (type, inside_init, origtype, ic_init, null_pointer_constant, NULL_TREE, NULL_TREE, 0); @@ -5549,6 +5616,7 @@ struct init_node int balance; tree purpose; tree value; + tree origtype; }; /* Tree of pending elements at this constructor level. @@ -6418,7 +6486,8 @@ set_init_label (tree fieldname) /* Add a new initializer to the tree of pending initializers. PURPOSE identifies the initializer, either array index or field in a structure. - VALUE is the value of that index or field. + VALUE is the value of that index or field. If ORIGTYPE is not + NULL_TREE, it is the original type of VALUE. IMPLICIT is true if value comes from pop_init_level (1), the new initializer has been merged with the existing one @@ -6426,7 +6495,7 @@ set_init_label (tree fieldname) existing initializer. */ static void -add_pending_init (tree purpose, tree value, bool implicit) +add_pending_init (tree purpose, tree value, tree origtype, bool implicit) { struct init_node *p, **q, *r; @@ -6452,6 +6521,7 @@ add_pending_init (tree purpose, tree value, bool implicit) warning_init (OPT_Woverride_init, "initialized field overwritten"); } p->value = value; + p->origtype = origtype; return; } } @@ -6478,6 +6548,7 @@ add_pending_init (tree purpose, tree value, bool implicit) warning_init (OPT_Woverride_init, "initialized field overwritten"); } p->value = value; + p->origtype = origtype; return; } } @@ -6486,6 +6557,7 @@ add_pending_init (tree purpose, tree value, bool implicit) r = GGC_NEW (struct init_node); r->purpose = purpose; r->value = value; + r->origtype = origtype; *q = r; r->parent = p; @@ -6661,7 +6733,7 @@ set_nonincremental_init (void) return; FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value) - add_pending_init (index, value, false); + add_pending_init (index, value, NULL_TREE, false); constructor_elements = 0; if (TREE_CODE (constructor_type) == RECORD_TYPE) { @@ -6751,7 +6823,7 @@ set_nonincremental_init_from_string (tree str) } value = build_int_cst_wide (type, val[1], val[0]); - add_pending_init (purpose, value, false); + add_pending_init (purpose, value, NULL_TREE, false); } constructor_incremental = 0; @@ -6816,6 +6888,7 @@ find_init_member (tree field) /* "Output" the next constructor element. At top level, really output it to assembler code now. Otherwise, collect it in a list from which we will make a CONSTRUCTOR. + If ORIGTYPE is not NULL_TREE, it is the original type of VALUE. TYPE is the data type that the containing data type wants here. FIELD is the field (a FIELD_DECL) or the index that this element fills. If VALUE is a string constant, STRICT_STRING is true if it is @@ -6832,8 +6905,8 @@ find_init_member (tree field) existing initializer. */ static void -output_init_element (tree value, bool strict_string, tree type, tree field, - int pending, bool implicit) +output_init_element (tree value, tree origtype, bool strict_string, tree type, + tree field, int pending, bool implicit) { tree semantic_type = NULL_TREE; constructor_elt *celt; @@ -6914,7 +6987,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field, if (semantic_type) value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value); - value = digest_init (type, value, npc, strict_string, + value = digest_init (type, value, origtype, npc, strict_string, require_constant_value); if (value == error_mark_node) { @@ -6934,7 +7007,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field, && tree_int_cst_lt (field, constructor_unfilled_index)) set_nonincremental_init (); - add_pending_init (field, value, implicit); + add_pending_init (field, value, origtype, implicit); return; } else if (TREE_CODE (constructor_type) == RECORD_TYPE @@ -6960,7 +7033,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field, } } - add_pending_init (field, value, implicit); + add_pending_init (field, value, origtype, implicit); return; } else if (TREE_CODE (constructor_type) == UNION_TYPE @@ -7043,7 +7116,7 @@ output_pending_init_elements (int all) { if (tree_int_cst_equal (elt->purpose, constructor_unfilled_index)) - output_init_element (elt->value, true, + output_init_element (elt->value, elt->origtype, true, TREE_TYPE (constructor_type), constructor_unfilled_index, 0, false); else if (tree_int_cst_lt (constructor_unfilled_index, @@ -7097,7 +7170,8 @@ output_pending_init_elements (int all) if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos)) { constructor_unfilled_fields = elt->purpose; - output_init_element (elt->value, true, TREE_TYPE (elt->purpose), + output_init_element (elt->value, elt->origtype, true, + TREE_TYPE (elt->purpose), elt->purpose, 0, false); } else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos)) @@ -7292,8 +7366,9 @@ process_init_element (struct c_expr value, bool implicit) if (value.value) { push_member_name (constructor_fields); - output_init_element (value.value, strict_string, - fieldtype, constructor_fields, 1, implicit); + output_init_element (value.value, value.original_type, + strict_string, fieldtype, + constructor_fields, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -7382,8 +7457,9 @@ process_init_element (struct c_expr value, bool implicit) if (value.value) { push_member_name (constructor_fields); - output_init_element (value.value, strict_string, - fieldtype, constructor_fields, 1, implicit); + output_init_element (value.value, value.original_type, + strict_string, fieldtype, + constructor_fields, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } else @@ -7432,8 +7508,9 @@ process_init_element (struct c_expr value, bool implicit) if (value.value) { push_array_bounds (tree_low_cst (constructor_index, 1)); - output_init_element (value.value, strict_string, - elttype, constructor_index, 1, implicit); + output_init_element (value.value, value.original_type, + strict_string, elttype, + constructor_index, 1, implicit); RESTORE_SPELLING_DEPTH (constructor_depth); } @@ -7461,8 +7538,9 @@ process_init_element (struct c_expr value, bool implicit) /* Now output the actual element. */ if (value.value) - output_init_element (value.value, strict_string, - elttype, constructor_index, 1, implicit); + output_init_element (value.value, value.original_type, + strict_string, elttype, + constructor_index, 1, implicit); constructor_index = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node); @@ -7486,8 +7564,9 @@ process_init_element (struct c_expr value, bool implicit) else { if (value.value) - output_init_element (value.value, strict_string, - constructor_type, NULL_TREE, 1, implicit); + output_init_element (value.value, value.original_type, + strict_string, constructor_type, + NULL_TREE, 1, implicit); constructor_fields = 0; } @@ -7718,10 +7797,11 @@ c_finish_goto_ptr (tree expr) } /* Generate a C `return' statement. RETVAL is the expression for what - to return, or a null pointer for `return;' with no value. */ + to return, or a null pointer for `return;' with no value. If + ORIGTYPE is not NULL_TREE, it is the original type of RETVAL. */ tree -c_finish_return (tree retval) +c_finish_return (tree retval, tree origtype) { tree valtype = TREE_TYPE (TREE_TYPE (current_function_decl)), ret_stmt; bool no_warning = false; @@ -7768,8 +7848,8 @@ c_finish_return (tree retval) } else { - tree t = convert_for_assignment (valtype, retval, ic_return, npc, - NULL_TREE, NULL_TREE, 0); + tree t = convert_for_assignment (valtype, retval, origtype, ic_return, + npc, NULL_TREE, NULL_TREE, 0); tree res = DECL_RESULT (current_function_decl); tree inner; -- cgit v1.2.1