* [C++ Patch] PR 53567 @ 2012-06-04 14:17 Paolo Carlini 2012-06-04 18:12 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-04 14:17 UTC (permalink / raw) To: gcc-patches; +Cc: Jason Merrill [-- Attachment #1: Type: text/plain, Size: 942 bytes --] Hi, in this "error reporting routines re-entered" ICE we try to emit a warning from ocp_convert while we are already producing an error message (we get to ocp_convert via the usual tsubst (tf_none) called by dump_template_bindings). I considered whether we could avoid the specific problem by passing different FLAGS to ocp_convert when build_static_cast_1 is called with tf_none, but I think it would be tricky and error-prone, because ocp_convert has a mix of errors, warnings, errors not protected by flags & LOOKUP_COMPLAIN. Anyway, when I tried the usual tsubst_flags_t route, I saw a large patch but also quite a few loose ends solved (which I noticed other times), convert_to_reference isn't special anymore in having to "synthesize" a complain, all in all very few explicit tf_warning_or_error remain, and in safe places, as far as I can see. Bootstrapped and tested x86_64-linux. Thanks, Paolo. ///////////////////// [-- Attachment #2: CL_53567 --] [-- Type: text/plain, Size: 1437 bytes --] /cp 2012-06-04 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * typeck.c (cp_perform_integral_promotions): New, like perform_integral_promotions but also takes a tsubst_flags_t parameter. (pointer_diff): Add tsubst_flags_t parameter. (decay_conversion, cp_default_conversion, cp_build_array_ref, cp_build_binary_op, cp_build_unary_op, build_static_cast_1, build_reinterpret_cast_1, cp_build_modify_expr, convert_for_assignment): Adjust. * init.c (expand_virtual_init, expand_default_init, build_new, build_vec_delete_1, build_vec_init, build_delete): Adjust. * class.c (build_base_path): Likewise. * decl.c (compute_array_index_type): Likewise. * rtti.c (ifnonnull): Add tsubst_flags_t parameter. (build_typeid, build_dynamic_cast_1): Adjust. * except.c (initialize_handler_parm): Likewise. * typeck2.c (process_init_constructor_record): Likewise. * semantics.c (finish_goto_stmt, handle_omp_for_class_iterator, finish_static_assert): Likewise. * call.c (build_op_delete_call, convert_like_real, convert_arg_to_ellipsis, convert_for_arg_passing): Likewise. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference, convert_to_reference, cp_convert, cp_convert_and_check, ocp_convert, convert_force): Add tsubst_flags_t parameter. * cp-tree.h: Adjust prototypes. /testsuite 2012-06-04 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * g++.dg/cpp0x/alias-decl-19.C: New. [-- Attachment #3: patch_53567_5 --] [-- Type: text/plain, Size: 46830 bytes --] Index: testsuite/g++.dg/cpp0x/alias-decl-19.C =================================================================== --- testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) +++ testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) @@ -0,0 +1,31 @@ +// PR c++/53567 +// { dg-do compile { target c++11 } } + +template <unsigned int, bool> struct IntegerType { typedef unsigned type; }; + +template <class EnumT> +using UnderlyingEnumType = typename IntegerType<sizeof(EnumT), (EnumT(-1) > EnumT(0))>::type; + +template <class EnumT, class UnderlyingT = UnderlyingEnumType<EnumT>> +struct EnumMask +{ + constexpr EnumMask(EnumT val) : m_val(val) {} + operator EnumT() { return m_val; } + + EnumT m_val; +}; + +enum class A : unsigned { x }; + +template <class EnumT> +EnumMask<EnumT> operator ~(EnumT lhs) +{ + return EnumT(~unsigned(lhs) & unsigned(EnumT::maskAll)); // { dg-error "not a member" } + +} + +int main() +{ + ~A::x; + return 0; +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 188167) +++ cp/typeck.c (working copy) @@ -53,7 +53,7 @@ static tree rationalize_conditional_expr (enum tre static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (const_tree, const_tree, bool); -static tree pointer_diff (tree, tree, tree); +static tree pointer_diff (tree, tree, tree, tsubst_flags_t); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); @@ -1907,7 +1907,7 @@ decay_conversion (tree exp, tsubst_flags_t complai /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = cp_build_addr_expr (exp, complain); - return cp_convert (ptrtype, adr); + return cp_convert (ptrtype, adr, complain); } /* If a bitfield is used in a context where integral promotion @@ -1951,12 +1951,12 @@ cp_default_conversion (tree exp, tsubst_flags_t co /* Check for target-specific promotions. */ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); if (promoted_type) - exp = cp_convert (promoted_type, exp); + exp = cp_convert (promoted_type, exp, complain); /* Perform the integral promotions first so that bitfield expressions (which may promote to "int", even if the bitfield is declared "unsigned") are promoted correctly. */ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); + exp = cp_perform_integral_promotions (exp, complain); /* Perform the other conversions. */ exp = decay_conversion (exp, complain); @@ -1976,7 +1976,7 @@ default_conversion (tree exp) converted value. */ tree -perform_integral_promotions (tree expr) +cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) { tree type; tree promoted_type; @@ -1996,10 +1996,18 @@ tree return expr; promoted_type = type_promotes_to (type); if (type != promoted_type) - expr = cp_convert (promoted_type, expr); + expr = cp_convert (promoted_type, expr, complain); return expr; } +/* C version. */ + +tree +perform_integral_promotions (tree expr) +{ + return cp_perform_integral_promotions (expr, tf_warning_or_error); +} + /* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */ @@ -2946,7 +2954,7 @@ cp_build_array_ref (location_t loc, tree array, tr does not say that we should. In fact, the natural thing would seem to be to convert IDX to ptrdiff_t; we're performing pointer arithmetic.) */ - idx = perform_integral_promotions (idx); + idx = cp_perform_integral_promotions (idx, complain); /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -3868,7 +3876,8 @@ cp_build_binary_op (location_t location, if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) - return pointer_diff (op0, op1, common_pointer_type (type0, type1)); + return pointer_diff (op0, op1, common_pointer_type (type0, type1), + complain); /* In all other cases except pointer - int, the usual arithmetic rules apply. */ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) @@ -4004,7 +4013,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4032,7 +4041,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4063,7 +4072,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); } break; @@ -4163,12 +4172,12 @@ cp_build_binary_op (location_t location, op0 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e1, e2, complain); - op1 = cp_convert (TREE_TYPE (op0), integer_one_node); + op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); } else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), op1); + op1 = cp_convert (TREE_TYPE (op0), op1, complain); } result_type = TREE_TYPE (op0); } @@ -4191,9 +4200,9 @@ cp_build_binary_op (location_t location, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) - op0 = cp_convert_and_check (type, op0); + op0 = cp_convert_and_check (type, op0, complain); if (!same_type_p (TREE_TYPE (op1), type)) - op1 = cp_convert_and_check (type, op1); + op1 = cp_convert_and_check (type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4457,16 +4466,16 @@ cp_build_binary_op (location_t location, if (first_complex) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != real_type) - op1 = cp_convert_and_check (real_type, op1); + op1 = cp_convert_and_check (real_type, op1, complain); } else { if (TREE_TYPE (op0) != real_type) - op0 = cp_convert_and_check (real_type, op0); + op0 = cp_convert_and_check (real_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); } if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) return error_mark_node; @@ -4551,7 +4560,7 @@ cp_build_binary_op (location_t location, tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return cp_convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val, complain); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -4581,9 +4590,9 @@ cp_build_binary_op (location_t location, if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4595,7 +4604,7 @@ cp_build_binary_op (location_t location, result = build2 (resultcode, build_type, op0, op1); result = fold_if_not_in_template (result); if (final_type != 0) - result = cp_convert (final_type, result); + result = cp_convert (final_type, result, complain); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (op0) @@ -4628,7 +4637,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tre The resulting tree has type int. */ static tree -pointer_diff (tree op0, tree op1, tree ptrtype) +pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) { tree result; tree restype = ptrdiff_type_node; @@ -4638,24 +4647,48 @@ static tree return error_mark_node; if (TREE_CODE (target_type) == VOID_TYPE) - permerror (input_location, "ISO C++ forbids using pointer of type %<void *%> in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer of " + "type %<void *%> in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == FUNCTION_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a function in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a function in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == METHOD_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a method in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a method in subtraction"); + else + return error_mark_node; + } /* First do the subtraction as integers; then drop through to build the divide operator. */ op0 = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (restype, op0), - cp_convert (restype, op1), - tf_warning_or_error); + cp_convert (restype, op0, complain), + cp_convert (restype, op1, complain), + complain); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) - error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); + { + if (complain & tf_error) + error ("invalid use of a pointer to an incomplete type in " + "pointer arithmetic"); + else + return error_mark_node; + } op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) @@ -4663,7 +4696,8 @@ static tree /* Do the division. */ - result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); + result = build2 (EXACT_DIV_EXPR, restype, op0, + cp_convert (restype, op1, complain)); return fold_if_not_in_template (result); } \f @@ -5176,7 +5210,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else { if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus expression is always a rvalue. */ @@ -5201,7 +5235,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); break; case ABS_EXPR: @@ -5359,7 +5393,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else inc = integer_one_node; - inc = cp_convert (argtype, inc); + inc = cp_convert (argtype, inc, complain); /* If 'arg' is an Objective-C PROPERTY_REF expression, then we need to ask Objective-C to build the increment or decrement @@ -6075,7 +6109,7 @@ build_static_cast_1 (tree type, tree expr, bool c_ || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -6418,7 +6452,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo return error_mark_node; } - return cp_convert (type, expr); + return cp_convert (type, expr, complain); } tree @@ -7079,7 +7113,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) - newrhs = cp_convert_and_check (lhstype, newrhs); + newrhs = cp_convert_and_check (lhstype, newrhs, complain); if (modifycode != INIT_EXPR) { @@ -7600,7 +7634,7 @@ convert_for_assignment (tree type, tree rhs, if (!warn_pmf2ptr && TYPE_PTR_P (type) && TYPE_PTRMEMFUNC_P (rhstype)) - rhs = cp_convert (strip_top_quals (type), rhs); + rhs = cp_convert (strip_top_quals (type), rhs, complain); else { if (complain & tf_error) Index: cp/init.c =================================================================== --- cp/init.c (revision 188167) +++ cp/init.c (working copy) @@ -1180,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1598,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tr have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -2815,7 +2816,7 @@ build_new (VEC(tree,gc) **placement, tree type, tr return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -3012,12 +3013,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -3189,14 +3190,14 @@ build_vec_init (tree base, tree maxindex, tree ini return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); base = decay_conversion (base, complain); if (base == error_mark_node) return error_mark_node; - base = cp_convert (ptype, base); + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3665,7 +3666,7 @@ build_delete (tree type, tree addr, special_functi addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3691,7 +3692,7 @@ build_delete (tree type, tree addr, special_functi if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); Index: cp/class.c =================================================================== --- cp/class.c (revision 188167) +++ cp/class.c (working copy) @@ -366,7 +366,7 @@ build_base_path (enum tree_code code, /* Now that we've saved expr, build the real null test. */ if (null_test) { - tree zero = cp_convert (TREE_TYPE (expr), nullptr_node); + tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, expr, zero); } Index: cp/decl.c =================================================================== --- cp/decl.c (revision 188167) +++ cp/decl.c (working copy) @@ -8104,9 +8104,10 @@ compute_array_index_type (tree name, tree size, ts processing_template_decl = 0; itype = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node), - tf_warning_or_error); + cp_convert (ssizetype, size, complain), + cp_convert (ssizetype, integer_one_node, + complain), + complain); itype = fold (itype); processing_template_decl = saved_processing_template_decl; Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 188167) +++ cp/rtti.c (working copy) @@ -99,7 +99,7 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree ifnonnull (tree, tree); +static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); @@ -336,7 +336,8 @@ build_typeid (tree exp) This is an lvalue use of expr then. */ exp = mark_lvalue_use (exp); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), + tf_warning_or_error); } exp = get_tinfo_decl_dynamic (exp); @@ -498,12 +499,13 @@ get_typeid (tree type) RESULT, it must have previously had a save_expr applied to it. */ static tree -ifnonnull (tree test, tree result) +ifnonnull (tree test, tree result, tsubst_flags_t complain) { return build3 (COND_EXPR, TREE_TYPE (result), build2 (EQ_EXPR, boolean_type_node, test, - cp_convert (TREE_TYPE (test), nullptr_node)), - cp_convert (TREE_TYPE (result), nullptr_node), + cp_convert (TREE_TYPE (test), nullptr_node, + complain)), + cp_convert (TREE_TYPE (result), nullptr_node, complain), result); } @@ -596,7 +598,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst /* Apply trivial conversion T -> T& for dereferenced ptrs. */ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, complain); } /* The dynamic_cast operator shall not cast away constness. */ @@ -644,7 +646,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst expr1 = build_headof (expr); if (TREE_TYPE (expr1) != type) expr1 = build1 (NOP_EXPR, type, expr1); - return ifnonnull (expr, expr1); + return ifnonnull (expr, expr1, complain); } else { @@ -752,12 +754,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst neq = cp_truthvalue_conversion (result); return cp_convert (type, build3 (COND_EXPR, TREE_TYPE (result), - neq, result, bad)); + neq, result, bad), complain); } /* Now back to the type we want from a void*. */ - result = cp_convert (type, result); - return ifnonnull (expr, result); + result = cp_convert (type, result, complain); + return ifnonnull (expr, result, complain); } } else Index: cp/except.c =================================================================== --- cp/except.c (revision 188167) +++ cp/except.c (working copy) @@ -424,7 +424,8 @@ initialize_handler_parm (tree decl, tree exp) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); - exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); init = convert_from_reference (exp); @@ -435,7 +436,8 @@ initialize_handler_parm (tree decl, tree exp) /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 188167) +++ cp/typeck2.c (working copy) @@ -1265,7 +1265,7 @@ process_init_constructor_record (tree type, tree i /* If this is a bitfield, now convert to the lowered type. */ if (type != TREE_TYPE (field)) - next = cp_convert_and_check (TREE_TYPE (field), next); + next = cp_convert_and_check (TREE_TYPE (field), next, complain); flags |= picflag_from_initializer (next); CONSTRUCTOR_APPEND_ELT (v, field, next); } Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 188167) +++ cp/semantics.c (working copy) @@ -565,7 +565,8 @@ finish_goto_stmt (tree destination) destination = mark_rvalue_use (destination); if (!processing_template_decl) { - destination = cp_convert (ptr_type_node, destination); + destination = cp_convert (ptr_type_node, destination, + tf_warning_or_error); if (error_operand_p (destination)) return NULL_TREE; } @@ -4527,7 +4528,8 @@ handle_omp_for_class_iterator (int i, location_t l if (error_operand_p (iter_incr)) return true; incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, + tf_warning_or_error); if (TREE_CODE (rhs) == MINUS_EXPR) { incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); @@ -4582,7 +4584,7 @@ handle_omp_for_class_iterator (int i, location_t l return true; } - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == iter) @@ -5131,7 +5133,7 @@ finish_static_assert (tree condition, tree message /* Fold the expression and convert it to a boolean value. */ condition = fold_non_dependent_expr (condition); - condition = cp_convert (boolean_type_node, condition); + condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) Index: cp/call.c =================================================================== --- cp/call.c (revision 188167) +++ cp/call.c (working copy) @@ -5413,7 +5413,7 @@ build_op_delete_call (enum tree_code code, tree ad fns = lookup_name_nonclass (fnname); /* Strip const and volatile from addr. */ - addr = cp_convert (ptr_type_node, addr); + addr = cp_convert (ptr_type_node, addr, tf_warning_or_error); if (placement) { @@ -5685,9 +5685,10 @@ convert_like_real (conversion *convs, tree expr, t complain); if (convs->kind == ck_ref_bind) return convert_to_reference (totype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, + complain); else - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } else if (t->kind == ck_user || !t->bad_p) { @@ -5712,7 +5713,7 @@ convert_like_real (conversion *convs, tree expr, t permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } if (issue_conversion_warnings && (complain & tf_warning)) @@ -5851,7 +5852,7 @@ convert_like_real (conversion *convs, tree expr, t /* Take the address explicitly rather than via decay_conversion to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); - array = cp_convert (build_pointer_type (elttype), array); + array = cp_convert (build_pointer_type (elttype), array, complain); /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6017,7 +6018,7 @@ convert_like_real (conversion *convs, tree expr, t reference. This will adjust the pointer if a derived to base conversion is being performed. */ expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), - expr); + expr, complain); /* Convert the pointer to the desired reference type. */ return build_nop (ref_type, expr); } @@ -6099,9 +6100,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t if (complain & tf_warning) warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " "integral type in a future version of GCC", arg_type); - arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg); + arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); } - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); } arg = require_complete_type (arg); @@ -6336,7 +6337,7 @@ convert_for_arg_passing (tree type, tree val, tsub && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - val = perform_integral_promotions (val); + val = cp_perform_integral_promotions (val, complain); if ((complain & tf_warning) && warn_suggest_attribute_format) { Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 188167) +++ cp/cvt.c (working copy) @@ -38,10 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree); -static tree convert_to_pointer_force (tree, tree); +static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); +static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); -static tree build_up_reference (tree, tree, int, tree); +static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); static void warn_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- @@ -74,7 +74,7 @@ static void warn_ref_binding (location_t, tree, tr else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr) +cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -89,15 +89,17 @@ static tree intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { - error_at (loc, "can%'t convert from incomplete type %qT to %qT", - intype, type); + if (complain & tf_error) + error_at (loc, "can%'t convert from incomplete type %qT to %qT", + intype, type); return error_mark_node; } rval = build_type_conversion (type, expr); if (rval) { - if (rval == error_mark_node) + if ((complain & tf_error) + && rval == error_mark_node) error_at (loc, "conversion of %qE from %qT to %qT is ambiguous", expr, intype, type); return rval; @@ -111,7 +113,7 @@ static tree { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) - return convert_member_func_to_ptr (type, expr, tf_warning_or_error); + return convert_member_func_to_ptr (type, expr, complain); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); @@ -159,8 +161,7 @@ static tree if (binfo || same_p) { if (binfo) - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); /* Add any qualifier conversions. */ return build_nop (type, expr); } @@ -168,8 +169,9 @@ static tree if (TYPE_PTRMEMFUNC_P (type)) { - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -178,20 +180,20 @@ static tree else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) - return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr)); + return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), + complain); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); return get_member_function_from_ptrfunc (&object, TREE_OPERAND (expr, 1), - tf_warning_or_error); + complain); } } error_at (loc, "cannot convert %qE from type %qT to type %qT", @@ -201,14 +203,15 @@ static tree if (null_ptr_cst_p (expr)) { - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !NULLPTR_TYPE_P (TREE_TYPE (expr))) warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); if (TYPE_PTRDATAMEM_P (type)) { @@ -223,7 +226,8 @@ static tree } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { - error_at (loc, "invalid conversion from %qT to %qT", intype, type); + if (complain & tf_error) + error_at (loc, "invalid conversion from %qT to %qT", intype, type); return error_mark_node; } @@ -231,7 +235,8 @@ static tree { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width as a pointer. */ @@ -242,10 +247,11 @@ static tree } if (type_unknown_p (expr)) - return instantiate_type (type, expr, tf_warning_or_error); + return instantiate_type (type, expr, complain); - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -254,7 +260,7 @@ static tree (such as conversion from sub-type to private super-type). */ static tree -convert_to_pointer_force (tree type, tree expr) +convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); @@ -284,8 +290,7 @@ static tree return error_mark_node; if (binfo) { - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); if (expr == error_mark_node) return error_mark_node; /* Add any qualifier conversions. */ @@ -297,7 +302,7 @@ static tree } } - return cp_convert_to_pointer (type, expr); + return cp_convert_to_pointer (type, expr, complain); } /* We are passing something to a function which requires a reference. @@ -309,7 +314,8 @@ static tree If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (tree type, tree arg, int flags, tree decl) +build_up_reference (tree type, tree arg, int flags, tree decl, + tsubst_flags_t complain) { tree rval; tree argtype = TREE_TYPE (arg); @@ -351,12 +357,12 @@ static tree return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - rval = build_base_path (PLUS_EXPR, rval, binfo, 1, - tf_warning_or_error); + rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain); } else rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); + = convert_to_pointer_force (build_pointer_type (target_type), + rval, complain); return build_nop (type, rval); } @@ -403,15 +409,13 @@ warn_ref_binding (location_t loc, tree reftype, tr tree convert_to_reference (tree reftype, tree expr, int convtype, - int flags, tree decl) + int flags, tree decl, tsubst_flags_t complain) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN) - ? tf_warning_or_error : tf_none); location_t loc = EXPR_LOC_OR_HERE (expr); if (TREE_CODE (type) == FUNCTION_TYPE @@ -457,7 +461,8 @@ convert_to_reference (tree reftype, tree expr, int tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); - if (! real_lvalue_p (expr)) + if ((complain & tf_warning) + && ! real_lvalue_p (expr)) warn_ref_binding (loc, reftype, intype, decl); if (! (convtype & CONV_CONST) @@ -466,7 +471,7 @@ convert_to_reference (tree reftype, tree expr, int ttr, reftype); } - return build_up_reference (reftype, expr, flags, decl); + return build_up_reference (reftype, expr, flags, decl, complain); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -477,16 +482,17 @@ convert_to_reference (tree reftype, tree expr, int /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (TREE_CODE (intype) == POINTER_TYPE + if ((complain & tf_warning) + && TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = cp_build_addr_expr (expr, tf_warning_or_error); + rval = cp_build_addr_expr (expr, complain); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), - rval, 0); + rval, 0, complain); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } @@ -494,11 +500,12 @@ convert_to_reference (tree reftype, tree expr, int { rval = convert_for_initialization (NULL_TREE, type, expr, flags, ICR_CONVERTING, 0, 0, - tf_warning_or_error); + complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - warn_ref_binding (loc, reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags, decl); + if (complain & tf_warning) + warn_ref_binding (loc, reftype, intype, decl); + rval = build_up_reference (reftype, rval, flags, decl, complain); } if (rval) @@ -595,9 +602,9 @@ cp_fold_convert (tree type, tree expr) /* C++ conversions, preference to static cast conversions. */ tree -cp_convert (tree type, tree expr) +cp_convert (tree type, tree expr, tsubst_flags_t complain) { - return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain); } /* C++ equivalent of convert_and_check but using cp_convert as the @@ -608,16 +615,17 @@ tree i.e. because of language rules and not because of an explicit cast. */ tree -cp_convert_and_check (tree type, tree expr) +cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree result; if (TREE_TYPE (expr) == type) return expr; - result = cp_convert (type, expr); + result = cp_convert (type, expr, complain); - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !TREE_OVERFLOW_P (expr) && result != error_mark_node) warnings_for_convert_and_check (type, expr, result); @@ -630,7 +638,8 @@ tree FLAGS indicates how we should behave. */ tree -ocp_convert (tree type, tree expr, int convtype, int flags) +ocp_convert (tree type, tree expr, int convtype, int flags, + tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -647,7 +656,8 @@ tree if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { - error (invalid_conv_diag); + if (complain & tf_error) + error (invalid_conv_diag); return error_mark_node; } @@ -696,7 +706,7 @@ tree if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, ICV_CAST, tf_warning_or_error); + e = convert_to_void (e, ICV_CAST, complain); return e; } @@ -714,9 +724,15 @@ tree && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { - if (flags & LOOKUP_COMPLAIN) - permerror (loc, "conversion from %q#T to %q#T", intype, type); - if (!flag_permissive) + if (complain & tf_error) + { + if (flags & LOOKUP_COMPLAIN) + permerror (loc, "conversion from %q#T to %q#T", + intype, type); + if (!flag_permissive) + return error_mark_node; + } + else return error_mark_node; } @@ -727,7 +743,8 @@ tree the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ - if (TREE_CODE (expr) == INTEGER_CST + if ((complain & tf_warning) + && TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " @@ -740,7 +757,8 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - if (flags & LOOKUP_COMPLAIN) + if ((complain & tf_error) + && (flags & LOOKUP_COMPLAIN)) error_at (loc, "%q#T used where a %qT was expected", intype, type); return error_mark_node; } @@ -748,8 +766,10 @@ tree { if (TREE_CODE (intype) == VOID_TYPE) { - error_at (loc, "could not convert %qE from %<void%> to %<bool%>", - expr); + if (complain & tf_error) + error_at (loc, + "could not convert %qE from %<void%> to %<bool%>", + expr); return error_mark_node; } @@ -768,7 +788,7 @@ tree if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); @@ -778,8 +798,10 @@ tree ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a %qT was expected", in_vtype, type); + if ((complain & tf_error) + && (flags & LOOKUP_COMPLAIN)) + error_at (loc, "%q#T used where a %qT was expected", + in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); @@ -793,8 +815,10 @@ tree if (rval) return rval; else - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a floating point value was expected", + if ((complain & tf_error) + && (flags & LOOKUP_COMPLAIN)) + error_at (loc, + "%q#T used where a floating point value was expected", TREE_TYPE (e)); } if (code == REAL_TYPE) @@ -826,35 +850,33 @@ tree return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) - ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + ctor = perform_implicit_conversion (type, ctor, complain); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ - ctor = build_user_type_conversion (type, ctor, flags, - tf_warning_or_error); + ctor = build_user_type_conversion (type, ctor, flags, complain); else { VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, &ctor_vec, - type, flags, - tf_warning_or_error); + type, flags, complain); release_tree_vector (ctor_vec); } if (ctor) - return build_cplus_new (type, ctor, tf_warning_or_error); + return build_cplus_new (type, ctor, complain); } if (flags & LOOKUP_COMPLAIN) { /* If the conversion failed and expr was an invalid use of pointer to member function, try to report a meaningful error. */ - if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (expr, complain)) /* We displayed the error message. */; - else + else if (complain & tf_error) error_at (loc, "conversion from %qT to non-scalar type %qT requested", TREE_TYPE (expr), type); } @@ -1416,7 +1438,8 @@ convert (tree type, tree expr) return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + tf_warning_or_error); } /* Like cp_convert, except permit conversions to take place which @@ -1424,7 +1447,7 @@ convert (tree type, tree expr) (such as conversion from sub-type to private super-type). */ tree -convert_force (tree type, tree expr, int convtype) +convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -1432,10 +1455,11 @@ tree if (code == REFERENCE_TYPE) return (fold_if_not_in_template (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, - NULL_TREE))); + NULL_TREE, complain))); if (code == POINTER_TYPE) - return fold_if_not_in_template (convert_to_pointer_force (type, e)); + return fold_if_not_in_template (convert_to_pointer_force (type, e, + complain)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR @@ -1446,9 +1470,9 @@ tree && TYPE_PTRMEMFUNC_P (type)) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, - /*c_cast_p=*/1, tf_warning_or_error); + /*c_cast_p=*/1, complain); - return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain); } /* Convert an aggregate EXPR to type XTYPE. If a conversion Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 188167) +++ cp/cp-tree.h (working copy) @@ -5001,16 +5001,19 @@ extern void adjust_clone_args (tree); extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ -extern tree convert_to_reference (tree, tree, int, int, tree); +extern tree convert_to_reference (tree, tree, int, int, tree, + tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); -extern tree ocp_convert (tree, tree, int, int); -extern tree cp_convert (tree, tree); -extern tree cp_convert_and_check (tree, tree); +extern tree ocp_convert (tree, tree, int, int, + tsubst_flags_t); +extern tree cp_convert (tree, tree, tsubst_flags_t); +extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, impl_conv_void, tsubst_flags_t); -extern tree convert_force (tree, tree, int); +extern tree convert_force (tree, tree, int, + tsubst_flags_t); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); extern tree perform_qualification_conversions (tree, tree); @@ -5899,6 +5902,7 @@ extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); +extern tree cp_perform_integral_promotions (tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-04 14:17 [C++ Patch] PR 53567 Paolo Carlini @ 2012-06-04 18:12 ` Jason Merrill 2012-06-04 22:57 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-04 18:12 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/04/2012 10:15 AM, Paolo Carlini wrote: > @@ -5413,7 +5413,7 @@ build_op_delete_call (enum tree_code code, tree ad > fns = lookup_name_nonclass (fnname); > > /* Strip const and volatile from addr. */ > - addr = cp_convert (ptr_type_node, addr); > + addr = cp_convert (ptr_type_node, addr, tf_warning_or_error); build_op_delete_call is called from build_new_1, so it should be complainified. > + if (complain & tf_error) > + { > + if (flags & LOOKUP_COMPLAIN) > + permerror (loc, "conversion from %q#T to %q#T", > + intype, type); > + if (!flag_permissive) > + return error_mark_node; > + } > + else > return error_mark_node; I don't think we want to check both tf_error and LOOKUP_COMPLAIN everywhere. We could use one to set the other, but at this point I think we want to do away with LOOKUP_COMPLAIN entirely as its function has been taken over. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-04 18:12 ` Jason Merrill @ 2012-06-04 22:57 ` Paolo Carlini 2012-06-04 23:23 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-04 22:57 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 2152 bytes --] Hi, On 06/04/2012 08:12 PM, Jason Merrill wrote: > On 06/04/2012 10:15 AM, Paolo Carlini wrote: >> @@ -5413,7 +5413,7 @@ build_op_delete_call (enum tree_code code, tree ad >> fns = lookup_name_nonclass (fnname); >> >> /* Strip const and volatile from addr. */ >> - addr = cp_convert (ptr_type_node, addr); >> + addr = cp_convert (ptr_type_node, addr, tf_warning_or_error); > > build_op_delete_call is called from build_new_1, so it should be > complainified. Ok. >> + if (complain & tf_error) >> + { >> + if (flags & LOOKUP_COMPLAIN) >> + permerror (loc, "conversion from %q#T to %q#T", >> + intype, type); >> + if (!flag_permissive) >> + return error_mark_node; >> + } >> + else >> return error_mark_node; > > I don't think we want to check both tf_error and LOOKUP_COMPLAIN > everywhere. We could use one to set the other, but at this point I > think we want to do away with LOOKUP_COMPLAIN entirely as its function > has been taken over. Well, if you mean not using it in the functions we are touching, something like the below passes the testsuite, for example. If, more generally, you mean we should remove it completely, I'm afraid some cases are rather nasty. For example, I think that whenever we go through implicit_conversion, thus its flags &=, the following function calls can easily have at the same time complain & tf_error true and flags & LOOKUP_COMPLAIN false. Thus, just as an example, the lines in build_user_type_conversion_1 if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) { error ("conversion from %qT to %qT is ambiguous", fromtype, totype); print_z_candidates (location_of (expr), candidates); } cannot simply discard the information in flags, that would not work for g++.dg/overload/ref-conv2.C. More generally, it looks like there are a few such cases in call.c, where we are checking both. Is there a conceptually simple recipe to simplify such tests? Or handle such cleanup separately from this bug... ;) Thanks, Paolo. ///////////////////// [-- Attachment #2: CL_53567_6 --] [-- Type: text/plain, Size: 1546 bytes --] /cp 2012-06-04 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * typeck.c (cp_perform_integral_promotions): New, like perform_integral_promotions but also takes a tsubst_flags_t parameter. (pointer_diff): Add tsubst_flags_t parameter. (decay_conversion, cp_default_conversion, cp_build_array_ref, cp_build_binary_op, cp_build_unary_op, build_static_cast_1, build_reinterpret_cast_1, cp_build_modify_expr, convert_for_assignment): Adjust. * optimize.c (build_delete_destructor_body): Adjust. * init.c (expand_virtual_init, expand_default_init, build_new, build_vec_delete_1, build_vec_init, build_delete): Adjust. * class.c (build_base_path): Likewise. * decl.c (compute_array_index_type, finish_destructor_body): Likewise. * rtti.c (ifnonnull): Add tsubst_flags_t parameter. (build_typeid, build_dynamic_cast_1): Adjust. * except.c (initialize_handler_parm): Likewise. * typeck2.c (process_init_constructor_record): Likewise. * semantics.c (finish_goto_stmt, handle_omp_for_class_iterator, finish_static_assert): Likewise. * call.c (build_op_delete_call): Add tsubst_flags_t parameter. (convert_like_real, convert_arg_to_ellipsis, convert_for_arg_passing): Adjust. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference, convert_to_reference, cp_convert, cp_convert_and_check, ocp_convert, convert_force): Add tsubst_flags_t parameter. * cp-tree.h: Adjust prototypes. /testsuite 2012-06-04 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * g++.dg/cpp0x/alias-decl-19.C: New. [-- Attachment #3: patch_53567_6 --] [-- Type: text/plain, Size: 52050 bytes --] Index: testsuite/g++.dg/cpp0x/alias-decl-19.C =================================================================== --- testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) +++ testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) @@ -0,0 +1,31 @@ +// PR c++/53567 +// { dg-do compile { target c++11 } } + +template <unsigned int, bool> struct IntegerType { typedef unsigned type; }; + +template <class EnumT> +using UnderlyingEnumType = typename IntegerType<sizeof(EnumT), (EnumT(-1) > EnumT(0))>::type; + +template <class EnumT, class UnderlyingT = UnderlyingEnumType<EnumT>> +struct EnumMask +{ + constexpr EnumMask(EnumT val) : m_val(val) {} + operator EnumT() { return m_val; } + + EnumT m_val; +}; + +enum class A : unsigned { x }; + +template <class EnumT> +EnumMask<EnumT> operator ~(EnumT lhs) +{ + return EnumT(~unsigned(lhs) & unsigned(EnumT::maskAll)); // { dg-error "not a member" } + +} + +int main() +{ + ~A::x; + return 0; +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 188203) +++ cp/typeck.c (working copy) @@ -52,7 +52,7 @@ static tree rationalize_conditional_expr (enum tre static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (const_tree, const_tree, bool); -static tree pointer_diff (tree, tree, tree); +static tree pointer_diff (tree, tree, tree, tsubst_flags_t); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); @@ -1906,7 +1906,7 @@ decay_conversion (tree exp, tsubst_flags_t complai /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = cp_build_addr_expr (exp, complain); - return cp_convert (ptrtype, adr); + return cp_convert (ptrtype, adr, complain); } /* If a bitfield is used in a context where integral promotion @@ -1950,12 +1950,12 @@ cp_default_conversion (tree exp, tsubst_flags_t co /* Check for target-specific promotions. */ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); if (promoted_type) - exp = cp_convert (promoted_type, exp); + exp = cp_convert (promoted_type, exp, complain); /* Perform the integral promotions first so that bitfield expressions (which may promote to "int", even if the bitfield is declared "unsigned") are promoted correctly. */ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); + exp = cp_perform_integral_promotions (exp, complain); /* Perform the other conversions. */ exp = decay_conversion (exp, complain); @@ -1975,7 +1975,7 @@ default_conversion (tree exp) converted value. */ tree -perform_integral_promotions (tree expr) +cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) { tree type; tree promoted_type; @@ -1995,10 +1995,18 @@ tree return expr; promoted_type = type_promotes_to (type); if (type != promoted_type) - expr = cp_convert (promoted_type, expr); + expr = cp_convert (promoted_type, expr, complain); return expr; } +/* C version. */ + +tree +perform_integral_promotions (tree expr) +{ + return cp_perform_integral_promotions (expr, tf_warning_or_error); +} + /* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */ @@ -2945,7 +2953,7 @@ cp_build_array_ref (location_t loc, tree array, tr does not say that we should. In fact, the natural thing would seem to be to convert IDX to ptrdiff_t; we're performing pointer arithmetic.) */ - idx = perform_integral_promotions (idx); + idx = cp_perform_integral_promotions (idx, complain); /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -3867,7 +3875,8 @@ cp_build_binary_op (location_t location, if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) - return pointer_diff (op0, op1, common_pointer_type (type0, type1)); + return pointer_diff (op0, op1, common_pointer_type (type0, type1), + complain); /* In all other cases except pointer - int, the usual arithmetic rules apply. */ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) @@ -4003,7 +4012,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4031,7 +4040,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4062,7 +4071,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); } break; @@ -4162,12 +4171,12 @@ cp_build_binary_op (location_t location, op0 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e1, e2, complain); - op1 = cp_convert (TREE_TYPE (op0), integer_one_node); + op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); } else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), op1); + op1 = cp_convert (TREE_TYPE (op0), op1, complain); } result_type = TREE_TYPE (op0); } @@ -4190,9 +4199,9 @@ cp_build_binary_op (location_t location, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) - op0 = cp_convert_and_check (type, op0); + op0 = cp_convert_and_check (type, op0, complain); if (!same_type_p (TREE_TYPE (op1), type)) - op1 = cp_convert_and_check (type, op1); + op1 = cp_convert_and_check (type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4456,16 +4465,16 @@ cp_build_binary_op (location_t location, if (first_complex) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != real_type) - op1 = cp_convert_and_check (real_type, op1); + op1 = cp_convert_and_check (real_type, op1, complain); } else { if (TREE_TYPE (op0) != real_type) - op0 = cp_convert_and_check (real_type, op0); + op0 = cp_convert_and_check (real_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); } if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) return error_mark_node; @@ -4550,7 +4559,7 @@ cp_build_binary_op (location_t location, tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return cp_convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val, complain); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -4580,9 +4589,9 @@ cp_build_binary_op (location_t location, if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4594,7 +4603,7 @@ cp_build_binary_op (location_t location, result = build2 (resultcode, build_type, op0, op1); result = fold_if_not_in_template (result); if (final_type != 0) - result = cp_convert (final_type, result); + result = cp_convert (final_type, result, complain); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (op0) @@ -4627,7 +4636,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tre The resulting tree has type int. */ static tree -pointer_diff (tree op0, tree op1, tree ptrtype) +pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) { tree result; tree restype = ptrdiff_type_node; @@ -4637,24 +4646,48 @@ static tree return error_mark_node; if (TREE_CODE (target_type) == VOID_TYPE) - permerror (input_location, "ISO C++ forbids using pointer of type %<void *%> in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer of " + "type %<void *%> in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == FUNCTION_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a function in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a function in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == METHOD_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a method in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a method in subtraction"); + else + return error_mark_node; + } /* First do the subtraction as integers; then drop through to build the divide operator. */ op0 = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (restype, op0), - cp_convert (restype, op1), - tf_warning_or_error); + cp_convert (restype, op0, complain), + cp_convert (restype, op1, complain), + complain); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) - error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); + { + if (complain & tf_error) + error ("invalid use of a pointer to an incomplete type in " + "pointer arithmetic"); + else + return error_mark_node; + } op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) @@ -4662,7 +4695,8 @@ static tree /* Do the division. */ - result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); + result = build2 (EXACT_DIV_EXPR, restype, op0, + cp_convert (restype, op1, complain)); return fold_if_not_in_template (result); } \f @@ -5175,7 +5209,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else { if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus expression is always a rvalue. */ @@ -5200,7 +5234,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); break; case ABS_EXPR: @@ -5358,7 +5392,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else inc = integer_one_node; - inc = cp_convert (argtype, inc); + inc = cp_convert (argtype, inc, complain); /* If 'arg' is an Objective-C PROPERTY_REF expression, then we need to ask Objective-C to build the increment or decrement @@ -6074,7 +6108,7 @@ build_static_cast_1 (tree type, tree expr, bool c_ || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -6417,7 +6451,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo return error_mark_node; } - return cp_convert (type, expr); + return cp_convert (type, expr, complain); } tree @@ -7078,7 +7112,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) - newrhs = cp_convert_and_check (lhstype, newrhs); + newrhs = cp_convert_and_check (lhstype, newrhs, complain); if (modifycode != INIT_EXPR) { @@ -7599,7 +7633,7 @@ convert_for_assignment (tree type, tree rhs, if (!warn_pmf2ptr && TYPE_PTR_P (type) && TYPE_PTRMEMFUNC_P (rhstype)) - rhs = cp_convert (strip_top_quals (type), rhs); + rhs = cp_convert (strip_top_quals (type), rhs, complain); else { if (complain & tf_error) Index: cp/optimize.c =================================================================== --- cp/optimize.c (revision 188203) +++ cp/optimize.c (working copy) @@ -138,7 +138,8 @@ build_delete_destructor_body (tree delete_dtor, tr virtual_size, /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); add_stmt (call_delete); /* Return the address of the object. */ Index: cp/init.c =================================================================== --- cp/init.c (revision 188203) +++ cp/init.c (working copy) @@ -1180,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1598,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tr have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -2656,7 +2657,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, size, globally_qualified_p, placement_allocation_fn_p ? alloc_call : NULL_TREE, - alloc_fn)); + alloc_fn, + complain)); if (!cleanup) /* We're done. */; @@ -2815,7 +2817,7 @@ build_new (VEC(tree,gc) **placement, tree type, tr return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -3012,12 +3014,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -3026,7 +3028,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd, virtual_size, use_global_delete & 1, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } body = loop; @@ -3189,14 +3192,14 @@ build_vec_init (tree base, tree maxindex, tree ini return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); base = decay_conversion (base, complain); if (base == error_mark_node) return error_mark_node; - base = cp_convert (ptype, base); + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3665,7 +3668,7 @@ build_delete (tree type, tree addr, special_functi addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3691,7 +3694,7 @@ build_delete (tree type, tree addr, special_functi if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); @@ -3705,7 +3708,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), use_global_delete, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } else { @@ -3744,7 +3748,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; } @@ -3756,7 +3761,8 @@ build_delete (tree type, tree addr, special_functi build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), Index: cp/class.c =================================================================== --- cp/class.c (revision 188203) +++ cp/class.c (working copy) @@ -366,7 +366,7 @@ build_base_path (enum tree_code code, /* Now that we've saved expr, build the real null test. */ if (null_test) { - tree zero = cp_convert (TREE_TYPE (expr), nullptr_node); + tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, expr, zero); } Index: cp/decl.c =================================================================== --- cp/decl.c (revision 188203) +++ cp/decl.c (working copy) @@ -8104,9 +8104,10 @@ compute_array_index_type (tree name, tree size, ts processing_template_decl = 0; itype = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node), - tf_warning_or_error); + cp_convert (ssizetype, size, complain), + cp_convert (ssizetype, integer_one_node, + complain), + complain); itype = fold (itype); processing_template_decl = saved_processing_template_decl; @@ -13290,11 +13291,12 @@ finish_destructor_body (void) an implicit definition), non-placement operator delete shall be looked up in the scope of the destructor's class and if found shall be accessible and unambiguous. */ - exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr, - virtual_size, - /*global_p=*/false, - /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, + virtual_size, + /*global_p=*/false, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); if_stmt = begin_if_stmt (); finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node, Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 188203) +++ cp/rtti.c (working copy) @@ -99,7 +99,7 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree ifnonnull (tree, tree); +static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); @@ -336,7 +336,8 @@ build_typeid (tree exp) This is an lvalue use of expr then. */ exp = mark_lvalue_use (exp); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), + tf_warning_or_error); } exp = get_tinfo_decl_dynamic (exp); @@ -498,12 +499,13 @@ get_typeid (tree type) RESULT, it must have previously had a save_expr applied to it. */ static tree -ifnonnull (tree test, tree result) +ifnonnull (tree test, tree result, tsubst_flags_t complain) { return build3 (COND_EXPR, TREE_TYPE (result), build2 (EQ_EXPR, boolean_type_node, test, - cp_convert (TREE_TYPE (test), nullptr_node)), - cp_convert (TREE_TYPE (result), nullptr_node), + cp_convert (TREE_TYPE (test), nullptr_node, + complain)), + cp_convert (TREE_TYPE (result), nullptr_node, complain), result); } @@ -596,7 +598,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst /* Apply trivial conversion T -> T& for dereferenced ptrs. */ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, complain); } /* The dynamic_cast operator shall not cast away constness. */ @@ -644,7 +646,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst expr1 = build_headof (expr); if (TREE_TYPE (expr1) != type) expr1 = build1 (NOP_EXPR, type, expr1); - return ifnonnull (expr, expr1); + return ifnonnull (expr, expr1, complain); } else { @@ -752,12 +754,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst neq = cp_truthvalue_conversion (result); return cp_convert (type, build3 (COND_EXPR, TREE_TYPE (result), - neq, result, bad)); + neq, result, bad), complain); } /* Now back to the type we want from a void*. */ - result = cp_convert (type, result); - return ifnonnull (expr, result); + result = cp_convert (type, result, complain); + return ifnonnull (expr, result, complain); } } else Index: cp/except.c =================================================================== --- cp/except.c (revision 188203) +++ cp/except.c (working copy) @@ -424,7 +424,8 @@ initialize_handler_parm (tree decl, tree exp) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); - exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); init = convert_from_reference (exp); @@ -435,7 +436,8 @@ initialize_handler_parm (tree decl, tree exp) /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 188203) +++ cp/typeck2.c (working copy) @@ -1264,7 +1264,7 @@ process_init_constructor_record (tree type, tree i /* If this is a bitfield, now convert to the lowered type. */ if (type != TREE_TYPE (field)) - next = cp_convert_and_check (TREE_TYPE (field), next); + next = cp_convert_and_check (TREE_TYPE (field), next, complain); flags |= picflag_from_initializer (next); CONSTRUCTOR_APPEND_ELT (v, field, next); } Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 188203) +++ cp/semantics.c (working copy) @@ -564,7 +564,8 @@ finish_goto_stmt (tree destination) destination = mark_rvalue_use (destination); if (!processing_template_decl) { - destination = cp_convert (ptr_type_node, destination); + destination = cp_convert (ptr_type_node, destination, + tf_warning_or_error); if (error_operand_p (destination)) return NULL_TREE; } @@ -4526,7 +4527,8 @@ handle_omp_for_class_iterator (int i, location_t l if (error_operand_p (iter_incr)) return true; incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, + tf_warning_or_error); if (TREE_CODE (rhs) == MINUS_EXPR) { incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); @@ -4581,7 +4583,7 @@ handle_omp_for_class_iterator (int i, location_t l return true; } - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == iter) @@ -5130,7 +5132,7 @@ finish_static_assert (tree condition, tree message /* Fold the expression and convert it to a boolean value. */ condition = fold_non_dependent_expr (condition); - condition = cp_convert (boolean_type_node, condition); + condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) Index: cp/call.c =================================================================== --- cp/call.c (revision 188204) +++ cp/call.c (working copy) @@ -5379,7 +5379,7 @@ non_placement_deallocation_fn_p (tree t) tree build_op_delete_call (enum tree_code code, tree addr, tree size, bool global_p, tree placement, - tree alloc_fn) + tree alloc_fn, tsubst_flags_t complain) { tree fn = NULL_TREE; tree fns, fnname, type, t; @@ -5413,7 +5413,7 @@ build_op_delete_call (enum tree_code code, tree ad fns = lookup_name_nonclass (fnname); /* Strip const and volatile from addr. */ - addr = cp_convert (ptr_type_node, addr); + addr = cp_convert (ptr_type_node, addr, complain); if (placement) { @@ -5452,8 +5452,13 @@ build_op_delete_call (enum tree_code code, tree ad && FUNCTION_ARG_CHAIN (elt) == void_list_node) goto ok; } - permerror (0, "non-placement deallocation function %q+D", fn); - permerror (input_location, "selected for placement delete"); + if (complain & tf_error) + { + permerror (0, "non-placement deallocation function %q+D", fn); + permerror (input_location, "selected for placement delete"); + } + else + return error_mark_node; ok:; } } @@ -5518,7 +5523,7 @@ build_op_delete_call (enum tree_code code, tree ad VEC_quick_push (tree, args, addr); if (FUNCTION_ARG_CHAIN (fn) != void_list_node) VEC_quick_push (tree, args, size); - ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error); + ret = cp_build_function_call_vec (fn, &args, complain); VEC_free (tree, gc, args); return ret; } @@ -5531,14 +5536,16 @@ build_op_delete_call (enum tree_code code, tree ad be freed. */ if (alloc_fn) { - if (!placement) + if ((complain & tf_warning) + && !placement) warning (0, "no corresponding deallocation function for %qD", alloc_fn); return NULL_TREE; } - error ("no suitable %<operator %s%> for %qT", - operator_name_info[(int)code].name, type); + if (complain & tf_error) + error ("no suitable %<operator %s%> for %qT", + operator_name_info[(int)code].name, type); return error_mark_node; } @@ -5685,9 +5692,10 @@ convert_like_real (conversion *convs, tree expr, t complain); if (convs->kind == ck_ref_bind) return convert_to_reference (totype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, + complain); else - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } else if (t->kind == ck_user || !t->bad_p) { @@ -5712,7 +5720,7 @@ convert_like_real (conversion *convs, tree expr, t permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } if (issue_conversion_warnings && (complain & tf_warning)) @@ -5851,7 +5859,7 @@ convert_like_real (conversion *convs, tree expr, t /* Take the address explicitly rather than via decay_conversion to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); - array = cp_convert (build_pointer_type (elttype), array); + array = cp_convert (build_pointer_type (elttype), array, complain); /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6017,7 +6025,7 @@ convert_like_real (conversion *convs, tree expr, t reference. This will adjust the pointer if a derived to base conversion is being performed. */ expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), - expr); + expr, complain); /* Convert the pointer to the desired reference type. */ return build_nop (ref_type, expr); } @@ -6099,9 +6107,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t if (complain & tf_warning) warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " "integral type in a future version of GCC", arg_type); - arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg); + arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); } - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); } arg = require_complete_type (arg); @@ -6336,7 +6344,7 @@ convert_for_arg_passing (tree type, tree val, tsub && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - val = perform_integral_promotions (val); + val = cp_perform_integral_promotions (val, complain); if ((complain & tf_warning) && warn_suggest_attribute_format) { Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 188203) +++ cp/cvt.c (working copy) @@ -38,10 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree); -static tree convert_to_pointer_force (tree, tree); +static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); +static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); -static tree build_up_reference (tree, tree, int, tree); +static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); static void warn_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- @@ -74,7 +74,7 @@ static void warn_ref_binding (location_t, tree, tr else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr) +cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -89,15 +89,17 @@ static tree intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { - error_at (loc, "can%'t convert from incomplete type %qT to %qT", - intype, type); + if (complain & tf_error) + error_at (loc, "can%'t convert from incomplete type %qT to %qT", + intype, type); return error_mark_node; } rval = build_type_conversion (type, expr); if (rval) { - if (rval == error_mark_node) + if ((complain & tf_error) + && rval == error_mark_node) error_at (loc, "conversion of %qE from %qT to %qT is ambiguous", expr, intype, type); return rval; @@ -111,7 +113,7 @@ static tree { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) - return convert_member_func_to_ptr (type, expr, tf_warning_or_error); + return convert_member_func_to_ptr (type, expr, complain); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); @@ -159,8 +161,7 @@ static tree if (binfo || same_p) { if (binfo) - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); /* Add any qualifier conversions. */ return build_nop (type, expr); } @@ -168,8 +169,9 @@ static tree if (TYPE_PTRMEMFUNC_P (type)) { - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -178,20 +180,20 @@ static tree else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) - return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr)); + return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), + complain); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); return get_member_function_from_ptrfunc (&object, TREE_OPERAND (expr, 1), - tf_warning_or_error); + complain); } } error_at (loc, "cannot convert %qE from type %qT to type %qT", @@ -201,14 +203,15 @@ static tree if (null_ptr_cst_p (expr)) { - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !NULLPTR_TYPE_P (TREE_TYPE (expr))) warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); if (TYPE_PTRDATAMEM_P (type)) { @@ -223,7 +226,8 @@ static tree } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { - error_at (loc, "invalid conversion from %qT to %qT", intype, type); + if (complain & tf_error) + error_at (loc, "invalid conversion from %qT to %qT", intype, type); return error_mark_node; } @@ -231,7 +235,8 @@ static tree { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width as a pointer. */ @@ -242,10 +247,11 @@ static tree } if (type_unknown_p (expr)) - return instantiate_type (type, expr, tf_warning_or_error); + return instantiate_type (type, expr, complain); - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -254,7 +260,7 @@ static tree (such as conversion from sub-type to private super-type). */ static tree -convert_to_pointer_force (tree type, tree expr) +convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); @@ -284,8 +290,7 @@ static tree return error_mark_node; if (binfo) { - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); if (expr == error_mark_node) return error_mark_node; /* Add any qualifier conversions. */ @@ -297,7 +302,7 @@ static tree } } - return cp_convert_to_pointer (type, expr); + return cp_convert_to_pointer (type, expr, complain); } /* We are passing something to a function which requires a reference. @@ -309,7 +314,8 @@ static tree If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (tree type, tree arg, int flags, tree decl) +build_up_reference (tree type, tree arg, int flags, tree decl, + tsubst_flags_t complain) { tree rval; tree argtype = TREE_TYPE (arg); @@ -351,12 +357,12 @@ static tree return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - rval = build_base_path (PLUS_EXPR, rval, binfo, 1, - tf_warning_or_error); + rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain); } else rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); + = convert_to_pointer_force (build_pointer_type (target_type), + rval, complain); return build_nop (type, rval); } @@ -403,15 +409,13 @@ warn_ref_binding (location_t loc, tree reftype, tr tree convert_to_reference (tree reftype, tree expr, int convtype, - int flags, tree decl) + int flags, tree decl, tsubst_flags_t complain) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN) - ? tf_warning_or_error : tf_none); location_t loc = EXPR_LOC_OR_HERE (expr); if (TREE_CODE (type) == FUNCTION_TYPE @@ -457,7 +461,8 @@ convert_to_reference (tree reftype, tree expr, int tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); - if (! real_lvalue_p (expr)) + if ((complain & tf_warning) + && ! real_lvalue_p (expr)) warn_ref_binding (loc, reftype, intype, decl); if (! (convtype & CONV_CONST) @@ -466,7 +471,7 @@ convert_to_reference (tree reftype, tree expr, int ttr, reftype); } - return build_up_reference (reftype, expr, flags, decl); + return build_up_reference (reftype, expr, flags, decl, complain); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -477,16 +482,17 @@ convert_to_reference (tree reftype, tree expr, int /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (TREE_CODE (intype) == POINTER_TYPE + if ((complain & tf_warning) + && TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = cp_build_addr_expr (expr, tf_warning_or_error); + rval = cp_build_addr_expr (expr, complain); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), - rval, 0); + rval, 0, complain); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } @@ -494,11 +500,12 @@ convert_to_reference (tree reftype, tree expr, int { rval = convert_for_initialization (NULL_TREE, type, expr, flags, ICR_CONVERTING, 0, 0, - tf_warning_or_error); + complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - warn_ref_binding (loc, reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags, decl); + if (complain & tf_warning) + warn_ref_binding (loc, reftype, intype, decl); + rval = build_up_reference (reftype, rval, flags, decl, complain); } if (rval) @@ -595,9 +602,9 @@ cp_fold_convert (tree type, tree expr) /* C++ conversions, preference to static cast conversions. */ tree -cp_convert (tree type, tree expr) +cp_convert (tree type, tree expr, tsubst_flags_t complain) { - return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain); } /* C++ equivalent of convert_and_check but using cp_convert as the @@ -608,16 +615,17 @@ tree i.e. because of language rules and not because of an explicit cast. */ tree -cp_convert_and_check (tree type, tree expr) +cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree result; if (TREE_TYPE (expr) == type) return expr; - result = cp_convert (type, expr); + result = cp_convert (type, expr, complain); - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !TREE_OVERFLOW_P (expr) && result != error_mark_node) warnings_for_convert_and_check (type, expr, result); @@ -630,7 +638,8 @@ tree FLAGS indicates how we should behave. */ tree -ocp_convert (tree type, tree expr, int convtype, int flags) +ocp_convert (tree type, tree expr, int convtype, int flags, + tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -647,7 +656,8 @@ tree if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { - error (invalid_conv_diag); + if (complain & tf_error) + error (invalid_conv_diag); return error_mark_node; } @@ -696,7 +706,7 @@ tree if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, ICV_CAST, tf_warning_or_error); + e = convert_to_void (e, ICV_CAST, complain); return e; } @@ -714,9 +724,14 @@ tree && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { - if (flags & LOOKUP_COMPLAIN) - permerror (loc, "conversion from %q#T to %q#T", intype, type); - if (!flag_permissive) + if (complain & tf_error) + { + permerror (loc, "conversion from %q#T to %q#T", + intype, type); + if (!flag_permissive) + return error_mark_node; + } + else return error_mark_node; } @@ -727,7 +742,8 @@ tree the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ - if (TREE_CODE (expr) == INTEGER_CST + if ((complain & tf_warning) + && TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " @@ -740,7 +756,7 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "%q#T used where a %qT was expected", intype, type); return error_mark_node; } @@ -748,8 +764,10 @@ tree { if (TREE_CODE (intype) == VOID_TYPE) { - error_at (loc, "could not convert %qE from %<void%> to %<bool%>", - expr); + if (complain & tf_error) + error_at (loc, + "could not convert %qE from %<void%> to %<bool%>", + expr); return error_mark_node; } @@ -768,7 +786,7 @@ tree if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); @@ -778,8 +796,9 @@ tree ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a %qT was expected", in_vtype, type); + if (complain & tf_error) + error_at (loc, "%q#T used where a %qT was expected", + in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); @@ -792,10 +811,10 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - else - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a floating point value was expected", - TREE_TYPE (e)); + else if (complain & tf_error) + error_at (loc, + "%q#T used where a floating point value was expected", + TREE_TYPE (e)); } if (code == REAL_TYPE) return fold_if_not_in_template (convert_to_real (type, e)); @@ -826,33 +845,31 @@ tree return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) - ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + ctor = perform_implicit_conversion (type, ctor, complain); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ - ctor = build_user_type_conversion (type, ctor, flags, - tf_warning_or_error); + ctor = build_user_type_conversion (type, ctor, flags, complain); else { VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, &ctor_vec, - type, flags, - tf_warning_or_error); + type, flags, complain); release_tree_vector (ctor_vec); } if (ctor) - return build_cplus_new (type, ctor, tf_warning_or_error); + return build_cplus_new (type, ctor, complain); } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) { /* If the conversion failed and expr was an invalid use of pointer to member function, try to report a meaningful error. */ - if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (expr, complain)) /* We displayed the error message. */; else error_at (loc, "conversion from %qT to non-scalar type %qT requested", @@ -1416,7 +1433,8 @@ convert (tree type, tree expr) return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + tf_warning_or_error); } /* Like cp_convert, except permit conversions to take place which @@ -1424,7 +1442,7 @@ convert (tree type, tree expr) (such as conversion from sub-type to private super-type). */ tree -convert_force (tree type, tree expr, int convtype) +convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -1432,10 +1450,11 @@ tree if (code == REFERENCE_TYPE) return (fold_if_not_in_template (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, - NULL_TREE))); + NULL_TREE, complain))); if (code == POINTER_TYPE) - return fold_if_not_in_template (convert_to_pointer_force (type, e)); + return fold_if_not_in_template (convert_to_pointer_force (type, e, + complain)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR @@ -1446,9 +1465,9 @@ tree && TYPE_PTRMEMFUNC_P (type)) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, - /*c_cast_p=*/1, tf_warning_or_error); + /*c_cast_p=*/1, complain); - return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain); } /* Convert an aggregate EXPR to type XTYPE. If a conversion Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 188203) +++ cp/cp-tree.h (working copy) @@ -4894,7 +4894,9 @@ extern tree build_new_op (location_t, enum tree_ tsubst_flags_t); extern tree build_op_call (tree, VEC(tree,gc) **, tsubst_flags_t); -extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); +extern tree build_op_delete_call (enum tree_code, tree, tree, + bool, tree, tree, + tsubst_flags_t); extern bool can_convert (tree, tree, tsubst_flags_t); extern bool can_convert_arg (tree, tree, tree, int, tsubst_flags_t); @@ -5001,16 +5003,19 @@ extern void adjust_clone_args (tree); extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ -extern tree convert_to_reference (tree, tree, int, int, tree); +extern tree convert_to_reference (tree, tree, int, int, tree, + tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); -extern tree ocp_convert (tree, tree, int, int); -extern tree cp_convert (tree, tree); -extern tree cp_convert_and_check (tree, tree); +extern tree ocp_convert (tree, tree, int, int, + tsubst_flags_t); +extern tree cp_convert (tree, tree, tsubst_flags_t); +extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, impl_conv_void, tsubst_flags_t); -extern tree convert_force (tree, tree, int); +extern tree convert_force (tree, tree, int, + tsubst_flags_t); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); extern tree perform_qualification_conversions (tree, tree); @@ -5901,6 +5906,7 @@ extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); +extern tree cp_perform_integral_promotions (tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-04 22:57 ` Paolo Carlini @ 2012-06-04 23:23 ` Jason Merrill 2012-06-04 23:47 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-04 23:23 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/04/2012 06:55 PM, Paolo Carlini wrote: > If, more generally, you mean we should remove it completely, I'm afraid > some cases are rather nasty. For example, I think that whenever we go > through implicit_conversion, thus its flags &=, the following function > calls can easily have at the same time complain & tf_error true and > flags & LOOKUP_COMPLAIN false. In cases where we currently don't set LOOKUP_COMPLAIN in flags, we can instead set complain to tf_none. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-04 23:23 ` Jason Merrill @ 2012-06-04 23:47 ` Paolo Carlini 2012-06-05 0:24 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-04 23:47 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On 06/05/2012 01:23 AM, Jason Merrill wrote: > On 06/04/2012 06:55 PM, Paolo Carlini wrote: >> If, more generally, you mean we should remove it completely, I'm afraid >> some cases are rather nasty. For example, I think that whenever we go >> through implicit_conversion, thus its flags &=, the following function >> calls can easily have at the same time complain & tf_error true and >> flags & LOOKUP_COMPLAIN false. > > In cases where we currently don't set LOOKUP_COMPLAIN in flags, we can > instead set complain to tf_none. Ok, I'll see what happens in the various specific circumstances. Indeed, earlier today I wondered myself if in principle not setting LOOKUP_COMPLAIN was just tf_none, but looking at the code things seemed more complex, when eg we are currently warning without checking LOOKUP_COMPLAIN and with complain available normally we would protect the warning with complain & tf_warning. But I don't want to speak too early ;) Let me see. Thanks! Paolo. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-04 23:47 ` Paolo Carlini @ 2012-06-05 0:24 ` Paolo Carlini 2012-06-05 2:11 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-05 0:24 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On 06/05/2012 01:45 AM, Paolo Carlini wrote: > On 06/05/2012 01:23 AM, Jason Merrill wrote: >> On 06/04/2012 06:55 PM, Paolo Carlini wrote: >>> If, more generally, you mean we should remove it completely, I'm afraid >>> some cases are rather nasty. For example, I think that whenever we go >>> through implicit_conversion, thus its flags &=, the following function >>> calls can easily have at the same time complain & tf_error true and >>> flags & LOOKUP_COMPLAIN false. >> >> In cases where we currently don't set LOOKUP_COMPLAIN in flags, we >> can instead set complain to tf_none. > Ok, I'll see what happens in the various specific circumstances. > Indeed, earlier today I wondered myself if in principle not setting > LOOKUP_COMPLAIN was just tf_none, but looking at the code things > seemed more complex, when eg we are currently warning without checking > LOOKUP_COMPLAIN and with complain available normally we would protect > the warning with complain & tf_warning. But I don't want to speak too > early ;) Let me see. In fact, I think setting complain to tf_warning may work better. Paolo. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 0:24 ` Paolo Carlini @ 2012-06-05 2:11 ` Jason Merrill 2012-06-05 11:02 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-05 2:11 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/04/2012 08:22 PM, Paolo Carlini wrote: > In fact, I think setting complain to tf_warning may work better. Sounds plausible. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 2:11 ` Jason Merrill @ 2012-06-05 11:02 ` Paolo Carlini 2012-06-05 14:17 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-05 11:02 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 608 bytes --] Hi, On 06/05/2012 04:10 AM, Jason Merrill wrote: > On 06/04/2012 08:22 PM, Paolo Carlini wrote: >> In fact, I think setting complain to tf_warning may work better. > Sounds plausible. Having quickly tried hackish implementations of the idea of allowing warnings, the way I actually propose to implement it in implicit_conversion is by masking out tf_error in the same place where we adjust the flags: exactly were we used to mask out LOOKUP_COMPLAIN we now mask out tf_error. The patch passes bootstrap and testing on x86_64-linux, LOOKUP_COMPLAIN is gone ;) Thanks, Paolo. /////////////////////// [-- Attachment #2: CL_53567_12 --] [-- Type: text/plain, Size: 2509 bytes --] /cp 2012-06-05 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * typeck.c (cp_perform_integral_promotions): New, like perform_integral_promotions but also takes a tsubst_flags_t parameter. (pointer_diff): Add tsubst_flags_t parameter. (decay_conversion, cp_default_conversion, cp_build_array_ref, cp_build_binary_op, cp_build_unary_op, build_static_cast_1, build_reinterpret_cast_1, cp_build_modify_expr, convert_for_assignment): Adjust. * optimize.c (build_delete_destructor_body): Adjust. * init.c (expand_virtual_init, expand_default_init, build_new_1, build_new, build_vec_delete_1, build_vec_init, build_delete): Adjust. (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. * class.c (build_base_path): Adjust. * decl.c (compute_array_index_type, finish_destructor_body): Likewise. * method.c (synthesized_method_walk): Adjust LOOKUP_PROTECT -> LOOKUP_NORMAL. * rtti.c (ifnonnull): Add tsubst_flags_t parameter. (build_typeid, build_dynamic_cast_1): Adjust. * except.c (initialize_handler_parm): Likewise. * typeck2.c (process_init_constructor_record): Likewise. * pt.c (tsubst_friend_class): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. * semantics.c (finish_goto_stmt, handle_omp_for_class_iterator, finish_static_assert): Likewise. * parser.c (cp_parser_lookup_name): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. * call.c (build_op_delete_call): Add tsubst_flags_t parameter. (convert_like_real, convert_arg_to_ellipsis, convert_for_arg_passing): Adjust. (standard_conversion): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. (implicit_conversion): Adjust LOOKUP_PROTECT -> LOOKUP_NORMAL; mask out tf_error. (build_user_type_conversion_1, build_new_op_1, build_over_call): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference, convert_to_reference, cp_convert, cp_convert_and_check, ocp_convert, convert_force): Add tsubst_flags_t parameter. (convert_to_reference, ocp_convert): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. (convert_force): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. * name-lookup.c (identifier_type_value_1, lookup_qualified_name, lookup_name_real, lookup_function_nonclass, lookup_name, lookup_name_prefer_type): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. * cp-tree.h: Adjust prototypes; remove LOOKUP_COMPLAIN. /testsuite 2012-06-05 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * g++.dg/cpp0x/alias-decl-19.C: New. [-- Attachment #3: patch_53567_12 --] [-- Type: text/plain, Size: 63006 bytes --] Index: testsuite/g++.dg/cpp0x/alias-decl-19.C =================================================================== --- testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) +++ testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) @@ -0,0 +1,31 @@ +// PR c++/53567 +// { dg-do compile { target c++11 } } + +template <unsigned int, bool> struct IntegerType { typedef unsigned type; }; + +template <class EnumT> +using UnderlyingEnumType = typename IntegerType<sizeof(EnumT), (EnumT(-1) > EnumT(0))>::type; + +template <class EnumT, class UnderlyingT = UnderlyingEnumType<EnumT>> +struct EnumMask +{ + constexpr EnumMask(EnumT val) : m_val(val) {} + operator EnumT() { return m_val; } + + EnumT m_val; +}; + +enum class A : unsigned { x }; + +template <class EnumT> +EnumMask<EnumT> operator ~(EnumT lhs) +{ + return EnumT(~unsigned(lhs) & unsigned(EnumT::maskAll)); // { dg-error "not a member" } + +} + +int main() +{ + ~A::x; + return 0; +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 188203) +++ cp/typeck.c (working copy) @@ -52,7 +52,7 @@ static tree rationalize_conditional_expr (enum tre static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (const_tree, const_tree, bool); -static tree pointer_diff (tree, tree, tree); +static tree pointer_diff (tree, tree, tree, tsubst_flags_t); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); @@ -1906,7 +1906,7 @@ decay_conversion (tree exp, tsubst_flags_t complai /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = cp_build_addr_expr (exp, complain); - return cp_convert (ptrtype, adr); + return cp_convert (ptrtype, adr, complain); } /* If a bitfield is used in a context where integral promotion @@ -1950,12 +1950,12 @@ cp_default_conversion (tree exp, tsubst_flags_t co /* Check for target-specific promotions. */ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); if (promoted_type) - exp = cp_convert (promoted_type, exp); + exp = cp_convert (promoted_type, exp, complain); /* Perform the integral promotions first so that bitfield expressions (which may promote to "int", even if the bitfield is declared "unsigned") are promoted correctly. */ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); + exp = cp_perform_integral_promotions (exp, complain); /* Perform the other conversions. */ exp = decay_conversion (exp, complain); @@ -1975,7 +1975,7 @@ default_conversion (tree exp) converted value. */ tree -perform_integral_promotions (tree expr) +cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) { tree type; tree promoted_type; @@ -1995,10 +1995,18 @@ tree return expr; promoted_type = type_promotes_to (type); if (type != promoted_type) - expr = cp_convert (promoted_type, expr); + expr = cp_convert (promoted_type, expr, complain); return expr; } +/* C version. */ + +tree +perform_integral_promotions (tree expr) +{ + return cp_perform_integral_promotions (expr, tf_warning_or_error); +} + /* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */ @@ -2945,7 +2953,7 @@ cp_build_array_ref (location_t loc, tree array, tr does not say that we should. In fact, the natural thing would seem to be to convert IDX to ptrdiff_t; we're performing pointer arithmetic.) */ - idx = perform_integral_promotions (idx); + idx = cp_perform_integral_promotions (idx, complain); /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -3867,7 +3875,8 @@ cp_build_binary_op (location_t location, if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) - return pointer_diff (op0, op1, common_pointer_type (type0, type1)); + return pointer_diff (op0, op1, common_pointer_type (type0, type1), + complain); /* In all other cases except pointer - int, the usual arithmetic rules apply. */ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) @@ -4003,7 +4012,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4031,7 +4040,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4062,7 +4071,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); } break; @@ -4162,12 +4171,12 @@ cp_build_binary_op (location_t location, op0 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e1, e2, complain); - op1 = cp_convert (TREE_TYPE (op0), integer_one_node); + op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); } else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), op1); + op1 = cp_convert (TREE_TYPE (op0), op1, complain); } result_type = TREE_TYPE (op0); } @@ -4190,9 +4199,9 @@ cp_build_binary_op (location_t location, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) - op0 = cp_convert_and_check (type, op0); + op0 = cp_convert_and_check (type, op0, complain); if (!same_type_p (TREE_TYPE (op1), type)) - op1 = cp_convert_and_check (type, op1); + op1 = cp_convert_and_check (type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4456,16 +4465,16 @@ cp_build_binary_op (location_t location, if (first_complex) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != real_type) - op1 = cp_convert_and_check (real_type, op1); + op1 = cp_convert_and_check (real_type, op1, complain); } else { if (TREE_TYPE (op0) != real_type) - op0 = cp_convert_and_check (real_type, op0); + op0 = cp_convert_and_check (real_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); } if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) return error_mark_node; @@ -4550,7 +4559,7 @@ cp_build_binary_op (location_t location, tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return cp_convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val, complain); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -4580,9 +4589,9 @@ cp_build_binary_op (location_t location, if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4594,7 +4603,7 @@ cp_build_binary_op (location_t location, result = build2 (resultcode, build_type, op0, op1); result = fold_if_not_in_template (result); if (final_type != 0) - result = cp_convert (final_type, result); + result = cp_convert (final_type, result, complain); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (op0) @@ -4627,7 +4636,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tre The resulting tree has type int. */ static tree -pointer_diff (tree op0, tree op1, tree ptrtype) +pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) { tree result; tree restype = ptrdiff_type_node; @@ -4637,24 +4646,48 @@ static tree return error_mark_node; if (TREE_CODE (target_type) == VOID_TYPE) - permerror (input_location, "ISO C++ forbids using pointer of type %<void *%> in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer of " + "type %<void *%> in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == FUNCTION_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a function in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a function in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == METHOD_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a method in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a method in subtraction"); + else + return error_mark_node; + } /* First do the subtraction as integers; then drop through to build the divide operator. */ op0 = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (restype, op0), - cp_convert (restype, op1), - tf_warning_or_error); + cp_convert (restype, op0, complain), + cp_convert (restype, op1, complain), + complain); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) - error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); + { + if (complain & tf_error) + error ("invalid use of a pointer to an incomplete type in " + "pointer arithmetic"); + else + return error_mark_node; + } op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) @@ -4662,7 +4695,8 @@ static tree /* Do the division. */ - result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); + result = build2 (EXACT_DIV_EXPR, restype, op0, + cp_convert (restype, op1, complain)); return fold_if_not_in_template (result); } \f @@ -5175,7 +5209,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else { if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus expression is always a rvalue. */ @@ -5200,7 +5234,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); break; case ABS_EXPR: @@ -5358,7 +5392,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else inc = integer_one_node; - inc = cp_convert (argtype, inc); + inc = cp_convert (argtype, inc, complain); /* If 'arg' is an Objective-C PROPERTY_REF expression, then we need to ask Objective-C to build the increment or decrement @@ -6074,7 +6108,7 @@ build_static_cast_1 (tree type, tree expr, bool c_ || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -6417,7 +6451,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo return error_mark_node; } - return cp_convert (type, expr); + return cp_convert (type, expr, complain); } tree @@ -7078,7 +7112,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) - newrhs = cp_convert_and_check (lhstype, newrhs); + newrhs = cp_convert_and_check (lhstype, newrhs, complain); if (modifycode != INIT_EXPR) { @@ -7599,7 +7633,7 @@ convert_for_assignment (tree type, tree rhs, if (!warn_pmf2ptr && TYPE_PTR_P (type) && TYPE_PTRMEMFUNC_P (rhstype)) - rhs = cp_convert (strip_top_quals (type), rhs); + rhs = cp_convert (strip_top_quals (type), rhs, complain); else { if (complain & tf_error) @@ -7723,10 +7757,8 @@ convert_for_assignment (tree type, tree rhs, latter (X(X&)). If using constructor make sure no conversion operator exists, if one does - exist, an ambiguity exists. + exist, an ambiguity exists. */ - If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */ - tree convert_for_initialization (tree exp, tree type, tree rhs, int flags, impl_conv_rhs errtype, tree fndecl, int parmnum, Index: cp/optimize.c =================================================================== --- cp/optimize.c (revision 188203) +++ cp/optimize.c (working copy) @@ -138,7 +138,8 @@ build_delete_destructor_body (tree delete_dtor, tr virtual_size, /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); add_stmt (call_delete); /* Return the address of the object. */ Index: cp/init.c =================================================================== --- cp/init.c (revision 188203) +++ cp/init.c (working copy) @@ -1180,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1250,7 +1250,7 @@ construct_virtual_base (tree vbase, tree arguments exp = convert_to_base_statically (current_class_ref, vbase); expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, - LOOKUP_COMPLAIN, tf_warning_or_error); + LOOKUP_NORMAL, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1598,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tr have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -2656,7 +2657,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, size, globally_qualified_p, placement_allocation_fn_p ? alloc_call : NULL_TREE, - alloc_fn)); + alloc_fn, + complain)); if (!cleanup) /* We're done. */; @@ -2815,7 +2817,7 @@ build_new (VEC(tree,gc) **placement, tree type, tr return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -3012,12 +3014,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -3026,7 +3028,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd, virtual_size, use_global_delete & 1, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } body = loop; @@ -3189,14 +3192,14 @@ build_vec_init (tree base, tree maxindex, tree ini return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); base = decay_conversion (base, complain); if (base == error_mark_node) return error_mark_node; - base = cp_convert (ptype, base); + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3665,7 +3668,7 @@ build_delete (tree type, tree addr, special_functi addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3691,7 +3694,7 @@ build_delete (tree type, tree addr, special_functi if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); @@ -3705,7 +3708,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), use_global_delete, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } else { @@ -3744,7 +3748,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; } @@ -3756,7 +3761,8 @@ build_delete (tree type, tree addr, special_functi build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), Index: cp/class.c =================================================================== --- cp/class.c (revision 188203) +++ cp/class.c (working copy) @@ -366,7 +366,7 @@ build_base_path (enum tree_code code, /* Now that we've saved expr, build the real null test. */ if (null_test) { - tree zero = cp_convert (TREE_TYPE (expr), nullptr_node); + tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, expr, zero); } Index: cp/decl.c =================================================================== --- cp/decl.c (revision 188203) +++ cp/decl.c (working copy) @@ -8104,9 +8104,10 @@ compute_array_index_type (tree name, tree size, ts processing_template_decl = 0; itype = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node), - tf_warning_or_error); + cp_convert (ssizetype, size, complain), + cp_convert (ssizetype, integer_one_node, + complain), + complain); itype = fold (itype); processing_template_decl = saved_processing_template_decl; @@ -13290,11 +13291,12 @@ finish_destructor_body (void) an implicit definition), non-placement operator delete shall be looked up in the scope of the destructor's class and if found shall be accessible and unambiguous. */ - exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr, - virtual_size, - /*global_p=*/false, - /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, + virtual_size, + /*global_p=*/false, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); if_stmt = begin_if_stmt (); finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node, Index: cp/method.c =================================================================== --- cp/method.c (revision 188203) +++ cp/method.c (working copy) @@ -1228,17 +1228,10 @@ synthesized_method_walk (tree ctype, special_funct scope = push_scope (ctype); - if (diag) - { - flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_warning_or_error; - } - else - { - flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_none; - } + flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; + complain = diag ? tf_warning_or_error : tf_none; + if (const_p) quals = TYPE_QUAL_CONST; else Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 188203) +++ cp/rtti.c (working copy) @@ -99,7 +99,7 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree ifnonnull (tree, tree); +static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); @@ -336,7 +336,8 @@ build_typeid (tree exp) This is an lvalue use of expr then. */ exp = mark_lvalue_use (exp); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), + tf_warning_or_error); } exp = get_tinfo_decl_dynamic (exp); @@ -498,12 +499,13 @@ get_typeid (tree type) RESULT, it must have previously had a save_expr applied to it. */ static tree -ifnonnull (tree test, tree result) +ifnonnull (tree test, tree result, tsubst_flags_t complain) { return build3 (COND_EXPR, TREE_TYPE (result), build2 (EQ_EXPR, boolean_type_node, test, - cp_convert (TREE_TYPE (test), nullptr_node)), - cp_convert (TREE_TYPE (result), nullptr_node), + cp_convert (TREE_TYPE (test), nullptr_node, + complain)), + cp_convert (TREE_TYPE (result), nullptr_node, complain), result); } @@ -596,7 +598,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst /* Apply trivial conversion T -> T& for dereferenced ptrs. */ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, complain); } /* The dynamic_cast operator shall not cast away constness. */ @@ -644,7 +646,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst expr1 = build_headof (expr); if (TREE_TYPE (expr1) != type) expr1 = build1 (NOP_EXPR, type, expr1); - return ifnonnull (expr, expr1); + return ifnonnull (expr, expr1, complain); } else { @@ -752,12 +754,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst neq = cp_truthvalue_conversion (result); return cp_convert (type, build3 (COND_EXPR, TREE_TYPE (result), - neq, result, bad)); + neq, result, bad), complain); } /* Now back to the type we want from a void*. */ - result = cp_convert (type, result); - return ifnonnull (expr, result); + result = cp_convert (type, result, complain); + return ifnonnull (expr, result, complain); } } else Index: cp/except.c =================================================================== --- cp/except.c (revision 188203) +++ cp/except.c (working copy) @@ -424,7 +424,8 @@ initialize_handler_parm (tree decl, tree exp) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); - exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); init = convert_from_reference (exp); @@ -435,7 +436,8 @@ initialize_handler_parm (tree decl, tree exp) /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 188203) +++ cp/typeck2.c (working copy) @@ -1264,7 +1264,7 @@ process_init_constructor_record (tree type, tree i /* If this is a bitfield, now convert to the lowered type. */ if (type != TREE_TYPE (field)) - next = cp_convert_and_check (TREE_TYPE (field), next); + next = cp_convert_and_check (TREE_TYPE (field), next, complain); flags |= picflag_from_initializer (next); CONSTRUCTOR_APPEND_ELT (v, field, next); } Index: cp/pt.c =================================================================== --- cp/pt.c (revision 188203) +++ cp/pt.c (working copy) @@ -8475,7 +8475,7 @@ tsubst_friend_class (tree friend_tmpl, tree args) both F templates are the same. */ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0, /*block_p=*/true, 0, - LOOKUP_COMPLAIN | LOOKUP_HIDDEN); + LOOKUP_NORMAL | LOOKUP_HIDDEN); /* But, if we don't find one, it might be because we're in a situation like this: Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 188203) +++ cp/semantics.c (working copy) @@ -564,7 +564,8 @@ finish_goto_stmt (tree destination) destination = mark_rvalue_use (destination); if (!processing_template_decl) { - destination = cp_convert (ptr_type_node, destination); + destination = cp_convert (ptr_type_node, destination, + tf_warning_or_error); if (error_operand_p (destination)) return NULL_TREE; } @@ -4526,7 +4527,8 @@ handle_omp_for_class_iterator (int i, location_t l if (error_operand_p (iter_incr)) return true; incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, + tf_warning_or_error); if (TREE_CODE (rhs) == MINUS_EXPR) { incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); @@ -4581,7 +4583,7 @@ handle_omp_for_class_iterator (int i, location_t l return true; } - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == iter) @@ -5130,7 +5132,7 @@ finish_static_assert (tree condition, tree message /* Fold the expression and convert it to a boolean value. */ condition = fold_non_dependent_expr (condition); - condition = cp_convert (boolean_type_node, condition); + condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) Index: cp/parser.c =================================================================== --- cp/parser.c (revision 188203) +++ cp/parser.c (working copy) @@ -20322,7 +20322,7 @@ cp_parser_lookup_name (cp_parser *parser, tree nam tree object_type = parser->context->object_type; if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - flags |= LOOKUP_COMPLAIN; + flags |= LOOKUP_NORMAL; /* Assume that the lookup will be unambiguous. */ if (ambiguous_decls) Index: cp/call.c =================================================================== --- cp/call.c (revision 188204) +++ cp/call.c (working copy) @@ -1095,7 +1095,7 @@ standard_conversion (tree to, tree from, tree expr && expr && type_unknown_p (expr)) { tsubst_flags_t tflags = tf_conv; - if (!(flags & LOOKUP_PROTECT)) + if (!(flags & LOOKUP_NORMAL)) tflags |= tf_no_access_control; expr = instantiate_type (to, expr, tflags); if (expr == error_mark_node) @@ -1693,8 +1693,10 @@ implicit_conversion (tree to, tree from, tree expr resolution, or after we've chosen one. */ flags &= (LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION|LOOKUP_COPY_PARM |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE - |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); + |LOOKUP_NO_NARROWING|LOOKUP_NORMAL); + complain &= ~tf_error; + if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, c_cast_p, flags, complain); else @@ -3607,8 +3609,7 @@ build_user_type_conversion_1 (tree totype, tree ex cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) - && (complain & tf_error)) + if (complain & tf_error) { error ("conversion from %qT to %qT is ambiguous", fromtype, totype); @@ -5098,7 +5099,7 @@ build_new_op_1 (location_t loc, enum tree_code cod distinguish between prefix and postfix ++ and operator++() was used for both, so we allow this with -fpermissive. */ - if (flags & LOOKUP_COMPLAIN) + else { const char *msg = (flag_permissive) ? G_("no %<%D(int)%> declared for postfix %qs," @@ -5127,7 +5128,7 @@ build_new_op_1 (location_t loc, enum tree_code cod break; default: - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { /* If one of the arguments of the operator represents an invalid use of member function pointer, try to report @@ -5153,7 +5154,7 @@ build_new_op_1 (location_t loc, enum tree_code cod cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { op_error (loc, code, code2, arg1, arg2, arg3, TRUE); print_z_candidates (loc, candidates); @@ -5379,7 +5380,7 @@ non_placement_deallocation_fn_p (tree t) tree build_op_delete_call (enum tree_code code, tree addr, tree size, bool global_p, tree placement, - tree alloc_fn) + tree alloc_fn, tsubst_flags_t complain) { tree fn = NULL_TREE; tree fns, fnname, type, t; @@ -5413,7 +5414,7 @@ build_op_delete_call (enum tree_code code, tree ad fns = lookup_name_nonclass (fnname); /* Strip const and volatile from addr. */ - addr = cp_convert (ptr_type_node, addr); + addr = cp_convert (ptr_type_node, addr, complain); if (placement) { @@ -5452,8 +5453,13 @@ build_op_delete_call (enum tree_code code, tree ad && FUNCTION_ARG_CHAIN (elt) == void_list_node) goto ok; } - permerror (0, "non-placement deallocation function %q+D", fn); - permerror (input_location, "selected for placement delete"); + if (complain & tf_error) + { + permerror (0, "non-placement deallocation function %q+D", fn); + permerror (input_location, "selected for placement delete"); + } + else + return error_mark_node; ok:; } } @@ -5518,7 +5524,7 @@ build_op_delete_call (enum tree_code code, tree ad VEC_quick_push (tree, args, addr); if (FUNCTION_ARG_CHAIN (fn) != void_list_node) VEC_quick_push (tree, args, size); - ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error); + ret = cp_build_function_call_vec (fn, &args, complain); VEC_free (tree, gc, args); return ret; } @@ -5531,14 +5537,16 @@ build_op_delete_call (enum tree_code code, tree ad be freed. */ if (alloc_fn) { - if (!placement) + if ((complain & tf_warning) + && !placement) warning (0, "no corresponding deallocation function for %qD", alloc_fn); return NULL_TREE; } - error ("no suitable %<operator %s%> for %qT", - operator_name_info[(int)code].name, type); + if (complain & tf_error) + error ("no suitable %<operator %s%> for %qT", + operator_name_info[(int)code].name, type); return error_mark_node; } @@ -5685,9 +5693,10 @@ convert_like_real (conversion *convs, tree expr, t complain); if (convs->kind == ck_ref_bind) return convert_to_reference (totype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, + complain); else - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } else if (t->kind == ck_user || !t->bad_p) { @@ -5712,7 +5721,7 @@ convert_like_real (conversion *convs, tree expr, t permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } if (issue_conversion_warnings && (complain & tf_warning)) @@ -5851,7 +5860,7 @@ convert_like_real (conversion *convs, tree expr, t /* Take the address explicitly rather than via decay_conversion to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); - array = cp_convert (build_pointer_type (elttype), array); + array = cp_convert (build_pointer_type (elttype), array, complain); /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6017,7 +6026,7 @@ convert_like_real (conversion *convs, tree expr, t reference. This will adjust the pointer if a derived to base conversion is being performed. */ expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), - expr); + expr, complain); /* Convert the pointer to the desired reference type. */ return build_nop (ref_type, expr); } @@ -6099,9 +6108,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t if (complain & tf_warning) warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " "integral type in a future version of GCC", arg_type); - arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg); + arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); } - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); } arg = require_complete_type (arg); @@ -6336,7 +6345,7 @@ convert_for_arg_passing (tree type, tree val, tsub && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - val = perform_integral_promotions (val); + val = cp_perform_integral_promotions (val, complain); if ((complain & tf_warning) && warn_suggest_attribute_format) { @@ -6487,7 +6496,7 @@ build_over_call (struct z_candidate *cand, int fla if (flags & LOOKUP_SPECULATIVE) { if (!speculative_access_check (cand->access_path, access_fn, fn, - !!(flags & LOOKUP_COMPLAIN))) + complain & tf_error)) return error_mark_node; } else @@ -6500,13 +6509,13 @@ build_over_call (struct z_candidate *cand, int fla { if (DECL_DELETED_FN (fn)) { - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) mark_used (fn); return error_mark_node; } if (cand->viable == 1) return fn; - else if (!(flags & LOOKUP_COMPLAIN)) + else if (!(complain & tf_error)) /* Reject bad conversions now. */ return error_mark_node; /* else continue to get conversion error. */ Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 188203) +++ cp/cvt.c (working copy) @@ -38,10 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree); -static tree convert_to_pointer_force (tree, tree); +static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); +static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); -static tree build_up_reference (tree, tree, int, tree); +static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); static void warn_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- @@ -74,7 +74,7 @@ static void warn_ref_binding (location_t, tree, tr else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr) +cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -89,15 +89,17 @@ static tree intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { - error_at (loc, "can%'t convert from incomplete type %qT to %qT", - intype, type); + if (complain & tf_error) + error_at (loc, "can%'t convert from incomplete type %qT to %qT", + intype, type); return error_mark_node; } rval = build_type_conversion (type, expr); if (rval) { - if (rval == error_mark_node) + if ((complain & tf_error) + && rval == error_mark_node) error_at (loc, "conversion of %qE from %qT to %qT is ambiguous", expr, intype, type); return rval; @@ -111,7 +113,7 @@ static tree { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) - return convert_member_func_to_ptr (type, expr, tf_warning_or_error); + return convert_member_func_to_ptr (type, expr, complain); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); @@ -159,8 +161,7 @@ static tree if (binfo || same_p) { if (binfo) - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); /* Add any qualifier conversions. */ return build_nop (type, expr); } @@ -168,8 +169,9 @@ static tree if (TYPE_PTRMEMFUNC_P (type)) { - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -178,20 +180,20 @@ static tree else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) - return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr)); + return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), + complain); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); return get_member_function_from_ptrfunc (&object, TREE_OPERAND (expr, 1), - tf_warning_or_error); + complain); } } error_at (loc, "cannot convert %qE from type %qT to type %qT", @@ -201,14 +203,15 @@ static tree if (null_ptr_cst_p (expr)) { - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !NULLPTR_TYPE_P (TREE_TYPE (expr))) warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); if (TYPE_PTRDATAMEM_P (type)) { @@ -223,7 +226,8 @@ static tree } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { - error_at (loc, "invalid conversion from %qT to %qT", intype, type); + if (complain & tf_error) + error_at (loc, "invalid conversion from %qT to %qT", intype, type); return error_mark_node; } @@ -231,7 +235,8 @@ static tree { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width as a pointer. */ @@ -242,10 +247,11 @@ static tree } if (type_unknown_p (expr)) - return instantiate_type (type, expr, tf_warning_or_error); + return instantiate_type (type, expr, complain); - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -254,7 +260,7 @@ static tree (such as conversion from sub-type to private super-type). */ static tree -convert_to_pointer_force (tree type, tree expr) +convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); @@ -284,8 +290,7 @@ static tree return error_mark_node; if (binfo) { - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); if (expr == error_mark_node) return error_mark_node; /* Add any qualifier conversions. */ @@ -297,7 +302,7 @@ static tree } } - return cp_convert_to_pointer (type, expr); + return cp_convert_to_pointer (type, expr, complain); } /* We are passing something to a function which requires a reference. @@ -309,7 +314,8 @@ static tree If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (tree type, tree arg, int flags, tree decl) +build_up_reference (tree type, tree arg, int flags, tree decl, + tsubst_flags_t complain) { tree rval; tree argtype = TREE_TYPE (arg); @@ -340,7 +346,7 @@ static tree if (rval == error_mark_node) return error_mark_node; - if ((flags & LOOKUP_PROTECT) + if ((flags & LOOKUP_NORMAL) && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type) && MAYBE_CLASS_TYPE_P (argtype) && MAYBE_CLASS_TYPE_P (target_type)) @@ -351,12 +357,12 @@ static tree return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - rval = build_base_path (PLUS_EXPR, rval, binfo, 1, - tf_warning_or_error); + rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain); } else rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); + = convert_to_pointer_force (build_pointer_type (target_type), + rval, complain); return build_nop (type, rval); } @@ -403,15 +409,13 @@ warn_ref_binding (location_t loc, tree reftype, tr tree convert_to_reference (tree reftype, tree expr, int convtype, - int flags, tree decl) + int flags, tree decl, tsubst_flags_t complain) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN) - ? tf_warning_or_error : tf_none); location_t loc = EXPR_LOC_OR_HERE (expr); if (TREE_CODE (type) == FUNCTION_TYPE @@ -452,21 +456,26 @@ convert_to_reference (tree reftype, tree expr, int if (((convtype & CONV_STATIC) && can_convert (intype, type, complain)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { - if (flags & LOOKUP_COMPLAIN) - { - tree ttl = TREE_TYPE (reftype); - tree ttr = lvalue_type (expr); + { + tree ttl = TREE_TYPE (reftype); + tree ttr = lvalue_type (expr); - if (! real_lvalue_p (expr)) - warn_ref_binding (loc, reftype, intype, decl); + if ((complain & tf_warning) + && ! real_lvalue_p (expr)) + warn_ref_binding (loc, reftype, intype, decl); - if (! (convtype & CONV_CONST) - && !at_least_as_qualified_p (ttl, ttr)) - permerror (loc, "conversion from %qT to %qT discards qualifiers", - ttr, reftype); - } + if (! (convtype & CONV_CONST) + && !at_least_as_qualified_p (ttl, ttr)) + { + if (complain & tf_error) + permerror (loc, "conversion from %qT to %qT discards qualifiers", + ttr, reftype); + else + return error_mark_node; + } + } - return build_up_reference (reftype, expr, flags, decl); + return build_up_reference (reftype, expr, flags, decl, complain); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -477,28 +486,29 @@ convert_to_reference (tree reftype, tree expr, int /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (TREE_CODE (intype) == POINTER_TYPE + if ((complain & tf_warning) + && TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = cp_build_addr_expr (expr, tf_warning_or_error); + rval = cp_build_addr_expr (expr, complain); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), - rval, 0); + rval, 0, complain); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, - ICR_CONVERTING, 0, 0, - tf_warning_or_error); + ICR_CONVERTING, 0, 0, complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - warn_ref_binding (loc, reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags, decl); + if (complain & tf_warning) + warn_ref_binding (loc, reftype, intype, decl); + rval = build_up_reference (reftype, rval, flags, decl, complain); } if (rval) @@ -507,7 +517,7 @@ convert_to_reference (tree reftype, tree expr, int return rval; } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; @@ -595,9 +605,9 @@ cp_fold_convert (tree type, tree expr) /* C++ conversions, preference to static cast conversions. */ tree -cp_convert (tree type, tree expr) +cp_convert (tree type, tree expr, tsubst_flags_t complain) { - return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain); } /* C++ equivalent of convert_and_check but using cp_convert as the @@ -608,16 +618,17 @@ tree i.e. because of language rules and not because of an explicit cast. */ tree -cp_convert_and_check (tree type, tree expr) +cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree result; if (TREE_TYPE (expr) == type) return expr; - result = cp_convert (type, expr); + result = cp_convert (type, expr, complain); - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !TREE_OVERFLOW_P (expr) && result != error_mark_node) warnings_for_convert_and_check (type, expr, result); @@ -630,7 +641,8 @@ tree FLAGS indicates how we should behave. */ tree -ocp_convert (tree type, tree expr, int convtype, int flags) +ocp_convert (tree type, tree expr, int convtype, int flags, + tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -647,7 +659,8 @@ tree if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { - error (invalid_conv_diag); + if (complain & tf_error) + error (invalid_conv_diag); return error_mark_node; } @@ -696,7 +709,7 @@ tree if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, ICV_CAST, tf_warning_or_error); + e = convert_to_void (e, ICV_CAST, complain); return e; } @@ -714,9 +727,14 @@ tree && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { - if (flags & LOOKUP_COMPLAIN) - permerror (loc, "conversion from %q#T to %q#T", intype, type); - if (!flag_permissive) + if (complain & tf_error) + { + permerror (loc, "conversion from %q#T to %q#T", + intype, type); + if (!flag_permissive) + return error_mark_node; + } + else return error_mark_node; } @@ -727,7 +745,8 @@ tree the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ - if (TREE_CODE (expr) == INTEGER_CST + if ((complain & tf_warning) + && TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " @@ -740,7 +759,7 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "%q#T used where a %qT was expected", intype, type); return error_mark_node; } @@ -748,8 +767,10 @@ tree { if (TREE_CODE (intype) == VOID_TYPE) { - error_at (loc, "could not convert %qE from %<void%> to %<bool%>", - expr); + if (complain & tf_error) + error_at (loc, + "could not convert %qE from %<void%> to %<bool%>", + expr); return error_mark_node; } @@ -768,7 +789,7 @@ tree if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); @@ -778,8 +799,9 @@ tree ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a %qT was expected", in_vtype, type); + if (complain & tf_error) + error_at (loc, "%q#T used where a %qT was expected", + in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); @@ -792,10 +814,10 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - else - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a floating point value was expected", - TREE_TYPE (e)); + else if (complain & tf_error) + error_at (loc, + "%q#T used where a floating point value was expected", + TREE_TYPE (e)); } if (code == REAL_TYPE) return fold_if_not_in_template (convert_to_real (type, e)); @@ -826,33 +848,31 @@ tree return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) - ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + ctor = perform_implicit_conversion (type, ctor, complain); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ - ctor = build_user_type_conversion (type, ctor, flags, - tf_warning_or_error); + ctor = build_user_type_conversion (type, ctor, flags, complain); else { VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, &ctor_vec, - type, flags, - tf_warning_or_error); + type, flags, complain); release_tree_vector (ctor_vec); } if (ctor) - return build_cplus_new (type, ctor, tf_warning_or_error); + return build_cplus_new (type, ctor, complain); } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) { /* If the conversion failed and expr was an invalid use of pointer to member function, try to report a meaningful error. */ - if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (expr, complain)) /* We displayed the error message. */; else error_at (loc, "conversion from %qT to non-scalar type %qT requested", @@ -1416,7 +1436,8 @@ convert (tree type, tree expr) return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + tf_warning_or_error); } /* Like cp_convert, except permit conversions to take place which @@ -1424,18 +1445,19 @@ convert (tree type, tree expr) (such as conversion from sub-type to private super-type). */ tree -convert_force (tree type, tree expr, int convtype) +convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) return (fold_if_not_in_template - (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, - NULL_TREE))); + (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_NORMAL, + NULL_TREE, complain))); if (code == POINTER_TYPE) - return fold_if_not_in_template (convert_to_pointer_force (type, e)); + return fold_if_not_in_template (convert_to_pointer_force (type, e, + complain)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR @@ -1446,9 +1468,9 @@ tree && TYPE_PTRMEMFUNC_P (type)) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, - /*c_cast_p=*/1, tf_warning_or_error); + /*c_cast_p=*/1, complain); - return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain); } /* Convert an aggregate EXPR to type XTYPE. If a conversion Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 188203) +++ cp/cp-tree.h (working copy) @@ -4370,17 +4370,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T probably be modified to accept explicit boolean flags for the behaviors relevant to them. */ /* Check for access violations. */ -#define LOOKUP_PROTECT (1 << 0) -/* Complain if no suitable member function matching the arguments is - found. */ -#define LOOKUP_COMPLAIN (1 << 1) -#define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN) +#define LOOKUP_NORMAL (1 << 0) /* Even if the function found by lookup is a virtual function, it should be called directly. */ -#define LOOKUP_NONVIRTUAL (1 << 2) +#define LOOKUP_NONVIRTUAL (1 << 1) /* Non-converting (i.e., "explicit") constructors are not tried. This flag indicates that we are not performing direct-initialization. */ -#define LOOKUP_ONLYCONVERTING (1 << 3) +#define LOOKUP_ONLYCONVERTING (1 << 2) #define LOOKUP_IMPLICIT (LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING) /* If a temporary is created, it should be created so that it lives as long as the current variable bindings; otherwise it only lives @@ -4388,20 +4384,20 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T direct-initialization in cases where other parts of the compiler have already generated a temporary, such as reference initialization and the catch parameter. */ -#define DIRECT_BIND (1 << 4) +#define DIRECT_BIND (1 << 3) /* We're performing a user-defined conversion, so more user-defined conversions are not permitted (only built-in conversions). */ -#define LOOKUP_NO_CONVERSION (1 << 5) +#define LOOKUP_NO_CONVERSION (1 << 4) /* The user has explicitly called a destructor. (Therefore, we do not need to check that the object is non-NULL before calling the destructor.) */ -#define LOOKUP_DESTRUCTOR (1 << 6) +#define LOOKUP_DESTRUCTOR (1 << 5) /* Do not permit references to bind to temporaries. */ -#define LOOKUP_NO_TEMP_BIND (1 << 7) +#define LOOKUP_NO_TEMP_BIND (1 << 6) /* Do not accept objects, and possibly namespaces. */ -#define LOOKUP_PREFER_TYPES (1 << 8) +#define LOOKUP_PREFER_TYPES (1 << 7) /* Do not accept objects, and possibly types. */ -#define LOOKUP_PREFER_NAMESPACES (1 << 9) +#define LOOKUP_PREFER_NAMESPACES (1 << 8) /* Accept types or namespaces. */ #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES) /* Return friend declarations and un-declared builtin functions. @@ -4894,7 +4890,9 @@ extern tree build_new_op (location_t, enum tree_ tsubst_flags_t); extern tree build_op_call (tree, VEC(tree,gc) **, tsubst_flags_t); -extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); +extern tree build_op_delete_call (enum tree_code, tree, tree, + bool, tree, tree, + tsubst_flags_t); extern bool can_convert (tree, tree, tsubst_flags_t); extern bool can_convert_arg (tree, tree, tree, int, tsubst_flags_t); @@ -5001,16 +4999,19 @@ extern void adjust_clone_args (tree); extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ -extern tree convert_to_reference (tree, tree, int, int, tree); +extern tree convert_to_reference (tree, tree, int, int, tree, + tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); -extern tree ocp_convert (tree, tree, int, int); -extern tree cp_convert (tree, tree); -extern tree cp_convert_and_check (tree, tree); +extern tree ocp_convert (tree, tree, int, int, + tsubst_flags_t); +extern tree cp_convert (tree, tree, tsubst_flags_t); +extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, impl_conv_void, tsubst_flags_t); -extern tree convert_force (tree, tree, int); +extern tree convert_force (tree, tree, int, + tsubst_flags_t); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); extern tree perform_qualification_conversions (tree, tree); @@ -5901,6 +5902,7 @@ extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); +extern tree cp_perform_integral_promotions (tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); Index: cp/name-lookup.c =================================================================== --- cp/name-lookup.c (revision 188203) +++ cp/name-lookup.c (working copy) @@ -1854,7 +1854,7 @@ identifier_type_value_1 (tree id) return REAL_IDENTIFIER_TYPE_VALUE (id); /* Have to search for it. It must be on the global level, now. Ask lookup_name not to return non-types. */ - id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, LOOKUP_NORMAL); if (id) return TREE_TYPE (id); return NULL_TREE; @@ -4345,7 +4345,7 @@ lookup_qualified_name (tree scope, tree name, bool { struct scope_binding binding = EMPTY_SCOPE_BINDING; - flags |= LOOKUP_COMPLAIN; + flags |= LOOKUP_NORMAL; if (is_type_p) flags |= LOOKUP_PREFER_TYPES; if (qualified_lookup_using_namespace (name, scope, &binding, flags)) @@ -4772,7 +4772,7 @@ lookup_name_real (tree name, int prefer_type, int tree lookup_name_nonclass (tree name) { - return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, LOOKUP_NORMAL); } tree @@ -4781,21 +4781,21 @@ lookup_function_nonclass (tree name, VEC(tree,gc) return lookup_arg_dependent (name, lookup_name_real (name, 0, 1, block_p, 0, - LOOKUP_COMPLAIN), + LOOKUP_NORMAL), args, false); } tree lookup_name (tree name) { - return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, LOOKUP_NORMAL); } tree lookup_name_prefer_type (tree name, int prefer_type) { return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, - 0, LOOKUP_COMPLAIN); + 0, LOOKUP_NORMAL); } /* Look up NAME for type used in elaborated name specifier in ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 11:02 ` Paolo Carlini @ 2012-06-05 14:17 ` Jason Merrill 2012-06-05 16:18 ` Paolo Carlini 2012-06-06 1:00 ` Paolo Carlini 0 siblings, 2 replies; 19+ messages in thread From: Jason Merrill @ 2012-06-05 14:17 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/05/2012 07:00 AM, Paolo Carlini wrote: > (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. This and the similar changes elsewhere seem dangerous; they're adding adding LOOKUP_PROTECT that wasn't there before. Instead, let's replace LOOKUP_COMPLAIN with 0 or some macro defined to 0. I would also keep the LOOKUP_PROTECT macro rather than replace its uses with LOOKUP_NORMAL. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 14:17 ` Jason Merrill @ 2012-06-05 16:18 ` Paolo Carlini 2012-06-05 16:34 ` Jason Merrill 2012-06-06 1:00 ` Paolo Carlini 1 sibling, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-05 16:18 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches Hi, Il giorno 05/giu/2012, alle ore 16:16, Jason Merrill <jason@redhat.com> ha scritto: > On 06/05/2012 07:00 AM, Paolo Carlini wrote: >> (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. > > This and the similar changes elsewhere seem dangerous; they're adding adding LOOKUP_PROTECT that wasn't there before. Instead, let's replace LOOKUP_COMPLAIN with 0 or some macro defined to 0. Indeed, sorry about that, somehow I got confused. > I would also keep the LOOKUP_PROTECT macro rather than replace its uses with LOOKUP_NORMAL. To be sure: NORMAL used to be just PROTECT | COMPLAIN, thus it's just about names, right? You mean, we do away with the NORMAL name, you mean? (indeed I had a moment of esitation about this, when I noticed that the comment preceding now NORMAL is the one which used to preceed PROTECT) > I'll send an updated patch later today. Thanks! Paolo ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 16:18 ` Paolo Carlini @ 2012-06-05 16:34 ` Jason Merrill 2012-06-05 16:50 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-05 16:34 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/05/2012 11:29 AM, Paolo Carlini wrote: > To be sure: NORMAL used to be just PROTECT | COMPLAIN, thus it's just about names, right? Yes. > You mean, we do away with the NORMAL name, you mean? We could, but I think it's fine to have it as an alias for LOOKUP_PROTECT; the LOOKUP_NORMAL name implies that we're doing a normal name lookup, whereas LOOKUP_PROTECT is what that implies. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 16:34 ` Jason Merrill @ 2012-06-05 16:50 ` Paolo Carlini 0 siblings, 0 replies; 19+ messages in thread From: Paolo Carlini @ 2012-06-05 16:50 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches Hi, > We could, but I think it's fine to have it as an alias for LOOKUP_PROTECT; the LOOKUP_NORMAL name implies that we're doing a normal name lookup, whereas LOOKUP_PROTECT is what that implies. Believe it or not, yesterday for a few minutes I had it exactly as an alias. Ok, I'll do that. Paolo ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-05 14:17 ` Jason Merrill 2012-06-05 16:18 ` Paolo Carlini @ 2012-06-06 1:00 ` Paolo Carlini 2012-06-06 2:29 ` Jason Merrill 1 sibling, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-06 1:00 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 740 bytes --] Hi, On 06/05/2012 04:16 PM, Jason Merrill wrote: > On 06/05/2012 07:00 AM, Paolo Carlini wrote: >> (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> LOOKUP_NORMAL. > > This and the similar changes elsewhere seem dangerous; they're adding > adding LOOKUP_PROTECT that wasn't there before. Instead, let's > replace LOOKUP_COMPLAIN with 0 or some macro defined to 0. > > I would also keep the LOOKUP_PROTECT macro rather than replace its > uses with LOOKUP_NORMAL. Thus, as agreed, the below implements both the above (assuming I'm not doing something stupid, I'm again at the end of a pretty long day, like last time ;) Patch passes bootstrap and testing on the usual x86_64-linux. Thanks! Paolo. ////////////////////////// [-- Attachment #2: CL_53567_13 --] [-- Type: text/plain, Size: 2381 bytes --] /cp 2012-06-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * typeck.c (cp_perform_integral_promotions): New, like perform_integral_promotions but also takes a tsubst_flags_t parameter. (pointer_diff): Add tsubst_flags_t parameter. (decay_conversion, cp_default_conversion, cp_build_array_ref, cp_build_binary_op, cp_build_unary_op, build_static_cast_1, build_reinterpret_cast_1, cp_build_modify_expr, convert_for_assignment): Adjust. * optimize.c (build_delete_destructor_body): Adjust. * init.c (expand_virtual_init, expand_default_init, build_new_1, build_new, build_vec_delete_1, build_vec_init, build_delete): Adjust. (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> 0. * class.c (build_base_path): Adjust. * decl.c (compute_array_index_type, finish_destructor_body): Likewise. * method.c (synthesized_method_walk): Adjust flag and complain. * rtti.c (ifnonnull): Add tsubst_flags_t parameter. (build_typeid, build_dynamic_cast_1): Adjust. * except.c (initialize_handler_parm): Likewise. * typeck2.c (process_init_constructor_record): Likewise. * pt.c (tsubst_friend_class): Don't change flags. * semantics.c (finish_goto_stmt, handle_omp_for_class_iterator, finish_static_assert): Likewise. * parser.c (cp_parser_lookup_name): Just pass 0 as flags to lookup_name_real. * call.c (build_op_delete_call): Add tsubst_flags_t parameter. (convert_like_real, convert_arg_to_ellipsis, convert_for_arg_passing): Adjust. (standard_conversion): Adjust LOOKUP_COMPLAIN -> 0. (implicit_conversion): Mask out tf_error. (build_user_type_conversion_1, build_new_op_1, build_over_call): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference, convert_to_reference, cp_convert, cp_convert_and_check, ocp_convert, convert_force): Add tsubst_flags_t parameter. (convert_to_reference, ocp_convert): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. (convert_force): Adjust LOOKUP_COMPLAIN -> 0. * name-lookup.c (identifier_type_value_1, lookup_qualified_name, lookup_name_real, lookup_function_nonclass, lookup_name, lookup_name_prefer_type): Adjust LOOKUP_COMPLAIN -> 0. * cp-tree.h: Adjust prototypes; remove LOOKUP_COMPLAIN. /testsuite 2012-06-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * g++.dg/cpp0x/alias-decl-19.C: New. [-- Attachment #3: patch_53567_13 --] [-- Type: text/plain, Size: 63005 bytes --] Index: testsuite/g++.dg/cpp0x/alias-decl-19.C =================================================================== --- testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) +++ testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) @@ -0,0 +1,31 @@ +// PR c++/53567 +// { dg-do compile { target c++11 } } + +template <unsigned int, bool> struct IntegerType { typedef unsigned type; }; + +template <class EnumT> +using UnderlyingEnumType = typename IntegerType<sizeof(EnumT), (EnumT(-1) > EnumT(0))>::type; + +template <class EnumT, class UnderlyingT = UnderlyingEnumType<EnumT>> +struct EnumMask +{ + constexpr EnumMask(EnumT val) : m_val(val) {} + operator EnumT() { return m_val; } + + EnumT m_val; +}; + +enum class A : unsigned { x }; + +template <class EnumT> +EnumMask<EnumT> operator ~(EnumT lhs) +{ + return EnumT(~unsigned(lhs) & unsigned(EnumT::maskAll)); // { dg-error "not a member" } + +} + +int main() +{ + ~A::x; + return 0; +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 188251) +++ cp/typeck.c (working copy) @@ -52,7 +52,7 @@ static tree rationalize_conditional_expr (enum tre static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (const_tree, const_tree, bool); -static tree pointer_diff (tree, tree, tree); +static tree pointer_diff (tree, tree, tree, tsubst_flags_t); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); @@ -1906,7 +1906,7 @@ decay_conversion (tree exp, tsubst_flags_t complai /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = cp_build_addr_expr (exp, complain); - return cp_convert (ptrtype, adr); + return cp_convert (ptrtype, adr, complain); } /* If a bitfield is used in a context where integral promotion @@ -1950,12 +1950,12 @@ cp_default_conversion (tree exp, tsubst_flags_t co /* Check for target-specific promotions. */ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); if (promoted_type) - exp = cp_convert (promoted_type, exp); + exp = cp_convert (promoted_type, exp, complain); /* Perform the integral promotions first so that bitfield expressions (which may promote to "int", even if the bitfield is declared "unsigned") are promoted correctly. */ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); + exp = cp_perform_integral_promotions (exp, complain); /* Perform the other conversions. */ exp = decay_conversion (exp, complain); @@ -1975,7 +1975,7 @@ default_conversion (tree exp) converted value. */ tree -perform_integral_promotions (tree expr) +cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) { tree type; tree promoted_type; @@ -1995,10 +1995,18 @@ tree return expr; promoted_type = type_promotes_to (type); if (type != promoted_type) - expr = cp_convert (promoted_type, expr); + expr = cp_convert (promoted_type, expr, complain); return expr; } +/* C version. */ + +tree +perform_integral_promotions (tree expr) +{ + return cp_perform_integral_promotions (expr, tf_warning_or_error); +} + /* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */ @@ -2945,7 +2953,7 @@ cp_build_array_ref (location_t loc, tree array, tr does not say that we should. In fact, the natural thing would seem to be to convert IDX to ptrdiff_t; we're performing pointer arithmetic.) */ - idx = perform_integral_promotions (idx); + idx = cp_perform_integral_promotions (idx, complain); /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -3867,7 +3875,8 @@ cp_build_binary_op (location_t location, if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) - return pointer_diff (op0, op1, common_pointer_type (type0, type1)); + return pointer_diff (op0, op1, common_pointer_type (type0, type1), + complain); /* In all other cases except pointer - int, the usual arithmetic rules apply. */ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) @@ -4003,7 +4012,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4031,7 +4040,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4062,7 +4071,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); } break; @@ -4162,12 +4171,12 @@ cp_build_binary_op (location_t location, op0 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e1, e2, complain); - op1 = cp_convert (TREE_TYPE (op0), integer_one_node); + op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); } else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), op1); + op1 = cp_convert (TREE_TYPE (op0), op1, complain); } result_type = TREE_TYPE (op0); } @@ -4190,9 +4199,9 @@ cp_build_binary_op (location_t location, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) - op0 = cp_convert_and_check (type, op0); + op0 = cp_convert_and_check (type, op0, complain); if (!same_type_p (TREE_TYPE (op1), type)) - op1 = cp_convert_and_check (type, op1); + op1 = cp_convert_and_check (type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4456,16 +4465,16 @@ cp_build_binary_op (location_t location, if (first_complex) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != real_type) - op1 = cp_convert_and_check (real_type, op1); + op1 = cp_convert_and_check (real_type, op1, complain); } else { if (TREE_TYPE (op0) != real_type) - op0 = cp_convert_and_check (real_type, op0); + op0 = cp_convert_and_check (real_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); } if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) return error_mark_node; @@ -4550,7 +4559,7 @@ cp_build_binary_op (location_t location, tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return cp_convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val, complain); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -4580,9 +4589,9 @@ cp_build_binary_op (location_t location, if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4594,7 +4603,7 @@ cp_build_binary_op (location_t location, result = build2 (resultcode, build_type, op0, op1); result = fold_if_not_in_template (result); if (final_type != 0) - result = cp_convert (final_type, result); + result = cp_convert (final_type, result, complain); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (op0) @@ -4627,7 +4636,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tre The resulting tree has type int. */ static tree -pointer_diff (tree op0, tree op1, tree ptrtype) +pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) { tree result; tree restype = ptrdiff_type_node; @@ -4637,24 +4646,48 @@ static tree return error_mark_node; if (TREE_CODE (target_type) == VOID_TYPE) - permerror (input_location, "ISO C++ forbids using pointer of type %<void *%> in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer of " + "type %<void *%> in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == FUNCTION_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a function in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a function in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == METHOD_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a method in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a method in subtraction"); + else + return error_mark_node; + } /* First do the subtraction as integers; then drop through to build the divide operator. */ op0 = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (restype, op0), - cp_convert (restype, op1), - tf_warning_or_error); + cp_convert (restype, op0, complain), + cp_convert (restype, op1, complain), + complain); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) - error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); + { + if (complain & tf_error) + error ("invalid use of a pointer to an incomplete type in " + "pointer arithmetic"); + else + return error_mark_node; + } op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) @@ -4662,7 +4695,8 @@ static tree /* Do the division. */ - result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); + result = build2 (EXACT_DIV_EXPR, restype, op0, + cp_convert (restype, op1, complain)); return fold_if_not_in_template (result); } \f @@ -5175,7 +5209,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else { if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus expression is always a rvalue. */ @@ -5200,7 +5234,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); break; case ABS_EXPR: @@ -5358,7 +5392,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else inc = integer_one_node; - inc = cp_convert (argtype, inc); + inc = cp_convert (argtype, inc, complain); /* If 'arg' is an Objective-C PROPERTY_REF expression, then we need to ask Objective-C to build the increment or decrement @@ -6074,7 +6108,7 @@ build_static_cast_1 (tree type, tree expr, bool c_ || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -6417,7 +6451,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo return error_mark_node; } - return cp_convert (type, expr); + return cp_convert (type, expr, complain); } tree @@ -7078,7 +7112,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) - newrhs = cp_convert_and_check (lhstype, newrhs); + newrhs = cp_convert_and_check (lhstype, newrhs, complain); if (modifycode != INIT_EXPR) { @@ -7599,7 +7633,7 @@ convert_for_assignment (tree type, tree rhs, if (!warn_pmf2ptr && TYPE_PTR_P (type) && TYPE_PTRMEMFUNC_P (rhstype)) - rhs = cp_convert (strip_top_quals (type), rhs); + rhs = cp_convert (strip_top_quals (type), rhs, complain); else { if (complain & tf_error) @@ -7723,10 +7757,8 @@ convert_for_assignment (tree type, tree rhs, latter (X(X&)). If using constructor make sure no conversion operator exists, if one does - exist, an ambiguity exists. + exist, an ambiguity exists. */ - If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */ - tree convert_for_initialization (tree exp, tree type, tree rhs, int flags, impl_conv_rhs errtype, tree fndecl, int parmnum, Index: cp/optimize.c =================================================================== --- cp/optimize.c (revision 188251) +++ cp/optimize.c (working copy) @@ -138,7 +138,8 @@ build_delete_destructor_body (tree delete_dtor, tr virtual_size, /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); add_stmt (call_delete); /* Return the address of the object. */ Index: cp/init.c =================================================================== --- cp/init.c (revision 188251) +++ cp/init.c (working copy) @@ -1180,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1250,7 +1250,7 @@ construct_virtual_base (tree vbase, tree arguments exp = convert_to_base_statically (current_class_ref, vbase); expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, - LOOKUP_COMPLAIN, tf_warning_or_error); + 0, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1598,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tr have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -2656,7 +2657,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, size, globally_qualified_p, placement_allocation_fn_p ? alloc_call : NULL_TREE, - alloc_fn)); + alloc_fn, + complain)); if (!cleanup) /* We're done. */; @@ -2815,7 +2817,7 @@ build_new (VEC(tree,gc) **placement, tree type, tr return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -3012,12 +3014,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -3026,7 +3028,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd, virtual_size, use_global_delete & 1, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } body = loop; @@ -3189,14 +3192,14 @@ build_vec_init (tree base, tree maxindex, tree ini return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); base = decay_conversion (base, complain); if (base == error_mark_node) return error_mark_node; - base = cp_convert (ptype, base); + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3665,7 +3668,7 @@ build_delete (tree type, tree addr, special_functi addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3691,7 +3694,7 @@ build_delete (tree type, tree addr, special_functi if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); @@ -3705,7 +3708,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), use_global_delete, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } else { @@ -3744,7 +3748,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; } @@ -3756,7 +3761,8 @@ build_delete (tree type, tree addr, special_functi build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), Index: cp/class.c =================================================================== --- cp/class.c (revision 188251) +++ cp/class.c (working copy) @@ -366,7 +366,7 @@ build_base_path (enum tree_code code, /* Now that we've saved expr, build the real null test. */ if (null_test) { - tree zero = cp_convert (TREE_TYPE (expr), nullptr_node); + tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, expr, zero); } Index: cp/decl.c =================================================================== --- cp/decl.c (revision 188251) +++ cp/decl.c (working copy) @@ -8104,9 +8104,10 @@ compute_array_index_type (tree name, tree size, ts processing_template_decl = 0; itype = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node), - tf_warning_or_error); + cp_convert (ssizetype, size, complain), + cp_convert (ssizetype, integer_one_node, + complain), + complain); itype = fold (itype); processing_template_decl = saved_processing_template_decl; @@ -13290,11 +13291,12 @@ finish_destructor_body (void) an implicit definition), non-placement operator delete shall be looked up in the scope of the destructor's class and if found shall be accessible and unambiguous. */ - exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr, - virtual_size, - /*global_p=*/false, - /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, + virtual_size, + /*global_p=*/false, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); if_stmt = begin_if_stmt (); finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node, Index: cp/method.c =================================================================== --- cp/method.c (revision 188251) +++ cp/method.c (working copy) @@ -1228,17 +1228,10 @@ synthesized_method_walk (tree ctype, special_funct scope = push_scope (ctype); - if (diag) - { - flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_warning_or_error; - } - else - { - flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_none; - } + flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; + complain = diag ? tf_warning_or_error : tf_none; + if (const_p) quals = TYPE_QUAL_CONST; else Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 188251) +++ cp/rtti.c (working copy) @@ -99,7 +99,7 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree ifnonnull (tree, tree); +static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); @@ -336,7 +336,8 @@ build_typeid (tree exp) This is an lvalue use of expr then. */ exp = mark_lvalue_use (exp); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), + tf_warning_or_error); } exp = get_tinfo_decl_dynamic (exp); @@ -498,12 +499,13 @@ get_typeid (tree type) RESULT, it must have previously had a save_expr applied to it. */ static tree -ifnonnull (tree test, tree result) +ifnonnull (tree test, tree result, tsubst_flags_t complain) { return build3 (COND_EXPR, TREE_TYPE (result), build2 (EQ_EXPR, boolean_type_node, test, - cp_convert (TREE_TYPE (test), nullptr_node)), - cp_convert (TREE_TYPE (result), nullptr_node), + cp_convert (TREE_TYPE (test), nullptr_node, + complain)), + cp_convert (TREE_TYPE (result), nullptr_node, complain), result); } @@ -596,7 +598,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst /* Apply trivial conversion T -> T& for dereferenced ptrs. */ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, complain); } /* The dynamic_cast operator shall not cast away constness. */ @@ -644,7 +646,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst expr1 = build_headof (expr); if (TREE_TYPE (expr1) != type) expr1 = build1 (NOP_EXPR, type, expr1); - return ifnonnull (expr, expr1); + return ifnonnull (expr, expr1, complain); } else { @@ -752,12 +754,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst neq = cp_truthvalue_conversion (result); return cp_convert (type, build3 (COND_EXPR, TREE_TYPE (result), - neq, result, bad)); + neq, result, bad), complain); } /* Now back to the type we want from a void*. */ - result = cp_convert (type, result); - return ifnonnull (expr, result); + result = cp_convert (type, result, complain); + return ifnonnull (expr, result, complain); } } else Index: cp/except.c =================================================================== --- cp/except.c (revision 188251) +++ cp/except.c (working copy) @@ -424,7 +424,8 @@ initialize_handler_parm (tree decl, tree exp) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); - exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); init = convert_from_reference (exp); @@ -435,7 +436,8 @@ initialize_handler_parm (tree decl, tree exp) /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 188251) +++ cp/typeck2.c (working copy) @@ -1264,7 +1264,7 @@ process_init_constructor_record (tree type, tree i /* If this is a bitfield, now convert to the lowered type. */ if (type != TREE_TYPE (field)) - next = cp_convert_and_check (TREE_TYPE (field), next); + next = cp_convert_and_check (TREE_TYPE (field), next, complain); flags |= picflag_from_initializer (next); CONSTRUCTOR_APPEND_ELT (v, field, next); } Index: cp/pt.c =================================================================== --- cp/pt.c (revision 188251) +++ cp/pt.c (working copy) @@ -8474,8 +8474,7 @@ tsubst_friend_class (tree friend_tmpl, tree args) both F templates are the same. */ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0, - /*block_p=*/true, 0, - LOOKUP_COMPLAIN | LOOKUP_HIDDEN); + /*block_p=*/true, 0, LOOKUP_HIDDEN); /* But, if we don't find one, it might be because we're in a situation like this: Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 188251) +++ cp/semantics.c (working copy) @@ -564,7 +564,8 @@ finish_goto_stmt (tree destination) destination = mark_rvalue_use (destination); if (!processing_template_decl) { - destination = cp_convert (ptr_type_node, destination); + destination = cp_convert (ptr_type_node, destination, + tf_warning_or_error); if (error_operand_p (destination)) return NULL_TREE; } @@ -4526,7 +4527,8 @@ handle_omp_for_class_iterator (int i, location_t l if (error_operand_p (iter_incr)) return true; incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, + tf_warning_or_error); if (TREE_CODE (rhs) == MINUS_EXPR) { incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); @@ -4581,7 +4583,7 @@ handle_omp_for_class_iterator (int i, location_t l return true; } - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == iter) @@ -5130,7 +5132,7 @@ finish_static_assert (tree condition, tree message /* Fold the expression and convert it to a boolean value. */ condition = fold_non_dependent_expr (condition); - condition = cp_convert (boolean_type_node, condition); + condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) Index: cp/parser.c =================================================================== --- cp/parser.c (revision 188251) +++ cp/parser.c (working copy) @@ -20317,13 +20317,9 @@ cp_parser_lookup_name (cp_parser *parser, tree nam tree *ambiguous_decls, location_t name_location) { - int flags = 0; tree decl; tree object_type = parser->context->object_type; - if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - flags |= LOOKUP_COMPLAIN; - /* Assume that the lookup will be unambiguous. */ if (ambiguous_decls) *ambiguous_decls = NULL_TREE; @@ -20495,7 +20491,7 @@ cp_parser_lookup_name (cp_parser *parser, tree nam /* Look it up in the enclosing context, too. */ decl = lookup_name_real (name, tag_type != none_type, /*nonclass=*/0, - /*block_p=*/true, is_namespace, flags); + /*block_p=*/true, is_namespace, 0); parser->object_scope = object_type; parser->qualifying_scope = NULL_TREE; if (object_decl) @@ -20505,7 +20501,7 @@ cp_parser_lookup_name (cp_parser *parser, tree nam { decl = lookup_name_real (name, tag_type != none_type, /*nonclass=*/0, - /*block_p=*/true, is_namespace, flags); + /*block_p=*/true, is_namespace, 0); parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; } Index: cp/call.c =================================================================== --- cp/call.c (revision 188251) +++ cp/call.c (working copy) @@ -1695,6 +1695,8 @@ implicit_conversion (tree to, tree from, tree expr |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); + complain &= ~tf_error; + if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, c_cast_p, flags, complain); else @@ -3607,8 +3609,7 @@ build_user_type_conversion_1 (tree totype, tree ex cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) - && (complain & tf_error)) + if (complain & tf_error) { error ("conversion from %qT to %qT is ambiguous", fromtype, totype); @@ -5098,7 +5099,7 @@ build_new_op_1 (location_t loc, enum tree_code cod distinguish between prefix and postfix ++ and operator++() was used for both, so we allow this with -fpermissive. */ - if (flags & LOOKUP_COMPLAIN) + else { const char *msg = (flag_permissive) ? G_("no %<%D(int)%> declared for postfix %qs," @@ -5127,7 +5128,7 @@ build_new_op_1 (location_t loc, enum tree_code cod break; default: - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { /* If one of the arguments of the operator represents an invalid use of member function pointer, try to report @@ -5153,7 +5154,7 @@ build_new_op_1 (location_t loc, enum tree_code cod cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { op_error (loc, code, code2, arg1, arg2, arg3, TRUE); print_z_candidates (loc, candidates); @@ -5379,7 +5380,7 @@ non_placement_deallocation_fn_p (tree t) tree build_op_delete_call (enum tree_code code, tree addr, tree size, bool global_p, tree placement, - tree alloc_fn) + tree alloc_fn, tsubst_flags_t complain) { tree fn = NULL_TREE; tree fns, fnname, type, t; @@ -5413,7 +5414,7 @@ build_op_delete_call (enum tree_code code, tree ad fns = lookup_name_nonclass (fnname); /* Strip const and volatile from addr. */ - addr = cp_convert (ptr_type_node, addr); + addr = cp_convert (ptr_type_node, addr, complain); if (placement) { @@ -5452,8 +5453,13 @@ build_op_delete_call (enum tree_code code, tree ad && FUNCTION_ARG_CHAIN (elt) == void_list_node) goto ok; } - permerror (0, "non-placement deallocation function %q+D", fn); - permerror (input_location, "selected for placement delete"); + if (complain & tf_error) + { + permerror (0, "non-placement deallocation function %q+D", fn); + permerror (input_location, "selected for placement delete"); + } + else + return error_mark_node; ok:; } } @@ -5518,7 +5524,7 @@ build_op_delete_call (enum tree_code code, tree ad VEC_quick_push (tree, args, addr); if (FUNCTION_ARG_CHAIN (fn) != void_list_node) VEC_quick_push (tree, args, size); - ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error); + ret = cp_build_function_call_vec (fn, &args, complain); VEC_free (tree, gc, args); return ret; } @@ -5531,14 +5537,16 @@ build_op_delete_call (enum tree_code code, tree ad be freed. */ if (alloc_fn) { - if (!placement) + if ((complain & tf_warning) + && !placement) warning (0, "no corresponding deallocation function for %qD", alloc_fn); return NULL_TREE; } - error ("no suitable %<operator %s%> for %qT", - operator_name_info[(int)code].name, type); + if (complain & tf_error) + error ("no suitable %<operator %s%> for %qT", + operator_name_info[(int)code].name, type); return error_mark_node; } @@ -5685,9 +5693,10 @@ convert_like_real (conversion *convs, tree expr, t complain); if (convs->kind == ck_ref_bind) return convert_to_reference (totype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, + complain); else - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } else if (t->kind == ck_user || !t->bad_p) { @@ -5712,7 +5721,7 @@ convert_like_real (conversion *convs, tree expr, t permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } if (issue_conversion_warnings && (complain & tf_warning)) @@ -5851,7 +5860,7 @@ convert_like_real (conversion *convs, tree expr, t /* Take the address explicitly rather than via decay_conversion to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); - array = cp_convert (build_pointer_type (elttype), array); + array = cp_convert (build_pointer_type (elttype), array, complain); /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6017,7 +6026,7 @@ convert_like_real (conversion *convs, tree expr, t reference. This will adjust the pointer if a derived to base conversion is being performed. */ expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), - expr); + expr, complain); /* Convert the pointer to the desired reference type. */ return build_nop (ref_type, expr); } @@ -6099,9 +6108,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t if (complain & tf_warning) warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " "integral type in a future version of GCC", arg_type); - arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg); + arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); } - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); } arg = require_complete_type (arg); @@ -6336,7 +6345,7 @@ convert_for_arg_passing (tree type, tree val, tsub && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - val = perform_integral_promotions (val); + val = cp_perform_integral_promotions (val, complain); if ((complain & tf_warning) && warn_suggest_attribute_format) { @@ -6487,7 +6496,7 @@ build_over_call (struct z_candidate *cand, int fla if (flags & LOOKUP_SPECULATIVE) { if (!speculative_access_check (cand->access_path, access_fn, fn, - !!(flags & LOOKUP_COMPLAIN))) + complain & tf_error)) return error_mark_node; } else @@ -6500,13 +6509,13 @@ build_over_call (struct z_candidate *cand, int fla { if (DECL_DELETED_FN (fn)) { - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) mark_used (fn); return error_mark_node; } if (cand->viable == 1) return fn; - else if (!(flags & LOOKUP_COMPLAIN)) + else if (!(complain & tf_error)) /* Reject bad conversions now. */ return error_mark_node; /* else continue to get conversion error. */ Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 188251) +++ cp/cvt.c (working copy) @@ -38,10 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree); -static tree convert_to_pointer_force (tree, tree); +static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); +static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); -static tree build_up_reference (tree, tree, int, tree); +static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); static void warn_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- @@ -74,7 +74,7 @@ static void warn_ref_binding (location_t, tree, tr else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr) +cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -89,15 +89,17 @@ static tree intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { - error_at (loc, "can%'t convert from incomplete type %qT to %qT", - intype, type); + if (complain & tf_error) + error_at (loc, "can%'t convert from incomplete type %qT to %qT", + intype, type); return error_mark_node; } rval = build_type_conversion (type, expr); if (rval) { - if (rval == error_mark_node) + if ((complain & tf_error) + && rval == error_mark_node) error_at (loc, "conversion of %qE from %qT to %qT is ambiguous", expr, intype, type); return rval; @@ -111,7 +113,7 @@ static tree { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) - return convert_member_func_to_ptr (type, expr, tf_warning_or_error); + return convert_member_func_to_ptr (type, expr, complain); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); @@ -159,8 +161,7 @@ static tree if (binfo || same_p) { if (binfo) - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); /* Add any qualifier conversions. */ return build_nop (type, expr); } @@ -168,8 +169,9 @@ static tree if (TYPE_PTRMEMFUNC_P (type)) { - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -178,20 +180,20 @@ static tree else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) - return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr)); + return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), + complain); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); return get_member_function_from_ptrfunc (&object, TREE_OPERAND (expr, 1), - tf_warning_or_error); + complain); } } error_at (loc, "cannot convert %qE from type %qT to type %qT", @@ -201,14 +203,15 @@ static tree if (null_ptr_cst_p (expr)) { - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !NULLPTR_TYPE_P (TREE_TYPE (expr))) warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); if (TYPE_PTRDATAMEM_P (type)) { @@ -223,7 +226,8 @@ static tree } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { - error_at (loc, "invalid conversion from %qT to %qT", intype, type); + if (complain & tf_error) + error_at (loc, "invalid conversion from %qT to %qT", intype, type); return error_mark_node; } @@ -231,7 +235,8 @@ static tree { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width as a pointer. */ @@ -242,10 +247,11 @@ static tree } if (type_unknown_p (expr)) - return instantiate_type (type, expr, tf_warning_or_error); + return instantiate_type (type, expr, complain); - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -254,7 +260,7 @@ static tree (such as conversion from sub-type to private super-type). */ static tree -convert_to_pointer_force (tree type, tree expr) +convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); @@ -284,8 +290,7 @@ static tree return error_mark_node; if (binfo) { - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); if (expr == error_mark_node) return error_mark_node; /* Add any qualifier conversions. */ @@ -297,7 +302,7 @@ static tree } } - return cp_convert_to_pointer (type, expr); + return cp_convert_to_pointer (type, expr, complain); } /* We are passing something to a function which requires a reference. @@ -309,7 +314,8 @@ static tree If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (tree type, tree arg, int flags, tree decl) +build_up_reference (tree type, tree arg, int flags, tree decl, + tsubst_flags_t complain) { tree rval; tree argtype = TREE_TYPE (arg); @@ -351,12 +357,12 @@ static tree return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - rval = build_base_path (PLUS_EXPR, rval, binfo, 1, - tf_warning_or_error); + rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain); } else rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); + = convert_to_pointer_force (build_pointer_type (target_type), + rval, complain); return build_nop (type, rval); } @@ -403,15 +409,13 @@ warn_ref_binding (location_t loc, tree reftype, tr tree convert_to_reference (tree reftype, tree expr, int convtype, - int flags, tree decl) + int flags, tree decl, tsubst_flags_t complain) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN) - ? tf_warning_or_error : tf_none); location_t loc = EXPR_LOC_OR_HERE (expr); if (TREE_CODE (type) == FUNCTION_TYPE @@ -452,21 +456,26 @@ convert_to_reference (tree reftype, tree expr, int if (((convtype & CONV_STATIC) && can_convert (intype, type, complain)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { - if (flags & LOOKUP_COMPLAIN) - { - tree ttl = TREE_TYPE (reftype); - tree ttr = lvalue_type (expr); + { + tree ttl = TREE_TYPE (reftype); + tree ttr = lvalue_type (expr); - if (! real_lvalue_p (expr)) - warn_ref_binding (loc, reftype, intype, decl); + if ((complain & tf_warning) + && ! real_lvalue_p (expr)) + warn_ref_binding (loc, reftype, intype, decl); - if (! (convtype & CONV_CONST) - && !at_least_as_qualified_p (ttl, ttr)) - permerror (loc, "conversion from %qT to %qT discards qualifiers", - ttr, reftype); - } + if (! (convtype & CONV_CONST) + && !at_least_as_qualified_p (ttl, ttr)) + { + if (complain & tf_error) + permerror (loc, "conversion from %qT to %qT discards qualifiers", + ttr, reftype); + else + return error_mark_node; + } + } - return build_up_reference (reftype, expr, flags, decl); + return build_up_reference (reftype, expr, flags, decl, complain); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -477,28 +486,29 @@ convert_to_reference (tree reftype, tree expr, int /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (TREE_CODE (intype) == POINTER_TYPE + if ((complain & tf_warning) + && TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = cp_build_addr_expr (expr, tf_warning_or_error); + rval = cp_build_addr_expr (expr, complain); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), - rval, 0); + rval, 0, complain); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, - ICR_CONVERTING, 0, 0, - tf_warning_or_error); + ICR_CONVERTING, 0, 0, complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - warn_ref_binding (loc, reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags, decl); + if (complain & tf_warning) + warn_ref_binding (loc, reftype, intype, decl); + rval = build_up_reference (reftype, rval, flags, decl, complain); } if (rval) @@ -507,7 +517,7 @@ convert_to_reference (tree reftype, tree expr, int return rval; } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; @@ -595,9 +605,9 @@ cp_fold_convert (tree type, tree expr) /* C++ conversions, preference to static cast conversions. */ tree -cp_convert (tree type, tree expr) +cp_convert (tree type, tree expr, tsubst_flags_t complain) { - return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain); } /* C++ equivalent of convert_and_check but using cp_convert as the @@ -608,16 +618,17 @@ tree i.e. because of language rules and not because of an explicit cast. */ tree -cp_convert_and_check (tree type, tree expr) +cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree result; if (TREE_TYPE (expr) == type) return expr; - result = cp_convert (type, expr); + result = cp_convert (type, expr, complain); - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !TREE_OVERFLOW_P (expr) && result != error_mark_node) warnings_for_convert_and_check (type, expr, result); @@ -630,7 +641,8 @@ tree FLAGS indicates how we should behave. */ tree -ocp_convert (tree type, tree expr, int convtype, int flags) +ocp_convert (tree type, tree expr, int convtype, int flags, + tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -647,7 +659,8 @@ tree if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { - error (invalid_conv_diag); + if (complain & tf_error) + error (invalid_conv_diag); return error_mark_node; } @@ -696,7 +709,7 @@ tree if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, ICV_CAST, tf_warning_or_error); + e = convert_to_void (e, ICV_CAST, complain); return e; } @@ -714,9 +727,14 @@ tree && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { - if (flags & LOOKUP_COMPLAIN) - permerror (loc, "conversion from %q#T to %q#T", intype, type); - if (!flag_permissive) + if (complain & tf_error) + { + permerror (loc, "conversion from %q#T to %q#T", + intype, type); + if (!flag_permissive) + return error_mark_node; + } + else return error_mark_node; } @@ -727,7 +745,8 @@ tree the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ - if (TREE_CODE (expr) == INTEGER_CST + if ((complain & tf_warning) + && TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " @@ -740,7 +759,7 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "%q#T used where a %qT was expected", intype, type); return error_mark_node; } @@ -748,8 +767,10 @@ tree { if (TREE_CODE (intype) == VOID_TYPE) { - error_at (loc, "could not convert %qE from %<void%> to %<bool%>", - expr); + if (complain & tf_error) + error_at (loc, + "could not convert %qE from %<void%> to %<bool%>", + expr); return error_mark_node; } @@ -768,7 +789,7 @@ tree if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); @@ -778,8 +799,9 @@ tree ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a %qT was expected", in_vtype, type); + if (complain & tf_error) + error_at (loc, "%q#T used where a %qT was expected", + in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); @@ -792,10 +814,10 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - else - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a floating point value was expected", - TREE_TYPE (e)); + else if (complain & tf_error) + error_at (loc, + "%q#T used where a floating point value was expected", + TREE_TYPE (e)); } if (code == REAL_TYPE) return fold_if_not_in_template (convert_to_real (type, e)); @@ -826,33 +848,31 @@ tree return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) - ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + ctor = perform_implicit_conversion (type, ctor, complain); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ - ctor = build_user_type_conversion (type, ctor, flags, - tf_warning_or_error); + ctor = build_user_type_conversion (type, ctor, flags, complain); else { VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, &ctor_vec, - type, flags, - tf_warning_or_error); + type, flags, complain); release_tree_vector (ctor_vec); } if (ctor) - return build_cplus_new (type, ctor, tf_warning_or_error); + return build_cplus_new (type, ctor, complain); } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) { /* If the conversion failed and expr was an invalid use of pointer to member function, try to report a meaningful error. */ - if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (expr, complain)) /* We displayed the error message. */; else error_at (loc, "conversion from %qT to non-scalar type %qT requested", @@ -1416,7 +1436,8 @@ convert (tree type, tree expr) return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + tf_warning_or_error); } /* Like cp_convert, except permit conversions to take place which @@ -1424,18 +1445,19 @@ convert (tree type, tree expr) (such as conversion from sub-type to private super-type). */ tree -convert_force (tree type, tree expr, int convtype) +convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) return (fold_if_not_in_template - (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, - NULL_TREE))); + (convert_to_reference (type, e, CONV_C_CAST, 0, + NULL_TREE, complain))); if (code == POINTER_TYPE) - return fold_if_not_in_template (convert_to_pointer_force (type, e)); + return fold_if_not_in_template (convert_to_pointer_force (type, e, + complain)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR @@ -1446,9 +1468,9 @@ tree && TYPE_PTRMEMFUNC_P (type)) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, - /*c_cast_p=*/1, tf_warning_or_error); + /*c_cast_p=*/1, complain); - return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain); } /* Convert an aggregate EXPR to type XTYPE. If a conversion Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 188251) +++ cp/cp-tree.h (working copy) @@ -4371,16 +4371,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T behaviors relevant to them. */ /* Check for access violations. */ #define LOOKUP_PROTECT (1 << 0) -/* Complain if no suitable member function matching the arguments is - found. */ -#define LOOKUP_COMPLAIN (1 << 1) -#define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN) +#define LOOKUP_NORMAL (LOOKUP_PROTECT) /* Even if the function found by lookup is a virtual function, it should be called directly. */ -#define LOOKUP_NONVIRTUAL (1 << 2) +#define LOOKUP_NONVIRTUAL (1 << 1) /* Non-converting (i.e., "explicit") constructors are not tried. This flag indicates that we are not performing direct-initialization. */ -#define LOOKUP_ONLYCONVERTING (1 << 3) +#define LOOKUP_ONLYCONVERTING (1 << 2) #define LOOKUP_IMPLICIT (LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING) /* If a temporary is created, it should be created so that it lives as long as the current variable bindings; otherwise it only lives @@ -4388,20 +4385,20 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T direct-initialization in cases where other parts of the compiler have already generated a temporary, such as reference initialization and the catch parameter. */ -#define DIRECT_BIND (1 << 4) +#define DIRECT_BIND (1 << 3) /* We're performing a user-defined conversion, so more user-defined conversions are not permitted (only built-in conversions). */ -#define LOOKUP_NO_CONVERSION (1 << 5) +#define LOOKUP_NO_CONVERSION (1 << 4) /* The user has explicitly called a destructor. (Therefore, we do not need to check that the object is non-NULL before calling the destructor.) */ -#define LOOKUP_DESTRUCTOR (1 << 6) +#define LOOKUP_DESTRUCTOR (1 << 5) /* Do not permit references to bind to temporaries. */ -#define LOOKUP_NO_TEMP_BIND (1 << 7) +#define LOOKUP_NO_TEMP_BIND (1 << 6) /* Do not accept objects, and possibly namespaces. */ -#define LOOKUP_PREFER_TYPES (1 << 8) +#define LOOKUP_PREFER_TYPES (1 << 7) /* Do not accept objects, and possibly types. */ -#define LOOKUP_PREFER_NAMESPACES (1 << 9) +#define LOOKUP_PREFER_NAMESPACES (1 << 8) /* Accept types or namespaces. */ #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES) /* Return friend declarations and un-declared builtin functions. @@ -4894,7 +4891,9 @@ extern tree build_new_op (location_t, enum tree_ tsubst_flags_t); extern tree build_op_call (tree, VEC(tree,gc) **, tsubst_flags_t); -extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); +extern tree build_op_delete_call (enum tree_code, tree, tree, + bool, tree, tree, + tsubst_flags_t); extern bool can_convert (tree, tree, tsubst_flags_t); extern bool can_convert_arg (tree, tree, tree, int, tsubst_flags_t); @@ -5001,16 +5000,19 @@ extern void adjust_clone_args (tree); extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ -extern tree convert_to_reference (tree, tree, int, int, tree); +extern tree convert_to_reference (tree, tree, int, int, tree, + tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); -extern tree ocp_convert (tree, tree, int, int); -extern tree cp_convert (tree, tree); -extern tree cp_convert_and_check (tree, tree); +extern tree ocp_convert (tree, tree, int, int, + tsubst_flags_t); +extern tree cp_convert (tree, tree, tsubst_flags_t); +extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, impl_conv_void, tsubst_flags_t); -extern tree convert_force (tree, tree, int); +extern tree convert_force (tree, tree, int, + tsubst_flags_t); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); extern tree perform_qualification_conversions (tree, tree); @@ -5901,6 +5903,7 @@ extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); +extern tree cp_perform_integral_promotions (tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); Index: cp/name-lookup.c =================================================================== --- cp/name-lookup.c (revision 188251) +++ cp/name-lookup.c (working copy) @@ -1854,7 +1854,7 @@ identifier_type_value_1 (tree id) return REAL_IDENTIFIER_TYPE_VALUE (id); /* Have to search for it. It must be on the global level, now. Ask lookup_name not to return non-types. */ - id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, 0); if (id) return TREE_TYPE (id); return NULL_TREE; @@ -4345,7 +4345,6 @@ lookup_qualified_name (tree scope, tree name, bool { struct scope_binding binding = EMPTY_SCOPE_BINDING; - flags |= LOOKUP_COMPLAIN; if (is_type_p) flags |= LOOKUP_PREFER_TYPES; if (qualified_lookup_using_namespace (name, scope, &binding, flags)) @@ -4772,7 +4771,7 @@ lookup_name_real (tree name, int prefer_type, int tree lookup_name_nonclass (tree name) { - return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, 0); } tree @@ -4780,22 +4779,20 @@ lookup_function_nonclass (tree name, VEC(tree,gc) { return lookup_arg_dependent (name, - lookup_name_real (name, 0, 1, block_p, 0, - LOOKUP_COMPLAIN), + lookup_name_real (name, 0, 1, block_p, 0, 0), args, false); } tree lookup_name (tree name) { - return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, 0); } tree lookup_name_prefer_type (tree name, int prefer_type) { - return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, - 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, 0, 0); } /* Look up NAME for type used in elaborated name specifier in ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 1:00 ` Paolo Carlini @ 2012-06-06 2:29 ` Jason Merrill 2012-06-06 9:33 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-06 2:29 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/05/2012 08:23 PM, Paolo Carlini wrote: > @@ -1695,6 +1695,8 @@ implicit_conversion (tree to, tree from, tree expr > |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE > |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); > > + complain&= ~tf_error; I don't think we want warnings from implicit_conversion, either. > - if (flags & LOOKUP_COMPLAIN) > - permerror (loc, "conversion from %q#T to %q#T", intype, type); > - if (!flag_permissive) > + if (complain & tf_error) > + { > + permerror (loc, "conversion from %q#T to %q#T", > + intype, type); > + if (!flag_permissive) > + return error_mark_node; I don't think we need the last two lines anymore, we can use the usual pattern of return error if sfinae, permerror and continue otherwise. BTW, I'm somewhat surprised that dropping LOOKUP_COMPLAIN from all the lookup_* functions works fine, but looking through the code myself I don't see anything that was using the flag. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 2:29 ` Jason Merrill @ 2012-06-06 9:33 ` Paolo Carlini 2012-06-06 10:23 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-06 9:33 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches Hi, On 06/06/2012 03:57 AM, Jason Merrill wrote: > On 06/05/2012 08:23 PM, Paolo Carlini wrote: >> @@ -1695,6 +1695,8 @@ implicit_conversion (tree to, tree from, tree expr >> |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE >> |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); >> >> + complain&= ~tf_error; > > I don't think we want warnings from implicit_conversion, either. I thought we already somewhat discussed this issue (when I said that passing tf_warning instead of tf_none could work better, remember?), but now I see that I kept a lot of it for myself . If I do something like complain&= ~(tf_warning|tf_error); then we regress on, eg, g++.old-deja/g++.benjamin/16077.C, that is, we don't produce any warnings anymore. > >> - if (flags & LOOKUP_COMPLAIN) >> - permerror (loc, "conversion from %q#T to %q#T", intype, type); >> - if (!flag_permissive) >> + if (complain & tf_error) >> + { >> + permerror (loc, "conversion from %q#T to %q#T", >> + intype, type); >> + if (!flag_permissive) >> + return error_mark_node; > > I don't think we need the last two lines anymore, we can use the usual > pattern of return error if sfinae, permerror and continue otherwise. Sure. Thanks, Paolo. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 9:33 ` Paolo Carlini @ 2012-06-06 10:23 ` Paolo Carlini 2012-06-06 16:17 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-06 10:23 UTC (permalink / raw) To: gcc-patches; +Cc: Jason Merrill Hi again, some additional details: On 06/06/2012 11:20 AM, Paolo Carlini wrote: > Hi, > > On 06/06/2012 03:57 AM, Jason Merrill wrote: >> On 06/05/2012 08:23 PM, Paolo Carlini wrote: >>> @@ -1695,6 +1695,8 @@ implicit_conversion (tree to, tree from, tree >>> expr >>> |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE >>> |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); >>> >>> + complain&= ~tf_error; >> >> I don't think we want warnings from implicit_conversion, either. > I thought we already somewhat discussed this issue (when I said that > passing tf_warning instead of tf_none could work better, remember?), > but now I see that I kept a lot of it for myself . If I do something like > > complain&= ~(tf_warning|tf_error); > > then we regress on, eg, g++.old-deja/g++.benjamin/16077.C, that is, we > don't produce any warnings anymore. The warning belongs to joust, called by tourney, called by build_user_type_conversion_1, called by implicit_conversion. When a couple of days ago I mentioned my quick tests with hackish changes, I had just noticed that the testsuite was Ok if only in implicit_conversion I allowed tf_warning to be passed to reference_binding and build_user_type_conversion_1. Then, later on, I thought that before these changes for 53567 nothing was preventing warnings to be emitted, thus maybe we only wanted to gate away hard errors, like before we gated away hard errors with the big flags &= line which wasn't including LOOKUP_COMPLAIN, and leave warnings (or any other tsubst_flags for that matter) alone in the whole implicit_conversion. I see now, I didn't remember this detail, that besides Benjamin's, the only other testsuite regression with ~(tf_warning|tf_error) is: g++.old-deja/g++.other/overcnv2.C which is again about the same warning in joust. Paolo. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 10:23 ` Paolo Carlini @ 2012-06-06 16:17 ` Jason Merrill 2012-06-06 17:12 ` Paolo Carlini 0 siblings, 1 reply; 19+ messages in thread From: Jason Merrill @ 2012-06-06 16:17 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches On 06/06/2012 05:45 AM, Paolo Carlini wrote: > The warning belongs to joust, called by tourney, called by > build_user_type_conversion_1, called by implicit_conversion. Hmm. We really ought not to issue that warning until we know that we've committed to that conversion. But I guess that doesn't need to happen in this patch, just add a FIXME comment to the ~tf_error line. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 16:17 ` Jason Merrill @ 2012-06-06 17:12 ` Paolo Carlini 2012-06-06 18:48 ` Jason Merrill 0 siblings, 1 reply; 19+ messages in thread From: Paolo Carlini @ 2012-06-06 17:12 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches [-- Attachment #1: Type: text/plain, Size: 1059 bytes --] Hi, On 06/06/2012 06:12 PM, Jason Merrill wrote: > On 06/06/2012 05:45 AM, Paolo Carlini wrote: >> The warning belongs to joust, called by tourney, called by >> build_user_type_conversion_1, called by implicit_conversion. > > Hmm. We really ought not to issue that warning until we know that > we've committed to that conversion. But I guess that doesn't need to > happen in this patch, just add a FIXME comment to the ~tf_error line. I see, I just learned something more about those conversions, eh And, I must admit, without LOOKUP_COMPLAIN all these bits of code become much neater, I even hope that implementing the access checking under SFINAE thing will become simpler (a while ago I started on it, and got some important cases working but also quite a few interesting special cases handled in weird ways: soon I will be sending over something concrete) Anyway, I bootstrapped and I'm finishing testing (in v3 now) the below, which just adds your two last indications about flag_permissive and the FIXME. Thanks, Paolo. ///////////////// [-- Attachment #2: CL_53567_14 --] [-- Type: text/plain, Size: 2394 bytes --] /cp 2012-06-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * typeck.c (cp_perform_integral_promotions): New, like perform_integral_promotions but also takes a tsubst_flags_t parameter. (pointer_diff): Add tsubst_flags_t parameter. (decay_conversion, cp_default_conversion, cp_build_array_ref, cp_build_binary_op, cp_build_unary_op, build_static_cast_1, build_reinterpret_cast_1, cp_build_modify_expr, convert_for_assignment): Adjust. * optimize.c (build_delete_destructor_body): Adjust. * init.c (expand_virtual_init, expand_default_init, build_new_1, build_new, build_vec_delete_1, build_vec_init, build_delete): Adjust. (construct_virtual_base): Adjust LOOKUP_COMPLAIN -> 0. * class.c (build_base_path): Adjust. * decl.c (compute_array_index_type, finish_destructor_body): Likewise. * method.c (synthesized_method_walk): Adjust flag and complain. * rtti.c (ifnonnull): Add tsubst_flags_t parameter. (build_typeid, build_dynamic_cast_1): Adjust. * except.c (initialize_handler_parm): Likewise. * typeck2.c (process_init_constructor_record): Likewise. * pt.c (tsubst_friend_class): Don't change flags. * semantics.c (finish_goto_stmt, handle_omp_for_class_iterator, finish_static_assert): Likewise. * parser.c (cp_parser_lookup_name): Just pass 0 as flags to lookup_name_real. * call.c (build_op_delete_call): Add tsubst_flags_t parameter. (convert_like_real, convert_arg_to_ellipsis, convert_for_arg_passing): Adjust. (standard_conversion): Adjust LOOKUP_COMPLAIN -> 0. (implicit_conversion): Mask out tf_error with a FIXME. (build_user_type_conversion_1, build_new_op_1, build_over_call): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. * cvt.c (cp_convert_to_pointer, convert_to_pointer_force, build_up_reference, convert_to_reference, cp_convert, cp_convert_and_check, ocp_convert, convert_force): Add tsubst_flags_t parameter. (convert_to_reference, ocp_convert): Use complain & tf_error instead of flags & LOOKUP_COMPLAIN. (convert_force): Adjust LOOKUP_COMPLAIN -> 0. * name-lookup.c (identifier_type_value_1, lookup_qualified_name, lookup_name_real, lookup_function_nonclass, lookup_name, lookup_name_prefer_type): Adjust LOOKUP_COMPLAIN -> 0. * cp-tree.h: Adjust prototypes; remove LOOKUP_COMPLAIN. /testsuite 2012-06-06 Paolo Carlini <paolo.carlini@oracle.com> PR c++/53567 * g++.dg/cpp0x/alias-decl-19.C: New. [-- Attachment #3: patch_53567_14 --] [-- Type: text/plain, Size: 63166 bytes --] Index: testsuite/g++.dg/cpp0x/alias-decl-19.C =================================================================== --- testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) +++ testsuite/g++.dg/cpp0x/alias-decl-19.C (revision 0) @@ -0,0 +1,31 @@ +// PR c++/53567 +// { dg-do compile { target c++11 } } + +template <unsigned int, bool> struct IntegerType { typedef unsigned type; }; + +template <class EnumT> +using UnderlyingEnumType = typename IntegerType<sizeof(EnumT), (EnumT(-1) > EnumT(0))>::type; + +template <class EnumT, class UnderlyingT = UnderlyingEnumType<EnumT>> +struct EnumMask +{ + constexpr EnumMask(EnumT val) : m_val(val) {} + operator EnumT() { return m_val; } + + EnumT m_val; +}; + +enum class A : unsigned { x }; + +template <class EnumT> +EnumMask<EnumT> operator ~(EnumT lhs) +{ + return EnumT(~unsigned(lhs) & unsigned(EnumT::maskAll)); // { dg-error "not a member" } + +} + +int main() +{ + ~A::x; + return 0; +} Index: cp/typeck.c =================================================================== --- cp/typeck.c (revision 188268) +++ cp/typeck.c (working copy) @@ -52,7 +52,7 @@ static tree rationalize_conditional_expr (enum tre static int comp_ptr_ttypes_real (tree, tree, int); static bool comp_except_types (tree, tree, bool); static bool comp_array_types (const_tree, const_tree, bool); -static tree pointer_diff (tree, tree, tree); +static tree pointer_diff (tree, tree, tree, tsubst_flags_t); static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); @@ -1906,7 +1906,7 @@ decay_conversion (tree exp, tsubst_flags_t complai /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = cp_build_addr_expr (exp, complain); - return cp_convert (ptrtype, adr); + return cp_convert (ptrtype, adr, complain); } /* If a bitfield is used in a context where integral promotion @@ -1950,12 +1950,12 @@ cp_default_conversion (tree exp, tsubst_flags_t co /* Check for target-specific promotions. */ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp)); if (promoted_type) - exp = cp_convert (promoted_type, exp); + exp = cp_convert (promoted_type, exp, complain); /* Perform the integral promotions first so that bitfield expressions (which may promote to "int", even if the bitfield is declared "unsigned") are promoted correctly. */ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp))) - exp = perform_integral_promotions (exp); + exp = cp_perform_integral_promotions (exp, complain); /* Perform the other conversions. */ exp = decay_conversion (exp, complain); @@ -1975,7 +1975,7 @@ default_conversion (tree exp) converted value. */ tree -perform_integral_promotions (tree expr) +cp_perform_integral_promotions (tree expr, tsubst_flags_t complain) { tree type; tree promoted_type; @@ -1995,10 +1995,18 @@ tree return expr; promoted_type = type_promotes_to (type); if (type != promoted_type) - expr = cp_convert (promoted_type, expr); + expr = cp_convert (promoted_type, expr, complain); return expr; } +/* C version. */ + +tree +perform_integral_promotions (tree expr) +{ + return cp_perform_integral_promotions (expr, tf_warning_or_error); +} + /* Returns nonzero iff exp is a STRING_CST or the result of applying decay_conversion to one. */ @@ -2945,7 +2953,7 @@ cp_build_array_ref (location_t loc, tree array, tr does not say that we should. In fact, the natural thing would seem to be to convert IDX to ptrdiff_t; we're performing pointer arithmetic.) */ - idx = perform_integral_promotions (idx); + idx = cp_perform_integral_promotions (idx, complain); /* An array that is indexed by a non-constant cannot be stored in a register; we must be able to do @@ -3867,7 +3875,8 @@ cp_build_binary_op (location_t location, if (code0 == POINTER_TYPE && code1 == POINTER_TYPE && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0), TREE_TYPE (type1))) - return pointer_diff (op0, op1, common_pointer_type (type0, type1)); + return pointer_diff (op0, op1, common_pointer_type (type0, type1), + complain); /* In all other cases except pointer - int, the usual arithmetic rules apply. */ else if (!(code0 == POINTER_TYPE && code1 == INTEGER_TYPE)) @@ -4003,7 +4012,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4031,7 +4040,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -4062,7 +4071,7 @@ cp_build_binary_op (location_t location, /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = cp_convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1, complain); } break; @@ -4162,12 +4171,12 @@ cp_build_binary_op (location_t location, op0 = cp_build_binary_op (location, TRUTH_ANDIF_EXPR, e1, e2, complain); - op1 = cp_convert (TREE_TYPE (op0), integer_one_node); + op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); } else { op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier); - op1 = cp_convert (TREE_TYPE (op0), op1); + op1 = cp_convert (TREE_TYPE (op0), op1, complain); } result_type = TREE_TYPE (op0); } @@ -4190,9 +4199,9 @@ cp_build_binary_op (location_t location, CPO_COMPARISON, complain); if (!same_type_p (TREE_TYPE (op0), type)) - op0 = cp_convert_and_check (type, op0); + op0 = cp_convert_and_check (type, op0, complain); if (!same_type_p (TREE_TYPE (op1), type)) - op1 = cp_convert_and_check (type, op1); + op1 = cp_convert_and_check (type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4456,16 +4465,16 @@ cp_build_binary_op (location_t location, if (first_complex) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != real_type) - op1 = cp_convert_and_check (real_type, op1); + op1 = cp_convert_and_check (real_type, op1, complain); } else { if (TREE_TYPE (op0) != real_type) - op0 = cp_convert_and_check (real_type, op0); + op0 = cp_convert_and_check (real_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); } if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK) return error_mark_node; @@ -4550,7 +4559,7 @@ cp_build_binary_op (location_t location, tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return cp_convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val, complain); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -4580,9 +4589,9 @@ cp_build_binary_op (location_t location, if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = cp_convert_and_check (result_type, op0); + op0 = cp_convert_and_check (result_type, op0, complain); if (TREE_TYPE (op1) != result_type) - op1 = cp_convert_and_check (result_type, op1); + op1 = cp_convert_and_check (result_type, op1, complain); if (op0 == error_mark_node || op1 == error_mark_node) return error_mark_node; @@ -4594,7 +4603,7 @@ cp_build_binary_op (location_t location, result = build2 (resultcode, build_type, op0, op1); result = fold_if_not_in_template (result); if (final_type != 0) - result = cp_convert (final_type, result); + result = cp_convert (final_type, result, complain); if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (op0) @@ -4627,7 +4636,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tre The resulting tree has type int. */ static tree -pointer_diff (tree op0, tree op1, tree ptrtype) +pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain) { tree result; tree restype = ptrdiff_type_node; @@ -4637,24 +4646,48 @@ static tree return error_mark_node; if (TREE_CODE (target_type) == VOID_TYPE) - permerror (input_location, "ISO C++ forbids using pointer of type %<void *%> in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer of " + "type %<void *%> in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == FUNCTION_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a function in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a function in subtraction"); + else + return error_mark_node; + } if (TREE_CODE (target_type) == METHOD_TYPE) - permerror (input_location, "ISO C++ forbids using pointer to a method in subtraction"); + { + if (complain & tf_error) + permerror (input_location, "ISO C++ forbids using pointer to " + "a method in subtraction"); + else + return error_mark_node; + } /* First do the subtraction as integers; then drop through to build the divide operator. */ op0 = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (restype, op0), - cp_convert (restype, op1), - tf_warning_or_error); + cp_convert (restype, op0, complain), + cp_convert (restype, op1, complain), + complain); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) - error ("invalid use of a pointer to an incomplete type in pointer arithmetic"); + { + if (complain & tf_error) + error ("invalid use of a pointer to an incomplete type in " + "pointer arithmetic"); + else + return error_mark_node; + } op1 = (TYPE_PTROB_P (ptrtype) ? size_in_bytes (target_type) @@ -4662,7 +4695,8 @@ static tree /* Do the division. */ - result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); + result = build2 (EXACT_DIV_EXPR, restype, op0, + cp_convert (restype, op1, complain)); return fold_if_not_in_template (result); } \f @@ -5175,7 +5209,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else { if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); /* Make sure the result is not an lvalue: a unary plus or minus expression is always a rvalue. */ @@ -5200,7 +5234,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, arg, true))) errstring = _("wrong type argument to bit-complement"); else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg))) - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); break; case ABS_EXPR: @@ -5358,7 +5392,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, else inc = integer_one_node; - inc = cp_convert (argtype, inc); + inc = cp_convert (argtype, inc, complain); /* If 'arg' is an Objective-C PROPERTY_REF expression, then we need to ask Objective-C to build the increment or decrement @@ -6074,7 +6108,7 @@ build_static_cast_1 (tree type, tree expr, bool c_ || SCALAR_FLOAT_TYPE_P (type)) && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype))) - return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain); if (TYPE_PTR_P (type) && TYPE_PTR_P (intype) && CLASS_TYPE_P (TREE_TYPE (type)) @@ -6417,7 +6451,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bo return error_mark_node; } - return cp_convert (type, expr); + return cp_convert (type, expr, complain); } tree @@ -7078,7 +7112,7 @@ cp_build_modify_expr (tree lhs, enum tree_code mod NULL_TREE, 0, complain, LOOKUP_IMPLICIT); if (!same_type_p (lhstype, olhstype)) - newrhs = cp_convert_and_check (lhstype, newrhs); + newrhs = cp_convert_and_check (lhstype, newrhs, complain); if (modifycode != INIT_EXPR) { @@ -7599,7 +7633,7 @@ convert_for_assignment (tree type, tree rhs, if (!warn_pmf2ptr && TYPE_PTR_P (type) && TYPE_PTRMEMFUNC_P (rhstype)) - rhs = cp_convert (strip_top_quals (type), rhs); + rhs = cp_convert (strip_top_quals (type), rhs, complain); else { if (complain & tf_error) @@ -7723,10 +7757,8 @@ convert_for_assignment (tree type, tree rhs, latter (X(X&)). If using constructor make sure no conversion operator exists, if one does - exist, an ambiguity exists. + exist, an ambiguity exists. */ - If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */ - tree convert_for_initialization (tree exp, tree type, tree rhs, int flags, impl_conv_rhs errtype, tree fndecl, int parmnum, Index: cp/optimize.c =================================================================== --- cp/optimize.c (revision 188268) +++ cp/optimize.c (working copy) @@ -138,7 +138,8 @@ build_delete_destructor_body (tree delete_dtor, tr virtual_size, /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); add_stmt (call_delete); /* Return the address of the object. */ Index: cp/init.c =================================================================== --- cp/init.c (revision 188268) +++ cp/init.c (working copy) @@ -1180,7 +1180,7 @@ expand_virtual_init (tree binfo, tree decl) gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ - vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); + vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0, tf_warning_or_error); finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, tf_warning_or_error)); } @@ -1250,7 +1250,7 @@ construct_virtual_base (tree vbase, tree arguments exp = convert_to_base_statically (current_class_ref, vbase); expand_aggr_init_1 (vbase, current_class_ref, exp, arguments, - LOOKUP_COMPLAIN, tf_warning_or_error); + 0, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1598,7 +1598,8 @@ expand_default_init (tree binfo, tree true_exp, tr have already built up the constructor call so we could wrap it in an exception region. */; else - init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, + flags, complain); if (TREE_CODE (init) == MUST_NOT_THROW_EXPR) /* We need to protect the initialization of a catch parm with a @@ -2656,7 +2657,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, size, globally_qualified_p, placement_allocation_fn_p ? alloc_call : NULL_TREE, - alloc_fn)); + alloc_fn, + complain)); if (!cleanup) /* We're done. */; @@ -2815,7 +2817,7 @@ build_new (VEC(tree,gc) **placement, tree type, tr return error_mark_node; } nelts = mark_rvalue_use (nelts); - nelts = cp_save_expr (cp_convert (sizetype, nelts)); + nelts = cp_save_expr (cp_convert (sizetype, nelts, complain)); } /* ``A reference cannot be created by the new operator. A reference @@ -3012,12 +3014,12 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd = cp_build_binary_op (input_location, MINUS_EXPR, cp_convert (string_type_node, - base), + base, complain), cookie_size, complain); if (base_tbd == error_mark_node) return error_mark_node; - base_tbd = cp_convert (ptype, base_tbd); + base_tbd = cp_convert (ptype, base_tbd, complain); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -3026,7 +3028,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree base_tbd, virtual_size, use_global_delete & 1, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } body = loop; @@ -3189,14 +3192,14 @@ build_vec_init (tree base, tree maxindex, tree ini return stmt_expr; } - maxindex = cp_convert (ptrdiff_type_node, maxindex); + maxindex = cp_convert (ptrdiff_type_node, maxindex, complain); if (TREE_CODE (atype) == ARRAY_TYPE) { ptype = build_pointer_type (type); base = decay_conversion (base, complain); if (base == error_mark_node) return error_mark_node; - base = cp_convert (ptype, base); + base = cp_convert (ptype, base, complain); } else ptype = atype; @@ -3665,7 +3668,7 @@ build_delete (tree type, tree addr, special_functi addr = save_expr (addr); /* Throw away const and volatile on target type of addr. */ - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3691,7 +3694,7 @@ build_delete (tree type, tree addr, special_functi if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); - addr = convert_force (build_pointer_type (type), addr, 0); + addr = convert_force (build_pointer_type (type), addr, 0, complain); } gcc_assert (MAYBE_CLASS_TYPE_P (type)); @@ -3705,7 +3708,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), use_global_delete, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } else { @@ -3744,7 +3748,8 @@ build_delete (tree type, tree addr, special_functi cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); /* Call the complete object destructor. */ auto_delete = sfk_complete_destructor; } @@ -3756,7 +3761,8 @@ build_delete (tree type, tree addr, special_functi build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), /*global_p=*/false, /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + /*alloc_fn=*/NULL_TREE, + complain); } expr = build_dtor_call (cp_build_indirect_ref (addr, RO_NULL, complain), Index: cp/class.c =================================================================== --- cp/class.c (revision 188268) +++ cp/class.c (working copy) @@ -366,7 +366,7 @@ build_base_path (enum tree_code code, /* Now that we've saved expr, build the real null test. */ if (null_test) { - tree zero = cp_convert (TREE_TYPE (expr), nullptr_node); + tree zero = cp_convert (TREE_TYPE (expr), nullptr_node, complain); null_test = fold_build2_loc (input_location, NE_EXPR, boolean_type_node, expr, zero); } Index: cp/decl.c =================================================================== --- cp/decl.c (revision 188268) +++ cp/decl.c (working copy) @@ -8104,9 +8104,10 @@ compute_array_index_type (tree name, tree size, ts processing_template_decl = 0; itype = cp_build_binary_op (input_location, MINUS_EXPR, - cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node), - tf_warning_or_error); + cp_convert (ssizetype, size, complain), + cp_convert (ssizetype, integer_one_node, + complain), + complain); itype = fold (itype); processing_template_decl = saved_processing_template_decl; @@ -13290,11 +13291,12 @@ finish_destructor_body (void) an implicit definition), non-placement operator delete shall be looked up in the scope of the destructor's class and if found shall be accessible and unambiguous. */ - exprstmt = build_op_delete_call(DELETE_EXPR, current_class_ptr, - virtual_size, - /*global_p=*/false, - /*placement=*/NULL_TREE, - /*alloc_fn=*/NULL_TREE); + exprstmt = build_op_delete_call (DELETE_EXPR, current_class_ptr, + virtual_size, + /*global_p=*/false, + /*placement=*/NULL_TREE, + /*alloc_fn=*/NULL_TREE, + tf_warning_or_error); if_stmt = begin_if_stmt (); finish_if_stmt_cond (build2 (BIT_AND_EXPR, integer_type_node, Index: cp/method.c =================================================================== --- cp/method.c (revision 188268) +++ cp/method.c (working copy) @@ -1228,17 +1228,10 @@ synthesized_method_walk (tree ctype, special_funct scope = push_scope (ctype); - if (diag) - { - flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_warning_or_error; - } - else - { - flags = LOOKUP_PROTECT|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; - complain = tf_none; - } + flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; + complain = diag ? tf_warning_or_error : tf_none; + if (const_p) quals = TYPE_QUAL_CONST; else Index: cp/rtti.c =================================================================== --- cp/rtti.c (revision 188268) +++ cp/rtti.c (working copy) @@ -99,7 +99,7 @@ VEC(tree,gc) *unemitted_tinfo_decls; and are generated as needed. */ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; -static tree ifnonnull (tree, tree); +static tree ifnonnull (tree, tree, tsubst_flags_t); static tree tinfo_name (tree, bool); static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); @@ -336,7 +336,8 @@ build_typeid (tree exp) This is an lvalue use of expr then. */ exp = mark_lvalue_use (exp); exp = stabilize_reference (exp); - cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0)); + cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0), + tf_warning_or_error); } exp = get_tinfo_decl_dynamic (exp); @@ -498,12 +499,13 @@ get_typeid (tree type) RESULT, it must have previously had a save_expr applied to it. */ static tree -ifnonnull (tree test, tree result) +ifnonnull (tree test, tree result, tsubst_flags_t complain) { return build3 (COND_EXPR, TREE_TYPE (result), build2 (EQ_EXPR, boolean_type_node, test, - cp_convert (TREE_TYPE (test), nullptr_node)), - cp_convert (TREE_TYPE (result), nullptr_node), + cp_convert (TREE_TYPE (test), nullptr_node, + complain)), + cp_convert (TREE_TYPE (result), nullptr_node, complain), result); } @@ -596,7 +598,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst /* Apply trivial conversion T -> T& for dereferenced ptrs. */ expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, complain); } /* The dynamic_cast operator shall not cast away constness. */ @@ -644,7 +646,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst expr1 = build_headof (expr); if (TREE_TYPE (expr1) != type) expr1 = build1 (NOP_EXPR, type, expr1); - return ifnonnull (expr, expr1); + return ifnonnull (expr, expr1, complain); } else { @@ -752,12 +754,12 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst neq = cp_truthvalue_conversion (result); return cp_convert (type, build3 (COND_EXPR, TREE_TYPE (result), - neq, result, bad)); + neq, result, bad), complain); } /* Now back to the type we want from a void*. */ - result = cp_convert (type, result); - return ifnonnull (expr, result); + result = cp_convert (type, result, complain); + return ifnonnull (expr, result, complain); } } else Index: cp/except.c =================================================================== --- cp/except.c (revision 188268) +++ cp/except.c (working copy) @@ -424,7 +424,8 @@ initialize_handler_parm (tree decl, tree exp) && TYPE_PTR_P (TREE_TYPE (init_type))) exp = cp_build_addr_expr (exp, tf_warning_or_error); - exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); init = convert_from_reference (exp); @@ -435,7 +436,8 @@ initialize_handler_parm (tree decl, tree exp) /* Generate the copy constructor call directly so we can wrap it. See also expand_default_init. */ init = ocp_convert (TREE_TYPE (decl), init, - CONV_IMPLICIT|CONV_FORCE_TEMP, 0); + CONV_IMPLICIT|CONV_FORCE_TEMP, 0, + tf_warning_or_error); /* Force cleanups now to avoid nesting problems with the MUST_NOT_THROW_EXPR. */ init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); Index: cp/typeck2.c =================================================================== --- cp/typeck2.c (revision 188268) +++ cp/typeck2.c (working copy) @@ -1264,7 +1264,7 @@ process_init_constructor_record (tree type, tree i /* If this is a bitfield, now convert to the lowered type. */ if (type != TREE_TYPE (field)) - next = cp_convert_and_check (TREE_TYPE (field), next); + next = cp_convert_and_check (TREE_TYPE (field), next, complain); flags |= picflag_from_initializer (next); CONSTRUCTOR_APPEND_ELT (v, field, next); } Index: cp/pt.c =================================================================== --- cp/pt.c (revision 188268) +++ cp/pt.c (working copy) @@ -8474,8 +8474,7 @@ tsubst_friend_class (tree friend_tmpl, tree args) both F templates are the same. */ tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0, - /*block_p=*/true, 0, - LOOKUP_COMPLAIN | LOOKUP_HIDDEN); + /*block_p=*/true, 0, LOOKUP_HIDDEN); /* But, if we don't find one, it might be because we're in a situation like this: Index: cp/semantics.c =================================================================== --- cp/semantics.c (revision 188268) +++ cp/semantics.c (working copy) @@ -564,7 +564,8 @@ finish_goto_stmt (tree destination) destination = mark_rvalue_use (destination); if (!processing_template_decl) { - destination = cp_convert (ptr_type_node, destination); + destination = cp_convert (ptr_type_node, destination, + tf_warning_or_error); if (error_operand_p (destination)) return NULL_TREE; } @@ -4526,7 +4527,8 @@ handle_omp_for_class_iterator (int i, location_t l if (error_operand_p (iter_incr)) return true; incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, + tf_warning_or_error); if (TREE_CODE (rhs) == MINUS_EXPR) { incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); @@ -4581,7 +4583,7 @@ handle_omp_for_class_iterator (int i, location_t l return true; } - incr = cp_convert (TREE_TYPE (diff), incr); + incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == iter) @@ -5130,7 +5132,7 @@ finish_static_assert (tree condition, tree message /* Fold the expression and convert it to a boolean value. */ condition = fold_non_dependent_expr (condition); - condition = cp_convert (boolean_type_node, condition); + condition = cp_convert (boolean_type_node, condition, tf_warning_or_error); condition = maybe_constant_value (condition); if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) Index: cp/parser.c =================================================================== --- cp/parser.c (revision 188268) +++ cp/parser.c (working copy) @@ -20320,13 +20320,9 @@ cp_parser_lookup_name (cp_parser *parser, tree nam tree *ambiguous_decls, location_t name_location) { - int flags = 0; tree decl; tree object_type = parser->context->object_type; - if (!cp_parser_uncommitted_to_tentative_parse_p (parser)) - flags |= LOOKUP_COMPLAIN; - /* Assume that the lookup will be unambiguous. */ if (ambiguous_decls) *ambiguous_decls = NULL_TREE; @@ -20498,7 +20494,7 @@ cp_parser_lookup_name (cp_parser *parser, tree nam /* Look it up in the enclosing context, too. */ decl = lookup_name_real (name, tag_type != none_type, /*nonclass=*/0, - /*block_p=*/true, is_namespace, flags); + /*block_p=*/true, is_namespace, 0); parser->object_scope = object_type; parser->qualifying_scope = NULL_TREE; if (object_decl) @@ -20508,7 +20504,7 @@ cp_parser_lookup_name (cp_parser *parser, tree nam { decl = lookup_name_real (name, tag_type != none_type, /*nonclass=*/0, - /*block_p=*/true, is_namespace, flags); + /*block_p=*/true, is_namespace, 0); parser->qualifying_scope = NULL_TREE; parser->object_scope = NULL_TREE; } Index: cp/call.c =================================================================== --- cp/call.c (revision 188268) +++ cp/call.c (working copy) @@ -1695,6 +1695,13 @@ implicit_conversion (tree to, tree from, tree expr |LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE |LOOKUP_NO_NARROWING|LOOKUP_PROTECT); + /* FIXME: actually we don't want warnings either, but we can't just + have 'complain &= ~(tf_warning|tf_error)' because it would cause + the regression of, eg, g++.old-deja/g++.benjamin/16077.C. + We really ought not to issue that warning until we've committed + to that conversion. */ + complain &= ~tf_error; + if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, c_cast_p, flags, complain); else @@ -3607,8 +3614,7 @@ build_user_type_conversion_1 (tree totype, tree ex cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) - && (complain & tf_error)) + if (complain & tf_error) { error ("conversion from %qT to %qT is ambiguous", fromtype, totype); @@ -5098,7 +5104,7 @@ build_new_op_1 (location_t loc, enum tree_code cod distinguish between prefix and postfix ++ and operator++() was used for both, so we allow this with -fpermissive. */ - if (flags & LOOKUP_COMPLAIN) + else { const char *msg = (flag_permissive) ? G_("no %<%D(int)%> declared for postfix %qs," @@ -5127,7 +5133,7 @@ build_new_op_1 (location_t loc, enum tree_code cod break; default: - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { /* If one of the arguments of the operator represents an invalid use of member function pointer, try to report @@ -5153,7 +5159,7 @@ build_new_op_1 (location_t loc, enum tree_code cod cand = tourney (candidates, complain); if (cand == 0) { - if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) + if (complain & tf_error) { op_error (loc, code, code2, arg1, arg2, arg3, TRUE); print_z_candidates (loc, candidates); @@ -5379,7 +5385,7 @@ non_placement_deallocation_fn_p (tree t) tree build_op_delete_call (enum tree_code code, tree addr, tree size, bool global_p, tree placement, - tree alloc_fn) + tree alloc_fn, tsubst_flags_t complain) { tree fn = NULL_TREE; tree fns, fnname, type, t; @@ -5413,7 +5419,7 @@ build_op_delete_call (enum tree_code code, tree ad fns = lookup_name_nonclass (fnname); /* Strip const and volatile from addr. */ - addr = cp_convert (ptr_type_node, addr); + addr = cp_convert (ptr_type_node, addr, complain); if (placement) { @@ -5452,8 +5458,13 @@ build_op_delete_call (enum tree_code code, tree ad && FUNCTION_ARG_CHAIN (elt) == void_list_node) goto ok; } - permerror (0, "non-placement deallocation function %q+D", fn); - permerror (input_location, "selected for placement delete"); + if (complain & tf_error) + { + permerror (0, "non-placement deallocation function %q+D", fn); + permerror (input_location, "selected for placement delete"); + } + else + return error_mark_node; ok:; } } @@ -5518,7 +5529,7 @@ build_op_delete_call (enum tree_code code, tree ad VEC_quick_push (tree, args, addr); if (FUNCTION_ARG_CHAIN (fn) != void_list_node) VEC_quick_push (tree, args, size); - ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error); + ret = cp_build_function_call_vec (fn, &args, complain); VEC_free (tree, gc, args); return ret; } @@ -5531,14 +5542,16 @@ build_op_delete_call (enum tree_code code, tree ad be freed. */ if (alloc_fn) { - if (!placement) + if ((complain & tf_warning) + && !placement) warning (0, "no corresponding deallocation function for %qD", alloc_fn); return NULL_TREE; } - error ("no suitable %<operator %s%> for %qT", - operator_name_info[(int)code].name, type); + if (complain & tf_error) + error ("no suitable %<operator %s%> for %qT", + operator_name_info[(int)code].name, type); return error_mark_node; } @@ -5685,9 +5698,10 @@ convert_like_real (conversion *convs, tree expr, t complain); if (convs->kind == ck_ref_bind) return convert_to_reference (totype, expr, CONV_IMPLICIT, - LOOKUP_NORMAL, NULL_TREE); + LOOKUP_NORMAL, NULL_TREE, + complain); else - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } else if (t->kind == ck_user || !t->bad_p) { @@ -5712,7 +5726,7 @@ convert_like_real (conversion *convs, tree expr, t permerror (DECL_SOURCE_LOCATION (fn), " initializing argument %P of %qD", argnum, fn); - return cp_convert (totype, expr); + return cp_convert (totype, expr, complain); } if (issue_conversion_warnings && (complain & tf_warning)) @@ -5851,7 +5865,7 @@ convert_like_real (conversion *convs, tree expr, t /* Take the address explicitly rather than via decay_conversion to avoid the error about taking the address of a temporary. */ array = cp_build_addr_expr (array, complain); - array = cp_convert (build_pointer_type (elttype), array); + array = cp_convert (build_pointer_type (elttype), array, complain); /* Build up the initializer_list object. */ totype = complete_type (totype); @@ -6017,7 +6031,7 @@ convert_like_real (conversion *convs, tree expr, t reference. This will adjust the pointer if a derived to base conversion is being performed. */ expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), - expr); + expr, complain); /* Convert the pointer to the desired reference type. */ return build_nop (ref_type, expr); } @@ -6099,9 +6113,9 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t if (complain & tf_warning) warning_at (loc, OPT_Wabi, "scoped enum %qT will not promote to an " "integral type in a future version of GCC", arg_type); - arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg); + arg = cp_convert (ENUM_UNDERLYING_TYPE (arg_type), arg, complain); } - arg = perform_integral_promotions (arg); + arg = cp_perform_integral_promotions (arg, complain); } arg = require_complete_type (arg); @@ -6336,7 +6350,7 @@ convert_for_arg_passing (tree type, tree val, tsub && COMPLETE_TYPE_P (type) && INT_CST_LT_UNSIGNED (TYPE_SIZE (type), TYPE_SIZE (integer_type_node))) - val = perform_integral_promotions (val); + val = cp_perform_integral_promotions (val, complain); if ((complain & tf_warning) && warn_suggest_attribute_format) { @@ -6487,7 +6501,7 @@ build_over_call (struct z_candidate *cand, int fla if (flags & LOOKUP_SPECULATIVE) { if (!speculative_access_check (cand->access_path, access_fn, fn, - !!(flags & LOOKUP_COMPLAIN))) + complain & tf_error)) return error_mark_node; } else @@ -6500,13 +6514,13 @@ build_over_call (struct z_candidate *cand, int fla { if (DECL_DELETED_FN (fn)) { - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) mark_used (fn); return error_mark_node; } if (cand->viable == 1) return fn; - else if (!(flags & LOOKUP_COMPLAIN)) + else if (!(complain & tf_error)) /* Reject bad conversions now. */ return error_mark_node; /* else continue to get conversion error. */ Index: cp/cvt.c =================================================================== --- cp/cvt.c (revision 188268) +++ cp/cvt.c (working copy) @@ -38,10 +38,10 @@ along with GCC; see the file COPYING3. If not see #include "decl.h" #include "target.h" -static tree cp_convert_to_pointer (tree, tree); -static tree convert_to_pointer_force (tree, tree); +static tree cp_convert_to_pointer (tree, tree, tsubst_flags_t); +static tree convert_to_pointer_force (tree, tree, tsubst_flags_t); static tree build_type_conversion (tree, tree); -static tree build_up_reference (tree, tree, int, tree); +static tree build_up_reference (tree, tree, int, tree, tsubst_flags_t); static void warn_ref_binding (location_t, tree, tree, tree); /* Change of width--truncation and extension of integers or reals-- @@ -74,7 +74,7 @@ static void warn_ref_binding (location_t, tree, tr else try C-style pointer conversion. */ static tree -cp_convert_to_pointer (tree type, tree expr) +cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form; @@ -89,15 +89,17 @@ static tree intype = complete_type (intype); if (!COMPLETE_TYPE_P (intype)) { - error_at (loc, "can%'t convert from incomplete type %qT to %qT", - intype, type); + if (complain & tf_error) + error_at (loc, "can%'t convert from incomplete type %qT to %qT", + intype, type); return error_mark_node; } rval = build_type_conversion (type, expr); if (rval) { - if (rval == error_mark_node) + if ((complain & tf_error) + && rval == error_mark_node) error_at (loc, "conversion of %qE from %qT to %qT is ambiguous", expr, intype, type); return rval; @@ -111,7 +113,7 @@ static tree { if (TYPE_PTRMEMFUNC_P (intype) || TREE_CODE (intype) == METHOD_TYPE) - return convert_member_func_to_ptr (type, expr, tf_warning_or_error); + return convert_member_func_to_ptr (type, expr, complain); if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) return build_nop (type, expr); intype = TREE_TYPE (expr); @@ -159,8 +161,7 @@ static tree if (binfo || same_p) { if (binfo) - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); /* Add any qualifier conversions. */ return build_nop (type, expr); } @@ -168,8 +169,9 @@ static tree if (TYPE_PTRMEMFUNC_P (type)) { - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -178,20 +180,20 @@ static tree else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype)) || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) return convert_ptrmem (type, expr, /*allow_inverse_p=*/false, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); else if (TYPE_PTRMEMFUNC_P (intype)) { if (!warn_pmf2ptr) { if (TREE_CODE (expr) == PTRMEM_CST) - return cp_convert_to_pointer (type, - PTRMEM_CST_MEMBER (expr)); + return cp_convert_to_pointer (type, PTRMEM_CST_MEMBER (expr), + complain); else if (TREE_CODE (expr) == OFFSET_REF) { tree object = TREE_OPERAND (expr, 0); return get_member_function_from_ptrfunc (&object, TREE_OPERAND (expr, 1), - tf_warning_or_error); + complain); } } error_at (loc, "cannot convert %qE from type %qT to type %qT", @@ -201,14 +203,15 @@ static tree if (null_ptr_cst_p (expr)) { - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !NULLPTR_TYPE_P (TREE_TYPE (expr))) warning_at (loc, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); if (TYPE_PTRMEMFUNC_P (type)) return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0, - /*c_cast_p=*/false, tf_warning_or_error); + /*c_cast_p=*/false, complain); if (TYPE_PTRDATAMEM_P (type)) { @@ -223,7 +226,8 @@ static tree } else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form)) { - error_at (loc, "invalid conversion from %qT to %qT", intype, type); + if (complain & tf_error) + error_at (loc, "invalid conversion from %qT to %qT", intype, type); return error_mark_node; } @@ -231,7 +235,8 @@ static tree { if (TYPE_PRECISION (intype) == POINTER_SIZE) return build1 (CONVERT_EXPR, type, expr); - expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr); + expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr, + complain); /* Modes may be different but sizes should be the same. There is supposed to be some integral type that is the same width as a pointer. */ @@ -242,10 +247,11 @@ static tree } if (type_unknown_p (expr)) - return instantiate_type (type, expr, tf_warning_or_error); + return instantiate_type (type, expr, complain); - error_at (loc, "cannot convert %qE from type %qT to type %qT", - expr, intype, type); + if (complain & tf_error) + error_at (loc, "cannot convert %qE from type %qT to type %qT", + expr, intype, type); return error_mark_node; } @@ -254,7 +260,7 @@ static tree (such as conversion from sub-type to private super-type). */ static tree -convert_to_pointer_force (tree type, tree expr) +convert_to_pointer_force (tree type, tree expr, tsubst_flags_t complain) { tree intype = TREE_TYPE (expr); enum tree_code form = TREE_CODE (intype); @@ -284,8 +290,7 @@ static tree return error_mark_node; if (binfo) { - expr = build_base_path (code, expr, binfo, 0, - tf_warning_or_error); + expr = build_base_path (code, expr, binfo, 0, complain); if (expr == error_mark_node) return error_mark_node; /* Add any qualifier conversions. */ @@ -297,7 +302,7 @@ static tree } } - return cp_convert_to_pointer (type, expr); + return cp_convert_to_pointer (type, expr, complain); } /* We are passing something to a function which requires a reference. @@ -309,7 +314,8 @@ static tree If DIRECT_BIND is set, DECL is the reference we're binding to. */ static tree -build_up_reference (tree type, tree arg, int flags, tree decl) +build_up_reference (tree type, tree arg, int flags, tree decl, + tsubst_flags_t complain) { tree rval; tree argtype = TREE_TYPE (arg); @@ -351,12 +357,12 @@ static tree return error_mark_node; if (binfo == NULL_TREE) return error_not_base_type (target_type, argtype); - rval = build_base_path (PLUS_EXPR, rval, binfo, 1, - tf_warning_or_error); + rval = build_base_path (PLUS_EXPR, rval, binfo, 1, complain); } else rval - = convert_to_pointer_force (build_pointer_type (target_type), rval); + = convert_to_pointer_force (build_pointer_type (target_type), + rval, complain); return build_nop (type, rval); } @@ -403,15 +409,13 @@ warn_ref_binding (location_t loc, tree reftype, tr tree convert_to_reference (tree reftype, tree expr, int convtype, - int flags, tree decl) + int flags, tree decl, tsubst_flags_t complain) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; - tsubst_flags_t complain = ((flags & LOOKUP_COMPLAIN) - ? tf_warning_or_error : tf_none); location_t loc = EXPR_LOC_OR_HERE (expr); if (TREE_CODE (type) == FUNCTION_TYPE @@ -452,21 +456,26 @@ convert_to_reference (tree reftype, tree expr, int if (((convtype & CONV_STATIC) && can_convert (intype, type, complain)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { - if (flags & LOOKUP_COMPLAIN) - { - tree ttl = TREE_TYPE (reftype); - tree ttr = lvalue_type (expr); + { + tree ttl = TREE_TYPE (reftype); + tree ttr = lvalue_type (expr); - if (! real_lvalue_p (expr)) - warn_ref_binding (loc, reftype, intype, decl); + if ((complain & tf_warning) + && ! real_lvalue_p (expr)) + warn_ref_binding (loc, reftype, intype, decl); - if (! (convtype & CONV_CONST) - && !at_least_as_qualified_p (ttl, ttr)) - permerror (loc, "conversion from %qT to %qT discards qualifiers", - ttr, reftype); - } + if (! (convtype & CONV_CONST) + && !at_least_as_qualified_p (ttl, ttr)) + { + if (complain & tf_error) + permerror (loc, "conversion from %qT to %qT discards qualifiers", + ttr, reftype); + else + return error_mark_node; + } + } - return build_up_reference (reftype, expr, flags, decl); + return build_up_reference (reftype, expr, flags, decl, complain); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { @@ -477,28 +486,29 @@ convert_to_reference (tree reftype, tree expr, int /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ - if (TREE_CODE (intype) == POINTER_TYPE + if ((complain & tf_warning) + && TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_DERIVED))) warning_at (loc, 0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = cp_build_addr_expr (expr, tf_warning_or_error); + rval = cp_build_addr_expr (expr, complain); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), - rval, 0); + rval, 0, complain); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, - ICR_CONVERTING, 0, 0, - tf_warning_or_error); + ICR_CONVERTING, 0, 0, complain); if (rval == NULL_TREE || rval == error_mark_node) return rval; - warn_ref_binding (loc, reftype, intype, decl); - rval = build_up_reference (reftype, rval, flags, decl); + if (complain & tf_warning) + warn_ref_binding (loc, reftype, intype, decl); + rval = build_up_reference (reftype, rval, flags, decl, complain); } if (rval) @@ -507,7 +517,7 @@ convert_to_reference (tree reftype, tree expr, int return rval; } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; @@ -595,9 +605,9 @@ cp_fold_convert (tree type, tree expr) /* C++ conversions, preference to static cast conversions. */ tree -cp_convert (tree type, tree expr) +cp_convert (tree type, tree expr, tsubst_flags_t complain) { - return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL); + return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL, complain); } /* C++ equivalent of convert_and_check but using cp_convert as the @@ -608,16 +618,17 @@ tree i.e. because of language rules and not because of an explicit cast. */ tree -cp_convert_and_check (tree type, tree expr) +cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { tree result; if (TREE_TYPE (expr) == type) return expr; - result = cp_convert (type, expr); + result = cp_convert (type, expr, complain); - if (c_inhibit_evaluation_warnings == 0 + if ((complain & tf_warning) + && c_inhibit_evaluation_warnings == 0 && !TREE_OVERFLOW_P (expr) && result != error_mark_node) warnings_for_convert_and_check (type, expr, result); @@ -630,7 +641,8 @@ tree FLAGS indicates how we should behave. */ tree -ocp_convert (tree type, tree expr, int convtype, int flags) +ocp_convert (tree type, tree expr, int convtype, int flags, + tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); @@ -647,7 +659,8 @@ tree if ((invalid_conv_diag = targetm.invalid_conversion (TREE_TYPE (expr), type))) { - error (invalid_conv_diag); + if (complain & tf_error) + error (invalid_conv_diag); return error_mark_node; } @@ -696,7 +709,7 @@ tree if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, ICV_CAST, tf_warning_or_error); + e = convert_to_void (e, ICV_CAST, complain); return e; } @@ -714,9 +727,9 @@ tree && ! (convtype & CONV_STATIC)) || TREE_CODE (intype) == POINTER_TYPE) { - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) permerror (loc, "conversion from %q#T to %q#T", intype, type); - if (!flag_permissive) + else return error_mark_node; } @@ -727,7 +740,8 @@ tree the original value is within the range of the enumeration values. Otherwise, the resulting enumeration value is unspecified. */ - if (TREE_CODE (expr) == INTEGER_CST + if ((complain & tf_warning) + && TREE_CODE (expr) == INTEGER_CST && !int_fits_type_p (expr, ENUM_UNDERLYING_TYPE (type))) warning_at (loc, OPT_Wconversion, "the result of the conversion is unspecified because " @@ -740,7 +754,7 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) error_at (loc, "%q#T used where a %qT was expected", intype, type); return error_mark_node; } @@ -748,8 +762,10 @@ tree { if (TREE_CODE (intype) == VOID_TYPE) { - error_at (loc, "could not convert %qE from %<void%> to %<bool%>", - expr); + if (complain & tf_error) + error_at (loc, + "could not convert %qE from %<void%> to %<bool%>", + expr); return error_mark_node; } @@ -768,7 +784,7 @@ tree if (NULLPTR_TYPE_P (type) && e && null_ptr_cst_p (e)) return nullptr_node; if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type)) - return fold_if_not_in_template (cp_convert_to_pointer (type, e)); + return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain)); if (code == VECTOR_TYPE) { tree in_vtype = TREE_TYPE (e); @@ -778,8 +794,9 @@ tree ret_val = build_type_conversion (type, e); if (ret_val) return ret_val; - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a %qT was expected", in_vtype, type); + if (complain & tf_error) + error_at (loc, "%q#T used where a %qT was expected", + in_vtype, type); return error_mark_node; } return fold_if_not_in_template (convert_to_vector (type, e)); @@ -792,10 +809,10 @@ tree rval = build_type_conversion (type, e); if (rval) return rval; - else - if (flags & LOOKUP_COMPLAIN) - error_at (loc, "%q#T used where a floating point value was expected", - TREE_TYPE (e)); + else if (complain & tf_error) + error_at (loc, + "%q#T used where a floating point value was expected", + TREE_TYPE (e)); } if (code == REAL_TYPE) return fold_if_not_in_template (convert_to_real (type, e)); @@ -826,33 +843,31 @@ tree return error_mark_node; if (BRACE_ENCLOSED_INITIALIZER_P (ctor)) - ctor = perform_implicit_conversion (type, ctor, tf_warning_or_error); + ctor = perform_implicit_conversion (type, ctor, complain); else if ((flags & LOOKUP_ONLYCONVERTING) && ! (CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ - ctor = build_user_type_conversion (type, ctor, flags, - tf_warning_or_error); + ctor = build_user_type_conversion (type, ctor, flags, complain); else { VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor); ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, &ctor_vec, - type, flags, - tf_warning_or_error); + type, flags, complain); release_tree_vector (ctor_vec); } if (ctor) - return build_cplus_new (type, ctor, tf_warning_or_error); + return build_cplus_new (type, ctor, complain); } - if (flags & LOOKUP_COMPLAIN) + if (complain & tf_error) { /* If the conversion failed and expr was an invalid use of pointer to member function, try to report a meaningful error. */ - if (invalid_nonstatic_memfn_p (expr, tf_warning_or_error)) + if (invalid_nonstatic_memfn_p (expr, complain)) /* We displayed the error message. */; else error_at (loc, "conversion from %qT to non-scalar type %qT requested", @@ -1416,7 +1431,8 @@ convert (tree type, tree expr) return fold_if_not_in_template (build_nop (type, expr)); return ocp_convert (type, expr, CONV_OLD_CONVERT, - LOOKUP_NORMAL|LOOKUP_NO_CONVERSION); + LOOKUP_NORMAL|LOOKUP_NO_CONVERSION, + tf_warning_or_error); } /* Like cp_convert, except permit conversions to take place which @@ -1424,18 +1440,19 @@ convert (tree type, tree expr) (such as conversion from sub-type to private super-type). */ tree -convert_force (tree type, tree expr, int convtype) +convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain) { tree e = expr; enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) return (fold_if_not_in_template - (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, - NULL_TREE))); + (convert_to_reference (type, e, CONV_C_CAST, 0, + NULL_TREE, complain))); if (code == POINTER_TYPE) - return fold_if_not_in_template (convert_to_pointer_force (type, e)); + return fold_if_not_in_template (convert_to_pointer_force (type, e, + complain)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR @@ -1446,9 +1463,9 @@ tree && TYPE_PTRMEMFUNC_P (type)) /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1, - /*c_cast_p=*/1, tf_warning_or_error); + /*c_cast_p=*/1, complain); - return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL); + return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL, complain); } /* Convert an aggregate EXPR to type XTYPE. If a conversion Index: cp/cp-tree.h =================================================================== --- cp/cp-tree.h (revision 188268) +++ cp/cp-tree.h (working copy) @@ -4371,16 +4371,13 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T behaviors relevant to them. */ /* Check for access violations. */ #define LOOKUP_PROTECT (1 << 0) -/* Complain if no suitable member function matching the arguments is - found. */ -#define LOOKUP_COMPLAIN (1 << 1) -#define LOOKUP_NORMAL (LOOKUP_PROTECT | LOOKUP_COMPLAIN) +#define LOOKUP_NORMAL (LOOKUP_PROTECT) /* Even if the function found by lookup is a virtual function, it should be called directly. */ -#define LOOKUP_NONVIRTUAL (1 << 2) +#define LOOKUP_NONVIRTUAL (1 << 1) /* Non-converting (i.e., "explicit") constructors are not tried. This flag indicates that we are not performing direct-initialization. */ -#define LOOKUP_ONLYCONVERTING (1 << 3) +#define LOOKUP_ONLYCONVERTING (1 << 2) #define LOOKUP_IMPLICIT (LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING) /* If a temporary is created, it should be created so that it lives as long as the current variable bindings; otherwise it only lives @@ -4388,20 +4385,20 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T direct-initialization in cases where other parts of the compiler have already generated a temporary, such as reference initialization and the catch parameter. */ -#define DIRECT_BIND (1 << 4) +#define DIRECT_BIND (1 << 3) /* We're performing a user-defined conversion, so more user-defined conversions are not permitted (only built-in conversions). */ -#define LOOKUP_NO_CONVERSION (1 << 5) +#define LOOKUP_NO_CONVERSION (1 << 4) /* The user has explicitly called a destructor. (Therefore, we do not need to check that the object is non-NULL before calling the destructor.) */ -#define LOOKUP_DESTRUCTOR (1 << 6) +#define LOOKUP_DESTRUCTOR (1 << 5) /* Do not permit references to bind to temporaries. */ -#define LOOKUP_NO_TEMP_BIND (1 << 7) +#define LOOKUP_NO_TEMP_BIND (1 << 6) /* Do not accept objects, and possibly namespaces. */ -#define LOOKUP_PREFER_TYPES (1 << 8) +#define LOOKUP_PREFER_TYPES (1 << 7) /* Do not accept objects, and possibly types. */ -#define LOOKUP_PREFER_NAMESPACES (1 << 9) +#define LOOKUP_PREFER_NAMESPACES (1 << 8) /* Accept types or namespaces. */ #define LOOKUP_PREFER_BOTH (LOOKUP_PREFER_TYPES | LOOKUP_PREFER_NAMESPACES) /* Return friend declarations and un-declared builtin functions. @@ -4894,7 +4891,9 @@ extern tree build_new_op (location_t, enum tree_ tsubst_flags_t); extern tree build_op_call (tree, VEC(tree,gc) **, tsubst_flags_t); -extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); +extern tree build_op_delete_call (enum tree_code, tree, tree, + bool, tree, tree, + tsubst_flags_t); extern bool can_convert (tree, tree, tsubst_flags_t); extern bool can_convert_arg (tree, tree, tree, int, tsubst_flags_t); @@ -5001,16 +5000,19 @@ extern void adjust_clone_args (tree); extern void deduce_noexcept_on_destructor (tree); /* in cvt.c */ -extern tree convert_to_reference (tree, tree, int, int, tree); +extern tree convert_to_reference (tree, tree, int, int, tree, + tsubst_flags_t); extern tree convert_from_reference (tree); extern tree force_rvalue (tree, tsubst_flags_t); -extern tree ocp_convert (tree, tree, int, int); -extern tree cp_convert (tree, tree); -extern tree cp_convert_and_check (tree, tree); +extern tree ocp_convert (tree, tree, int, int, + tsubst_flags_t); +extern tree cp_convert (tree, tree, tsubst_flags_t); +extern tree cp_convert_and_check (tree, tree, tsubst_flags_t); extern tree cp_fold_convert (tree, tree); extern tree convert_to_void (tree, impl_conv_void, tsubst_flags_t); -extern tree convert_force (tree, tree, int); +extern tree convert_force (tree, tree, int, + tsubst_flags_t); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); extern tree perform_qualification_conversions (tree, tree); @@ -5901,6 +5903,7 @@ extern void check_template_keyword (tree); extern bool check_raw_literal_operator (const_tree decl); extern bool check_literal_operator_args (const_tree, bool *, bool *); extern void maybe_warn_about_useless_cast (tree, tree, tsubst_flags_t); +extern tree cp_perform_integral_promotions (tree, tsubst_flags_t); /* in typeck2.c */ extern void require_complete_eh_spec_types (tree, tree); Index: cp/name-lookup.c =================================================================== --- cp/name-lookup.c (revision 188268) +++ cp/name-lookup.c (working copy) @@ -1854,7 +1854,7 @@ identifier_type_value_1 (tree id) return REAL_IDENTIFIER_TYPE_VALUE (id); /* Have to search for it. It must be on the global level, now. Ask lookup_name not to return non-types. */ - id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + id = lookup_name_real (id, 2, 1, /*block_p=*/true, 0, 0); if (id) return TREE_TYPE (id); return NULL_TREE; @@ -4345,7 +4345,6 @@ lookup_qualified_name (tree scope, tree name, bool { struct scope_binding binding = EMPTY_SCOPE_BINDING; - flags |= LOOKUP_COMPLAIN; if (is_type_p) flags |= LOOKUP_PREFER_TYPES; if (qualified_lookup_using_namespace (name, scope, &binding, flags)) @@ -4772,7 +4771,7 @@ lookup_name_real (tree name, int prefer_type, int tree lookup_name_nonclass (tree name) { - return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 1, /*block_p=*/true, 0, 0); } tree @@ -4780,22 +4779,20 @@ lookup_function_nonclass (tree name, VEC(tree,gc) { return lookup_arg_dependent (name, - lookup_name_real (name, 0, 1, block_p, 0, - LOOKUP_COMPLAIN), + lookup_name_real (name, 0, 1, block_p, 0, 0), args, false); } tree lookup_name (tree name) { - return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, 0, 0, /*block_p=*/true, 0, 0); } tree lookup_name_prefer_type (tree name, int prefer_type) { - return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, - 0, LOOKUP_COMPLAIN); + return lookup_name_real (name, prefer_type, 0, /*block_p=*/true, 0, 0); } /* Look up NAME for type used in elaborated name specifier in ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [C++ Patch] PR 53567 2012-06-06 17:12 ` Paolo Carlini @ 2012-06-06 18:48 ` Jason Merrill 0 siblings, 0 replies; 19+ messages in thread From: Jason Merrill @ 2012-06-06 18:48 UTC (permalink / raw) To: Paolo Carlini; +Cc: gcc-patches OK, thanks. Jason ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2012-06-06 18:42 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-06-04 14:17 [C++ Patch] PR 53567 Paolo Carlini 2012-06-04 18:12 ` Jason Merrill 2012-06-04 22:57 ` Paolo Carlini 2012-06-04 23:23 ` Jason Merrill 2012-06-04 23:47 ` Paolo Carlini 2012-06-05 0:24 ` Paolo Carlini 2012-06-05 2:11 ` Jason Merrill 2012-06-05 11:02 ` Paolo Carlini 2012-06-05 14:17 ` Jason Merrill 2012-06-05 16:18 ` Paolo Carlini 2012-06-05 16:34 ` Jason Merrill 2012-06-05 16:50 ` Paolo Carlini 2012-06-06 1:00 ` Paolo Carlini 2012-06-06 2:29 ` Jason Merrill 2012-06-06 9:33 ` Paolo Carlini 2012-06-06 10:23 ` Paolo Carlini 2012-06-06 16:17 ` Jason Merrill 2012-06-06 17:12 ` Paolo Carlini 2012-06-06 18:48 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).