diff options
32 files changed, 2877 insertions, 809 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 03f6332..05ece07 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2008-03-25 Douglas Gregor <doug.gregor@gmail.com> + + * c-common.c (c_sizeof_or_alignof_type): If we're not allowed to + complain when we hit an error, return ERROR_MARK_NODE. + 2008-03-25 Naveen.H.S <naveen.hs@kpitcummins.com> * config/sh/constraints.md (Pso, Psz): New constraints. diff --git a/gcc/c-common.c b/gcc/c-common.c index 2bc7434..1b62974 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -3347,6 +3347,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) { if (complain && (pedantic || warn_pointer_arith)) pedwarn ("invalid application of %<sizeof%> to a function type"); + else if (!complain) + return error_mark_node; value = size_one_node; } else @@ -3357,6 +3359,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) if (type_code == VOID_TYPE && complain && (pedantic || warn_pointer_arith)) pedwarn ("invalid application of %qs to a void type", op_name); + else if (!complain) + return error_mark_node; value = size_one_node; } else if (!COMPLETE_TYPE_P (type)) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ce147f7..c90f583 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,208 @@ +2008-03-25 Douglas Gregor <doug.gregor@gmail.com> + + * typeck.c (composite_pointer_type_r): Add SFINAE support. + (composite_pointer_type): Ditto. + (common_type): Fix call to composite_pointer_type. + (cxx_sizeof_nowarn): New; used to be a macro. + (cxx_sizeof_expr): Add SFINAE support. + (cxx_alignof_expr): Ditto. + (decay_conversion): Fix calls for SFINAE support. + (rationalize_conditional_expr): Add SFINAE support. + (build_class_member_access_expr): Ditto. + (finish_class_member_access_expr): Ditto. + (build_x_indirect_ref): Ditto. + (build_indirect_ref): Original version renamed to + cp_build_indirect_ref; new version provides a bridge from + c-common. + (cp_build_indirect_ref): Was build_indirect_ref; added SFINAE + support. + (get_member_function_from_ptrfunc): Fix calls for SFINAE support. + (build_function_call): Original version renamed to + cp_build_function_call; new version provides a bridge from + c-common. + (cp_build_function_call): Was build_function_call; added SFINAE + support. + (convert_arguments): Add SFINAE support. + (build_x_binary_op): Ditto. + (build_binary_op): Original version renamed to cp_build_binary_op; + new version provides a bridge from c-common. + (cp_build_binary_op): Was build_binary_op; added SFINAE support. + (pointer_diff): Fix calls for SFINAE. + (build_x_unary_op): Add SFINAE support. + (condition_conversion): Fix calls for SFINAE. + (build_unary_op): Original version renamed to cp_build_unary_op; + new version provides a bridge from c-common. + (cp_build_unary_op): Was build_unary_op; added SFINAE support. + (unary_complex_lvalue): Fix calls for SFINAE. + (build_x_conditional_expr): Add SFINAE support. + (build_x_compound_expr_from_list): Fix calls for SFINAE. + (build_x_compound_expr): Add SFINAE support. + (convert_ptrmem): Fix calls for SFINAE. + (build_static_cast_1): Add SFINAE support. + (build_static_cast): Ditto. + (build_reinterpret_cast_1): Ditto. + (build_reinterpret_cast): Ditto. + (build_const_cast_1): Ditto. + (build_const_cast): Ditto. + (build_c_cast): Ditto. + (build_modify_expr): Original version renamed to + cp_build_modify_expr; new version provides a bridge from c-common. + (cp_build_modify_expr): Was build_modify_expr; added SFINAE + support. + (build_x_modify_expr): Add SFINAE support. + (build_ptrmemfunc): Fix calls for SFINAE. + (convert_for_assignment): Add SFINAE support. + (convert_for_initialization): Ditto. + (check_return_expr): Fix calls for SFINAE. + (lvalue_or_else): Add SFINAE support. + * init.c (perform_member_init): Fix calls for SFINAE. + (emit_mem_initializers): Ditto. + (expand_virtual_init): Ditto. + (expand_cleanup_for_base): Ditto. + (build_aggr_init): Add SFINAE support. + (expand_default_init): Ditto. + (expand_aggr_init_1): Fix calls for SFINAE. + (build_offset_ref): Ditto. + (build_new_1): Add SFINAE support. + (build_new): Ditto. + (build_vec_delete_1): Fix calls for SFINAE. + (get_temp_regvar): Ditto. + (build_vec_init): Add SFINAE support. + (build_dtor_call): Fix calls for SFINAE. + (build_delete): Ditto. + (push_base_cleanups): Ditto. + (build_vec_delete_1): Ditto. + * class.c (build_base_path): Fix calls for SFINAE. + (build_simple_base_path): Ditto. + (convert_to_base_statically): Ditto. + (build_vfn_ref): Ditto. + (resolve_address_of_overloaded_function): Ditto. + * decl.c (check_initializer): Fix calls for SFINAE. + (register_dtor_fn): Ditto. + (compute_array_index_type): Ditto. + (finish_enum): Ditto. + (start_preparsed_function): Ditto. + (cxx_maybe_build_cleanup): Ditto. + * call.c (convert_like): Add COMPLAIN argument. + (convert_like_with_context): Ditto. + (build_this): Fix calls for SFINAE. + (build_user_type_conversion): Ditto. + (resolve_args): Ditto. + (build_new_function_call): Add SFINAE support. + (build_operator_new_call): Fix calls for SFINAE. + (build_object_call): Add SFINAE support. + (build_conditional_expr): Ditto. + (build_new_op): Ditto. + (build_op_delete_call): Fix calls for SFINAE. + (build_temp): Ditto. + (convert_like_real): Add SFINAE support. + (build_x_va_arg): Fix calls for SFINAE. + (convert_default_arg): Ditto. + (build_over_call): Add SFINAE support. + (build_java_interface_fn_ref): Fix calls for SFINAE. + (build_special_member_call): Add SFINAE support. + (build_new_method_call): Ditto. + (perform_implicit_conversion): Ditto. + (perform_direct_initialization_if_possible): Ditto. + (initialize_reference): Fix calls for SFINAE. + * method.c (do_build_assign_ref): Fix calls for SFINAE. + * rtti.c (build_headof): Fix calls for SFINAE. + (get_tinfo_decl_dynamic): Ditto. + (get_typeid): Ditto. + (build_dynamic_cast_1): Add SFINAE support. + (build_dynamic_cast): Ditto. + (tinfo_base_init): Fix calls for SFINAE. + * except.c (do_get_exception_ptr): Fix calls for SFINAE. + (do_end_catch): Ditto. + (initialize_handler_parm): Ditto. + (expand_start_catch_block): Ditto. + (do_allocate_exception): Ditto. + (do_free_exception): Ditto. + (build_throw): Ditto. + * cvt.c (build_up_reference): Fix calls for SFINAE. + (convert_to_reference): Ditto. + (ocp_convert): Ditto. + (convert_to_void): Add SFINAE support. + * tree.c (build_dummy_object): Fix calls for SFINAE. + (stabilize_expr): Ditto. + * cp-tree.h (build_conditional_expr): Add tsubst_flags_t + parameter. + (build_new_method_call): Ditto. + (build_special_member_call): Ditto. + (build_new_op): Ditto. + (perform_implicit_conversion): Ditto. + (perform_direct_initialization_if_possible): Ditto. + (convert_to_void): Ditto. + (build_aggr_init): Ditto. + (build_new): Ditto. + (build_vec_init): Ditto. + (build_dynamic_cast): Ditto. + (finish_call_expr): Ditto + (cxx_sizeof_or_alignof_expr): Add COMPLAIN parameter. + (cxx_sizeof_nowarn): Remove macro; add function declaration. + (build_class_member_access_expr): Add tsubst_flags_t parameter. + (finish_class_member_access_expr): Ditto. + (build_x_indirect_ref): Ditto. + (cp_build_indirect_ref): New. + (cp_build_function_call): Add tsubst_flags_t parameter. + (build_x_unary_op): Ditto. + (cp_build_unary_op): New. + (build_x_conditional_expr): Add tsubst_flags_t parameter. + (build_x_compound_expr): Ditto. + (build_compound_expr): Ditto. + (build_static_cast): Ditto. + (build_reinterpret_cast): Ditto. + (build_const_cast): Ditto. + (build_c_cast): Ditto. + (build_x_modify_expr): Ditto. + (cp_build_modify_expr): New. + (convert_for_initialization): Add tsubst_flags_t parameter. + (cp_build_binary_op): Remove macro; add function declaration. + (invalid_nonstatic_memfn_p): Add tsubst_flags_t parameter. + (lvalue_or_else): Ditto. + (build_functional_cast): Ditto. + * typeck2.c (digest_init): Fix calls for SFINAE. + (process_init_constructor_array): Ditto. + (process_init_constructor_record): Ditto. + (build_x_arrow): Ditto. + (build_m_component_ref): Ditto. + (build_functional_cast): Add SFINAE support. + * pt.c (tsubst_copy_and_build): Add (more) SFINAE support. + * semantics.c (simplify_loop_decl_cond): Fix calls for SFINAE. + (finish_expr_stmt): Ditto. + (finish_for_expr): Ditto. + (finish_asm_stmt): Ditto. + (finish_non_static_data_member): Ditto. + (finish_qualified_id_expr): Ditto. + (finish_call_expr): Add SFINAE support. + (finish_increment_expr): Fix calls for SFINAE. + (finish_unary_op_expr): Ditto. + (simplify_aggr_init_expr): Ditto. + (finish_omp_clauses): Ditto. + (finish_omp_for): Ditto. + (finish_omp_barrier): Ditto. + (finish_omo_flush): Ditto. + * decl2.c (grok_array_decl): Fix calls or SFINAE. + (build_anon_union_vars): Ditto. + (get_guard_cond): Ditto. + (set_guard): Ditto. + (one_static_initialization_or_destruction): Ditto. + (do_static_initialization_or_destruction): Ditto. + (generate_ctor_or_dtor_function): Ditto. + (build_offset_ref_call_from_tree): Ditto. + * parser.c (cp_parser_postfix_expression): Fix calls for SFINAE. + (cp_parser_postfix_dot_deref_expression): Ditto. + (cp_parser_unary_expression): Ditto. + (cp_parser_new_expression): Ditto. + (cp_parser_cast_expression): Ditto. + (cp_parser_binary_expression): Ditto. + (cp_parser_question_colon_clause): Ditto. + (cp_parser_assignment_expression): Ditto. + (cp_parser_expression): Ditto. + (cp_parser_builtin_offsetof): Ditto. + (cp_parser_template_argument): Ditto. + (cp_parser_functional_cast): Ditto. + 2008-03-24 Tom Tromey <tromey@redhat.com> * lex.c (handle_pragma_interface): Don't copy the filename. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 41e6933..29dda07 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -126,21 +126,21 @@ static struct z_candidate * tourney (struct z_candidate *); static int equal_functions (tree, tree); static int joust (struct z_candidate *, struct z_candidate *, bool); static int compare_ics (conversion *, conversion *); -static tree build_over_call (struct z_candidate *, int); +static tree build_over_call (struct z_candidate *, int, tsubst_flags_t); static tree build_java_interface_fn_ref (tree, tree); -#define convert_like(CONV, EXPR) \ +#define convert_like(CONV, EXPR, COMPLAIN) \ convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0, \ /*issue_conversion_warnings=*/true, \ - /*c_cast_p=*/false) -#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \ - convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \ - /*issue_conversion_warnings=*/true, \ - /*c_cast_p=*/false) + /*c_cast_p=*/false, (COMPLAIN)) +#define convert_like_with_context(CONV, EXPR, FN, ARGNO, COMPLAIN ) \ + convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0, \ + /*issue_conversion_warnings=*/true, \ + /*c_cast_p=*/false, (COMPLAIN)) static tree convert_like_real (conversion *, tree, tree, int, int, bool, - bool); + bool, tsubst_flags_t); static void op_error (enum tree_code, enum tree_code, tree, tree, tree, const char *); -static tree build_object_call (tree, tree); +static tree build_object_call (tree, tree, tsubst_flags_t); static tree resolve_args (tree); static struct z_candidate *build_user_type_conversion_1 (tree, tree, int); static void print_z_candidate (const char *, struct z_candidate *); @@ -2418,7 +2418,7 @@ build_this (tree obj) if (processing_template_decl) return build_address (obj); - return build_unary_op (ADDR_EXPR, obj, 0); + return cp_build_unary_op (ADDR_EXPR, obj, 0, tf_warning_or_error); } /* Returns true iff functions are equivalent. Equivalent functions are @@ -2750,7 +2750,7 @@ build_user_type_conversion (tree totype, tree expr, int flags) { if (cand->second_conv->kind == ck_ambig) return error_mark_node; - expr = convert_like (cand->second_conv, expr); + expr = convert_like (cand->second_conv, expr, tf_warning_or_error); return convert_from_reference (expr); } return NULL_TREE; @@ -2773,7 +2773,7 @@ resolve_args (tree args) error ("invalid use of void expression"); return error_mark_node; } - else if (invalid_nonstatic_memfn_p (arg)) + else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error)) return error_mark_node; } return args; @@ -2837,7 +2837,8 @@ perform_overload_resolution (tree fn, or a static member function) with the ARGS. */ tree -build_new_function_call (tree fn, tree args, bool koenig_p) +build_new_function_call (tree fn, tree args, bool koenig_p, + tsubst_flags_t complain) { struct z_candidate *candidates, *cand; bool any_viable_p; @@ -2858,8 +2859,9 @@ build_new_function_call (tree fn, tree args, bool koenig_p) fn = remove_hidden_names (fn); if (!fn) { - error ("no matching function for call to %<%D(%A)%>", - DECL_NAME (OVL_CURRENT (orig_fn)), args); + if (complain & tf_error) + error ("no matching function for call to %<%D(%A)%>", + DECL_NAME (OVL_CURRENT (orig_fn)), args); return error_mark_node; } } @@ -2871,22 +2873,25 @@ build_new_function_call (tree fn, tree args, bool koenig_p) if (!cand) { - if (!any_viable_p && candidates && ! candidates->next) - return build_function_call (candidates->fn, args); - if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - fn = TREE_OPERAND (fn, 0); - if (!any_viable_p) - error ("no matching function for call to %<%D(%A)%>", - DECL_NAME (OVL_CURRENT (fn)), args); - else - error ("call of overloaded %<%D(%A)%> is ambiguous", - DECL_NAME (OVL_CURRENT (fn)), args); - if (candidates) - print_z_candidates (candidates); + if (complain & tf_error) + { + if (!any_viable_p && candidates && ! candidates->next) + return cp_build_function_call (candidates->fn, args, complain); + if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) + fn = TREE_OPERAND (fn, 0); + if (!any_viable_p) + error ("no matching function for call to %<%D(%A)%>", + DECL_NAME (OVL_CURRENT (fn)), args); + else + error ("call of overloaded %<%D(%A)%> is ambiguous", + DECL_NAME (OVL_CURRENT (fn)), args); + if (candidates) + print_z_candidates (candidates); + } result = error_mark_node; } else - result = build_over_call (cand, LOOKUP_NORMAL); + result = build_over_call (cand, LOOKUP_NORMAL, complain); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); @@ -2997,11 +3002,11 @@ build_operator_new_call (tree fnname, tree args, *fn = cand->fn; /* Build the CALL_EXPR. */ - return build_over_call (cand, LOOKUP_NORMAL); + return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error); } static tree -build_object_call (tree obj, tree args) +build_object_call (tree obj, tree args, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; tree fns, convs, mem_args = NULL_TREE; @@ -3012,9 +3017,10 @@ build_object_call (tree obj, tree args) if (TYPE_PTRMEMFUNC_P (type)) { - /* It's no good looking for an overloaded operator() on a - pointer-to-member-function. */ - error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj); + if (complain & tf_error) + /* It's no good looking for an overloaded operator() on a + pointer-to-member-function. */ + error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj); return error_mark_node; } @@ -3088,8 +3094,11 @@ build_object_call (tree obj, tree args) candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { - error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args); - print_z_candidates (candidates); + if (complain & tf_error) + { + error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args); + print_z_candidates (candidates); + } result = error_mark_node; } else @@ -3097,8 +3106,12 @@ build_object_call (tree obj, tree args) cand = tourney (candidates); if (cand == 0) { - error ("call of %<(%T) (%A)%> is ambiguous", TREE_TYPE (obj), args); - print_z_candidates (candidates); + if (complain & tf_error) + { + error ("call of %<(%T) (%A)%> is ambiguous", + TREE_TYPE (obj), args); + print_z_candidates (candidates); + } result = error_mark_node; } /* Since cand->fn will be a type, not a function, for a conversion @@ -3106,12 +3119,13 @@ build_object_call (tree obj, tree args) DECL_NAME here. */ else if (TREE_CODE (cand->fn) == FUNCTION_DECL && DECL_OVERLOADED_OPERATOR_P (cand->fn) == CALL_EXPR) - result = build_over_call (cand, LOOKUP_NORMAL); + result = build_over_call (cand, LOOKUP_NORMAL, complain); else { - obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1); + obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1, + complain); obj = convert_from_reference (obj); - result = build_function_call (obj, args); + result = cp_build_function_call (obj, args, complain); } } @@ -3232,7 +3246,8 @@ conditional_conversion (tree e1, tree e2) arguments to the conditional expression. */ tree -build_conditional_expr (tree arg1, tree arg2, tree arg3) +build_conditional_expr (tree arg1, tree arg2, tree arg3, + tsubst_flags_t complain) { tree arg2_type; tree arg3_type; @@ -3249,7 +3264,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) calculated only once. */ if (!arg2) { - if (pedantic) + if (pedantic && (complain & tf_error)) pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression"); /* Make sure that lvalues remain lvalues. See g++.oliva/ext1.C. */ @@ -3263,7 +3278,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) The first expr ession is implicitly converted to bool (clause _conv_). */ - arg1 = perform_implicit_conversion (boolean_type_node, arg1); + arg1 = perform_implicit_conversion (boolean_type_node, arg1, complain); /* If something has already gone wrong, just pass that fact up the tree. */ @@ -3327,16 +3342,19 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) result_type = void_type_node; else { - if (VOID_TYPE_P (arg2_type)) - error ("second operand to the conditional operator " - "is of type %<void%>, " - "but the third operand is neither a throw-expression " - "nor of type %<void%>"); - else - error ("third operand to the conditional operator " - "is of type %<void%>, " - "but the second operand is neither a throw-expression " - "nor of type %<void%>"); + if (complain & tf_error) + { + if (VOID_TYPE_P (arg2_type)) + error ("second operand to the conditional operator " + "is of type %<void%>, " + "but the third operand is neither a throw-expression " + "nor of type %<void%>"); + else + error ("third operand to the conditional operator " + "is of type %<void%>, " + "but the second operand is neither a throw-expression " + "nor of type %<void%>"); + } return error_mark_node; } @@ -3380,7 +3398,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) } else if (conv2 && (!conv2->bad_p || !conv3)) { - arg2 = convert_like (conv2, arg2); + arg2 = convert_like (conv2, arg2, complain); arg2 = convert_from_reference (arg2); arg2_type = TREE_TYPE (arg2); /* Even if CONV2 is a valid conversion, the result of the @@ -3393,7 +3411,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) } else if (conv3 && (!conv3->bad_p || !conv2)) { - arg3 = convert_like (conv3, arg3); + arg3 = convert_like (conv3, arg3, complain); arg3 = convert_from_reference (arg3); arg3_type = TREE_TYPE (arg3); if (error_operand_p (arg3)) @@ -3477,15 +3495,21 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { - op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match"); - print_z_candidates (candidates); + if (complain & tf_error) + { + op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); + } return error_mark_node; } cand = tourney (candidates); if (!cand) { - op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match"); - print_z_candidates (candidates); + if (complain & tf_error) + { + op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match"); + print_z_candidates (candidates); + } return error_mark_node; } @@ -3495,11 +3519,11 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) the converted operands are used in place of the original operands for the remainder of this section. */ conv = cand->convs[0]; - arg1 = convert_like (conv, arg1); + arg1 = convert_like (conv, arg1, complain); conv = cand->convs[1]; - arg2 = convert_like (conv, arg2); + arg2 = convert_like (conv, arg2, complain); conv = cand->convs[2]; - arg3 = convert_like (conv, arg3); + arg3 = convert_like (conv, arg3, complain); } /* [expr.cond] @@ -3548,17 +3572,25 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) if (TREE_CODE (arg2_type) == ENUMERAL_TYPE && TREE_CODE (arg3_type) == ENUMERAL_TYPE) - warning (0, "enumeral mismatch in conditional expression: %qT vs %qT", - arg2_type, arg3_type); + { + if (complain & tf_warning) + warning (0, + "enumeral mismatch in conditional expression: %qT vs %qT", + arg2_type, arg3_type); + } else if (extra_warnings && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE && !same_type_p (arg3_type, type_promotes_to (arg2_type))) || (TREE_CODE (arg3_type) == ENUMERAL_TYPE && !same_type_p (arg2_type, type_promotes_to (arg3_type))))) - warning (0, "enumeral and non-enumeral type in conditional expression"); + { + if (complain & tf_warning) + warning (0, + "enumeral and non-enumeral type in conditional expression"); + } - arg2 = perform_implicit_conversion (result_type, arg2); - arg3 = perform_implicit_conversion (result_type, arg3); + arg2 = perform_implicit_conversion (result_type, arg2, complain); + arg3 = perform_implicit_conversion (result_type, arg3, complain); } /* [expr.cond] @@ -3585,17 +3617,19 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3) || (TYPE_PTRMEMFUNC_P (arg2_type) && TYPE_PTRMEMFUNC_P (arg3_type))) { result_type = composite_pointer_type (arg2_type, arg3_type, arg2, - arg3, "conditional expression"); + arg3, "conditional expression", + complain); if (result_type == error_mark_node) return error_mark_node; - arg2 = perform_implicit_conversion (result_type, arg2); - arg3 = perform_implicit_conversion (result_type, arg3); + arg2 = perform_implicit_conversion (result_type, arg2, complain); + arg3 = perform_implicit_conversion (result_type, arg3, complain); } if (!result_type) { - error ("operands to ?: have different types %qT and %qT", - arg2_type, arg3_type); + if (complain & tf_error) + error ("operands to ?: have different types %qT and %qT", + arg2_type, arg3_type); return error_mark_node; } @@ -3707,7 +3741,7 @@ add_candidates (tree fns, tree args, tree build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, - bool *overloaded_p) + bool *overloaded_p, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; tree arglist, fnname; @@ -3747,7 +3781,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, gcc_unreachable (); case CALL_EXPR: - return build_object_call (arg1, arg2); + return build_object_call (arg1, arg2, complain); case TRUTH_ORIF_EXPR: case TRUTH_ANDIF_EXPR: @@ -3856,6 +3890,11 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, { case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: + /* Don't try anything fancy if we're not allowed to produce + errors. */ + if (!(complain & tf_error)) + return error_mark_node; + /* Look for an `operator++ (int)'. If they didn't have one, then we fall back to the old way of doing things. */ if (flags & LOOKUP_COMPLAIN) @@ -3868,7 +3907,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, else code = PREDECREMENT_EXPR; result = build_new_op (code, flags, arg1, NULL_TREE, NULL_TREE, - overloaded_p); + overloaded_p, complain); break; /* The caller will deal with these. */ @@ -3880,7 +3919,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, break; default: - if (flags & LOOKUP_COMPLAIN) + if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) { op_error (code, code2, arg1, arg2, arg3, "no match"); print_z_candidates (candidates); @@ -3894,7 +3933,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, cand = tourney (candidates); if (cand == 0) { - if (flags & LOOKUP_COMPLAIN) + if ((flags & LOOKUP_COMPLAIN) && (complain & tf_error)) { op_error (code, code2, arg1, arg2, arg3, "ambiguous overload"); print_z_candidates (candidates); @@ -3909,12 +3948,12 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, if (resolve_args (arglist) == error_mark_node) result = error_mark_node; else - result = build_over_call (cand, LOOKUP_NORMAL); + result = build_over_call (cand, LOOKUP_NORMAL, complain); } else { /* Give any warnings we noticed during overload resolution. */ - if (cand->warnings) + if (cand->warnings && (complain & tf_warning)) { struct candidate_warning *w; for (w = cand->warnings; w; w = w->next) @@ -3933,7 +3972,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, if (TREE_CODE (TREE_TYPE (arg1)) == ENUMERAL_TYPE && TREE_CODE (TREE_TYPE (arg2)) == ENUMERAL_TYPE && (TYPE_MAIN_VARIANT (TREE_TYPE (arg1)) - != TYPE_MAIN_VARIANT (TREE_TYPE (arg2)))) + != TYPE_MAIN_VARIANT (TREE_TYPE (arg2))) + && (complain & tf_warning)) { warning (0, "comparison between %q#T and %q#T", TREE_TYPE (arg1), TREE_TYPE (arg2)); @@ -3950,25 +3990,26 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, conv = cand->convs[0]; if (conv->kind == ck_ref_bind) conv = conv->u.next; - arg1 = convert_like (conv, arg1); + arg1 = convert_like (conv, arg1, complain); if (arg2) { conv = cand->convs[1]; if (conv->kind == ck_ref_bind) conv = conv->u.next; - arg2 = convert_like (conv, arg2); + arg2 = convert_like (conv, arg2, complain); } if (arg3) { conv = cand->convs[2]; if (conv->kind == ck_ref_bind) conv = conv->u.next; - arg3 = convert_like (conv, arg3); + arg3 = convert_like (conv, arg3, complain); } if (!expl_eq_arg1) { - warn_logical_operator (code, arg1, arg2); + if (complain & tf_warning) + warn_logical_operator (code, arg1, arg2); expl_eq_arg1 = true; } } @@ -3986,10 +4027,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, switch (code) { case MODIFY_EXPR: - return build_modify_expr (arg1, code2, arg2); + return cp_build_modify_expr (arg1, code2, arg2, complain); case INDIRECT_REF: - return build_indirect_ref (arg1, "unary *"); + return cp_build_indirect_ref (arg1, "unary *", complain); case TRUTH_ANDIF_EXPR: case TRUTH_ORIF_EXPR: @@ -4015,7 +4056,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, case BIT_AND_EXPR: case BIT_IOR_EXPR: case BIT_XOR_EXPR: - return cp_build_binary_op (code, arg1, arg2); + return cp_build_binary_op (code, arg1, arg2, complain); case UNARY_PLUS_EXPR: case NEGATE_EXPR: @@ -4027,16 +4068,18 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, case POSTDECREMENT_EXPR: case REALPART_EXPR: case IMAGPART_EXPR: - return build_unary_op (code, arg1, candidates != 0); + return cp_build_unary_op (code, arg1, candidates != 0, complain); case ARRAY_REF: return build_array_ref (arg1, arg2); case COND_EXPR: - return build_conditional_expr (arg1, arg2, arg3); + return build_conditional_expr (arg1, arg2, arg3, complain); case MEMBER_REF: - return build_m_component_ref (build_indirect_ref (arg1, NULL), arg2); + return build_m_component_ref (cp_build_indirect_ref (arg1, NULL, + complain), + arg2); /* The caller will deal with these. */ case ADDR_EXPR: @@ -4205,7 +4248,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, else args = tree_cons (NULL_TREE, addr, build_tree_list (NULL_TREE, size)); - return build_function_call (fn, args); + return cp_build_function_call (fn, args, tf_warning_or_error); } } @@ -4268,7 +4311,7 @@ build_temp (tree expr, tree type, int flags, expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), - type, flags); + type, flags, tf_warning_or_error); if (warningcount > savew) *diagnostic_fn = warning0; else if (errorcount > savee) @@ -4317,7 +4360,7 @@ conversion_null_warnings (tree totype, tree expr, tree fn, int argnum) static tree convert_like_real (conversion *convs, tree expr, tree fn, int argnum, int inner, bool issue_conversion_warnings, - bool c_cast_p) + bool c_cast_p, tsubst_flags_t complain) { tree totype = convs->type; diagnostic_fn_t diagnostic_fn; @@ -4335,23 +4378,31 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, { expr = convert_like_real (t, expr, fn, argnum, 1, /*issue_conversion_warnings=*/false, - /*c_cast_p=*/false); + /*c_cast_p=*/false, + complain); break; } else if (t->kind == ck_ambig) return convert_like_real (t, expr, fn, argnum, 1, /*issue_conversion_warnings=*/false, - /*c_cast_p=*/false); + /*c_cast_p=*/false, + complain); else if (t->kind == ck_identity) break; } - permerror ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype); - if (fn) - permerror (" initializing argument %P of %qD", argnum, fn); + if (complain & tf_error) + { + permerror ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype); + if (fn) + permerror (" initializing argument %P of %qD", argnum, fn); + } + else + return error_mark_node; + return cp_convert (totype, expr); } - if (issue_conversion_warnings) + if (issue_conversion_warnings && (complain & tf_warning)) conversion_null_warnings (totype, expr, fn, argnum); switch (convs->kind) @@ -4367,7 +4418,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, for (i = 0; i < cand->num_convs; ++i) cand->convs[i]->user_conv_p = true; - expr = build_over_call (cand, LOOKUP_NORMAL); + expr = build_over_call (cand, LOOKUP_NORMAL, complain); /* If this is a constructor or a function returning an aggr type, we need to build up a TARGET_EXPR. */ @@ -4394,7 +4445,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION, &diagnostic_fn)); - if (diagnostic_fn) + if (diagnostic_fn && (complain & tf_error)) { if (fn) diagnostic_fn @@ -4410,7 +4461,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, } case ck_identity: if (type_unknown_p (expr)) - expr = instantiate_type (totype, expr, tf_warning_or_error); + expr = instantiate_type (totype, expr, complain); /* Convert a constant to its underlying value, unless we are about to bind it to a reference, in which case we need to leave it as an lvalue. */ @@ -4436,7 +4487,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, expr = convert_like_real (convs->u.next, expr, fn, argnum, convs->kind == ck_ref_bind ? -1 : 1, convs->kind == ck_ref_bind ? issue_conversion_warnings : false, - c_cast_p); + c_cast_p, + complain); if (expr == error_mark_node) return error_mark_node; @@ -4453,10 +4505,10 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, /* We are going to bind a reference directly to a base-class subobject of EXPR. */ /* Build an expression for `*((base*) &expr)'. */ - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain); expr = convert_to_base (expr, build_pointer_type (totype), !c_cast_p, /*nonnull=*/true); - expr = build_indirect_ref (expr, "implicit conversion"); + expr = cp_build_indirect_ref (expr, "implicit conversion", complain); return expr; } @@ -4470,7 +4522,12 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, flags |= LOOKUP_NO_CONVERSION; expr = build_temp (expr, totype, flags, &diagnostic_fn); if (diagnostic_fn && fn) - diagnostic_fn (" initializing argument %P of %qD", argnum, fn); + { + if ((complain & tf_error)) + diagnostic_fn (" initializing argument %P of %qD", argnum, fn); + else if (diagnostic_fn == error) + return error_mark_node; + } return build_cplus_new (totype, expr); case ck_ref_bind: @@ -4482,7 +4539,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, VA_ARG_EXPR and CONSTRUCTOR expressions are special cases that need temporaries, even when their types are reference compatible with the type of reference being bound, so the - upcoming call to build_unary_op (ADDR_EXPR, expr, ...) + upcoming call to cp_build_unary_op (ADDR_EXPR, expr, ...) doesn't fail. */ if (convs->need_temporary_p || TREE_CODE (expr) == CONSTRUCTOR @@ -4494,16 +4551,19 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)) && !TYPE_REF_IS_RVALUE (ref_type)) { - /* If the reference is volatile or non-const, we - cannot create a temporary. */ - if (lvalue & clk_bitfield) - error ("cannot bind bitfield %qE to %qT", - expr, ref_type); - else if (lvalue & clk_packed) - error ("cannot bind packed field %qE to %qT", - expr, ref_type); - else - error ("cannot bind rvalue %qE to %qT", expr, ref_type); + if (complain & tf_error) + { + /* If the reference is volatile or non-const, we + cannot create a temporary. */ + if (lvalue & clk_bitfield) + error ("cannot bind bitfield %qE to %qT", + expr, ref_type); + else if (lvalue & clk_packed) + error ("cannot bind packed field %qE to %qT", + expr, ref_type); + else + error ("cannot bind rvalue %qE to %qT", expr, ref_type); + } return error_mark_node; } /* If the source is a packed field, and we must use a copy @@ -4516,8 +4576,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, && CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_INIT_REF (type)) { - error ("cannot bind packed field %qE to %qT", - expr, ref_type); + if (complain & tf_error) + error ("cannot bind packed field %qE to %qT", + expr, ref_type); return error_mark_node; } if (lvalue & clk_bitfield) @@ -4527,7 +4588,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, /* Take the address of the thing to which we will bind the reference. */ - expr = build_unary_op (ADDR_EXPR, expr, 1); + expr = cp_build_unary_op (ADDR_EXPR, expr, 1, complain); if (expr == error_mark_node) return error_mark_node; @@ -4652,7 +4713,7 @@ build_x_va_arg (tree expr, tree type) expr = convert (build_pointer_type (type1), null_node); expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), call_builtin_trap (), expr); - expr = build_indirect_ref (expr, NULL); + expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error); return expr; } @@ -4719,7 +4780,8 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) { arg = digest_init (type, arg); arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, - "default argument", fn, parmnum); + "default argument", fn, parmnum, + tf_warning_or_error); } else { @@ -4732,7 +4794,8 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum) if (!CONSTANT_CLASS_P (arg)) arg = unshare_expr (arg); arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL, - "default argument", fn, parmnum); + "default argument", fn, parmnum, + tf_warning_or_error); arg = convert_for_arg_passing (type, arg); } @@ -4845,7 +4908,7 @@ magic_varargs_p (tree fn) bitmask of various LOOKUP_* flags which apply to the call itself. */ static tree -build_over_call (struct z_candidate *cand, int flags) +build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) { tree fn = cand->fn; tree args = cand->args; @@ -4957,8 +5020,13 @@ build_over_call (struct z_candidate *cand, int flags) tree base_binfo; if (convs[i]->bad_p) - permerror ("passing %qT as %<this%> argument of %q#D discards qualifiers", - TREE_TYPE (argtype), fn); + { + if (complain & tf_error) + permerror ("passing %qT as %<this%> argument of %q#D discards qualifiers", + TREE_TYPE (argtype), fn); + else + return error_mark_node; + } /* [class.mfct.nonstatic]: If a nonstatic member function of a class X is called for an object that is not of type X, or of a type @@ -5008,10 +5076,13 @@ build_over_call (struct z_candidate *cand, int flags) conv = conv->u.next; val = convert_like_with_context - (conv, TREE_VALUE (arg), fn, i - is_method); + (conv, TREE_VALUE (arg), fn, i - is_method, complain); val = convert_for_arg_passing (type, val); - argarray[j++] = val; + if ((complain == tf_none) && val == error_mark_node) + return error_mark_node; + else + argarray[j++] = val; } /* Default arguments */ @@ -5067,7 +5138,7 @@ build_over_call (struct z_candidate *cand, int flags) if (targ) arg = targ; else - arg = build_indirect_ref (arg, 0); + arg = cp_build_indirect_ref (arg, 0, complain); /* [class.copy]: the copy constructor is implicitly defined even if the implementation elided its use. */ @@ -5091,7 +5162,7 @@ build_over_call (struct z_candidate *cand, int flags) && !move_fn_p (fn))) { tree to = stabilize_reference - (build_indirect_ref (TREE_VALUE (args), 0)); + (cp_build_indirect_ref (TREE_VALUE (args), 0, complain)); val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg); return val; @@ -5102,14 +5173,14 @@ build_over_call (struct z_candidate *cand, int flags) && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn))) { tree to = stabilize_reference - (build_indirect_ref (argarray[0], 0)); + (cp_build_indirect_ref (argarray[0], 0, complain)); tree type = TREE_TYPE (to); tree as_base = CLASSTYPE_AS_BASE (type); arg = argarray[1]; if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) { - arg = build_indirect_ref (arg, 0); + arg = cp_build_indirect_ref (arg, 0, complain); val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg); } else @@ -5121,12 +5192,12 @@ build_over_call (struct z_candidate *cand, int flags) arg2 = TYPE_SIZE_UNIT (as_base); arg1 = arg; - arg0 = build_unary_op (ADDR_EXPR, to, 0); + arg0 = cp_build_unary_op (ADDR_EXPR, to, 0, complain); t = implicit_built_in_decls[BUILT_IN_MEMCPY]; t = build_call_n (t, 3, arg0, arg1, arg2); t = convert (TREE_TYPE (arg0), t); - val = build_indirect_ref (t, 0); + val = cp_build_indirect_ref (t, 0, complain); } return val; @@ -5227,7 +5298,8 @@ build_java_interface_fn_ref (tree fn, tree instance) /* Look up the pointer to the runtime java.lang.Class object for `instance'. This is the first entry in the vtable. */ - klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0), + klass_ref = build_vtbl_ref (cp_build_indirect_ref (instance, 0, + tf_warning_or_error), integer_zero_node); /* Get the java.lang.Class pointer for the interface being called. */ @@ -5300,7 +5372,7 @@ in_charge_arg_for_name (tree name) tree build_special_member_call (tree instance, tree name, tree args, - tree binfo, int flags) + tree binfo, int flags, tsubst_flags_t complain) { tree fns; /* The type of the subobject to be constructed or destroyed. */ @@ -5390,7 +5462,8 @@ build_special_member_call (tree instance, tree name, tree args, return build_new_method_call (instance, fns, args, TYPE_BINFO (BINFO_TYPE (binfo)), - flags, /*fn=*/NULL); + flags, /*fn=*/NULL, + complain); } /* Return the NAME, as a C string. The NAME indicates a function that @@ -5444,7 +5517,7 @@ name_as_c_string (tree name, tree type, bool *free_p) tree build_new_method_call (tree instance, tree fns, tree args, tree conversion_path, int flags, - tree *fn_p) + tree *fn_p, tsubst_flags_t complain) { struct z_candidate *candidates = 0, *cand; tree explicit_targs = NULL_TREE; @@ -5477,7 +5550,8 @@ build_new_method_call (tree instance, tree fns, tree args, if (!BASELINK_P (fns)) { - error ("call to non-function %qD", fns); + if (complain & tf_error) + error ("call to non-function %qD", fns); return error_mark_node; } @@ -5594,21 +5668,24 @@ build_new_method_call (tree instance, tree fns, tree args, candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) { - if (!COMPLETE_TYPE_P (basetype)) - cxx_incomplete_type_error (instance_ptr, basetype); - else + if (complain & tf_error) { - char *pretty_name; - bool free_p; - - pretty_name = name_as_c_string (name, basetype, &free_p); - error ("no matching function for call to %<%T::%s(%A)%#V%>", - basetype, pretty_name, user_args, - TREE_TYPE (TREE_TYPE (instance_ptr))); - if (free_p) - free (pretty_name); + if (!COMPLETE_TYPE_P (basetype)) + cxx_incomplete_type_error (instance_ptr, basetype); + else + { + char *pretty_name; + bool free_p; + + pretty_name = name_as_c_string (name, basetype, &free_p); + error ("no matching function for call to %<%T::%s(%A)%#V%>", + basetype, pretty_name, user_args, + TREE_TYPE (TREE_TYPE (instance_ptr))); + if (free_p) + free (pretty_name); + } + print_z_candidates (candidates); } - print_z_candidates (candidates); call = error_mark_node; } else @@ -5619,12 +5696,15 @@ build_new_method_call (tree instance, tree fns, tree args, char *pretty_name; bool free_p; - pretty_name = name_as_c_string (name, basetype, &free_p); - error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name, - user_args); - print_z_candidates (candidates); - if (free_p) - free (pretty_name); + if (complain & tf_error) + { + pretty_name = name_as_c_string (name, basetype, &free_p); + error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name, + user_args); + print_z_candidates (candidates); + if (free_p) + free (pretty_name); + } call = error_mark_node; } else @@ -5635,7 +5715,8 @@ build_new_method_call (tree instance, tree fns, tree args, && DECL_PURE_VIRTUAL_P (fn) && instance == current_class_ref && (DECL_CONSTRUCTOR_P (current_function_decl) - || DECL_DESTRUCTOR_P (current_function_decl))) + || DECL_DESTRUCTOR_P (current_function_decl)) + && (complain & tf_warning)) /* This is not an error, it is runtime undefined behavior. */ warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ? @@ -5646,8 +5727,9 @@ build_new_method_call (tree instance, tree fns, tree args, if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE && is_dummy_object (instance_ptr)) { - error ("cannot call member function %qD without object", - fn); + if (complain & tf_error) + error ("cannot call member function %qD without object", + fn); call = error_mark_node; } else @@ -5659,7 +5741,7 @@ build_new_method_call (tree instance, tree fns, tree args, if (fn_p) *fn_p = fn; /* Build the actual CALL_EXPR. */ - call = build_over_call (cand, flags); + call = build_over_call (cand, flags, complain); /* In an expression of the form `a->f()' where `f' turns out to be a static member function, `a' is none-the-less evaluated. */ @@ -6608,7 +6690,7 @@ can_convert_arg_bad (tree to, tree from, tree arg) doing a bad conversion, convert_like will complain. */ tree -perform_implicit_conversion (tree type, tree expr) +perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain) { conversion *conv; void *p; @@ -6624,7 +6706,8 @@ perform_implicit_conversion (tree type, tree expr) LOOKUP_NORMAL); if (!conv) { - error ("could not convert %qE to %qT", expr, type); + if (complain & tf_error) + error ("could not convert %qE to %qT", expr, type); expr = error_mark_node; } else if (processing_template_decl) @@ -6636,7 +6719,7 @@ perform_implicit_conversion (tree type, tree expr) expr = build_nop (type, expr); } else - expr = convert_like (conv, expr); + expr = convert_like (conv, expr, complain); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); @@ -6655,7 +6738,8 @@ perform_implicit_conversion (tree type, tree expr) tree perform_direct_initialization_if_possible (tree type, tree expr, - bool c_cast_p) + bool c_cast_p, + tsubst_flags_t complain) { conversion *conv; void *p; @@ -6674,7 +6758,7 @@ perform_direct_initialization_if_possible (tree type, { expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, expr), - type, LOOKUP_NORMAL); + type, LOOKUP_NORMAL, complain); return build_cplus_new (type, expr); } @@ -6689,7 +6773,8 @@ perform_direct_initialization_if_possible (tree type, else expr = convert_like_real (conv, expr, NULL_TREE, 0, 0, /*issue_conversion_warnings=*/false, - c_cast_p); + c_cast_p, + tf_warning_or_error); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); @@ -6824,7 +6909,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) /*fn=*/NULL_TREE, /*argnum=*/0, /*inner=*/-1, /*issue_conversion_warnings=*/true, - /*c_cast_p=*/false); + /*c_cast_p=*/false, + tf_warning_or_error); if (error_operand_p (expr)) expr = error_mark_node; else @@ -6897,17 +6983,18 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup) } else /* Take the address of EXPR. */ - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error); /* If a BASE_CONV was required, perform it now. */ if (base_conv_type) expr = (perform_implicit_conversion - (build_pointer_type (base_conv_type), expr)); + (build_pointer_type (base_conv_type), expr, + tf_warning_or_error)); expr = build_nop (type, expr); } } else /* Perform the conversion. */ - expr = convert_like (conv, expr); + expr = convert_like (conv, expr, tf_warning_or_error); /* Free all the conversions we allocated. */ obstack_free (&conversion_obstack, p); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 154c3b3..69acf11 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -284,7 +284,7 @@ build_base_path (enum tree_code code, if (!want_pointer) /* This must happen before the call to save_expr. */ - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error); offset = BINFO_OFFSET (binfo); fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull); @@ -345,7 +345,7 @@ build_base_path (enum tree_code code, interesting to the optimizers anyway. */ && !has_empty) { - expr = build_indirect_ref (expr, NULL); + expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error); expr = build_simple_base_path (expr, binfo); if (want_pointer) expr = build_address (expr); @@ -370,10 +370,12 @@ build_base_path (enum tree_code code, t = TREE_TYPE (TYPE_VFIELD (current_class_type)); t = build_pointer_type (t); v_offset = convert (t, current_vtt_parm); - v_offset = build_indirect_ref (v_offset, NULL); + v_offset = cp_build_indirect_ref (v_offset, NULL, + tf_warning_or_error); } else - v_offset = build_vfield_ref (build_indirect_ref (expr, NULL), + v_offset = build_vfield_ref (cp_build_indirect_ref (expr, NULL, + tf_warning_or_error), TREE_TYPE (TREE_TYPE (expr))); v_offset = build2 (POINTER_PLUS_EXPR, TREE_TYPE (v_offset), @@ -381,7 +383,7 @@ build_base_path (enum tree_code code, v_offset = build1 (NOP_EXPR, build_pointer_type (ptrdiff_type_node), v_offset); - v_offset = build_indirect_ref (v_offset, NULL); + v_offset = cp_build_indirect_ref (v_offset, NULL, tf_warning_or_error); TREE_CONSTANT (v_offset) = 1; TREE_INVARIANT (v_offset) = 1; @@ -425,7 +427,7 @@ build_base_path (enum tree_code code, null_test = NULL; if (!want_pointer) - expr = build_indirect_ref (expr, NULL); + expr = cp_build_indirect_ref (expr, NULL, tf_warning_or_error); out: if (null_test) @@ -459,7 +461,7 @@ build_simple_base_path (tree expr, tree binfo) in the back end. */ temp = unary_complex_lvalue (ADDR_EXPR, expr); if (temp) - expr = build_indirect_ref (temp, NULL); + expr = cp_build_indirect_ref (temp, NULL, tf_warning_or_error); return expr; } @@ -551,7 +553,8 @@ convert_to_base_statically (tree expr, tree base) when processing a template because they do not handle C++-specific trees. */ gcc_assert (!processing_template_decl); - expr = build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1); + expr = cp_build_unary_op (ADDR_EXPR, expr, /*noconvert=*/1, + tf_warning_or_error); if (!integer_zerop (BINFO_OFFSET (base))) expr = fold_build2 (POINTER_PLUS_EXPR, pointer_type, expr, fold_convert (sizetype, BINFO_OFFSET (base))); @@ -648,13 +651,16 @@ build_vfn_ref (tree instance_ptr, tree idx) { tree aref; - aref = build_vtbl_ref_1 (build_indirect_ref (instance_ptr, 0), idx); + aref = build_vtbl_ref_1 (cp_build_indirect_ref (instance_ptr, 0, + tf_warning_or_error), + idx); /* When using function descriptors, the address of the vtable entry is treated as a function pointer. */ if (TARGET_VTABLE_USES_DESCRIPTORS) aref = build1 (NOP_EXPR, TREE_TYPE (aref), - build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1)); + cp_build_unary_op (ADDR_EXPR, aref, /*noconvert=*/1, + tf_warning_or_error)); /* Remember this as a method reference, for later devirtualization. */ aref = build3 (OBJ_TYPE_REF, TREE_TYPE (aref), aref, instance_ptr, idx); @@ -6098,10 +6104,10 @@ resolve_address_of_overloaded_function (tree target_type, } if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type)) - return build_unary_op (ADDR_EXPR, fn, 0); + return cp_build_unary_op (ADDR_EXPR, fn, 0, flags); else { - /* The target must be a REFERENCE_TYPE. Above, build_unary_op + /* The target must be a REFERENCE_TYPE. Above, cp_build_unary_op will mark the function as addressed, but here we must do it explicitly. */ cxx_mark_addressable (fn); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9afeed7..8387fd7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4061,7 +4061,8 @@ extern cp_parameter_declarator *no_parameters; extern bool check_dtor_name (tree, tree); extern tree build_vfield_ref (tree, tree); -extern tree build_conditional_expr (tree, tree, tree); +extern tree build_conditional_expr (tree, tree, tree, + tsubst_flags_t); extern tree build_addr_func (tree); extern tree build_call_a (tree, int, tree*); extern tree build_call_n (tree, int, ...); @@ -4069,13 +4070,17 @@ extern bool null_ptr_cst_p (tree); extern bool sufficient_parms_p (const_tree); extern tree type_decays_to (tree); extern tree build_user_type_conversion (tree, tree, int); -extern tree build_new_function_call (tree, tree, bool); +extern tree build_new_function_call (tree, tree, bool, + tsubst_flags_t); extern tree build_operator_new_call (tree, tree, tree *, tree *, tree *); extern tree build_new_method_call (tree, tree, tree, tree, int, - tree *); -extern tree build_special_member_call (tree, tree, tree, tree, int); -extern tree build_new_op (enum tree_code, int, tree, tree, tree, bool *); + tree *, tsubst_flags_t); +extern tree build_special_member_call (tree, tree, tree, tree, int, + tsubst_flags_t); +extern tree build_new_op (enum tree_code, int, tree, + tree, tree, bool *, + tsubst_flags_t); extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree); extern bool can_convert (tree, tree); extern bool can_convert_arg (tree, tree, tree, int); @@ -4091,8 +4096,9 @@ extern bool is_properly_derived_from (tree, tree); extern tree initialize_reference (tree, tree, tree, tree *); extern tree make_temporary_var_for_ref_to_temp (tree, tree); extern tree strip_top_quals (tree); -extern tree perform_implicit_conversion (tree, tree); -extern tree perform_direct_initialization_if_possible (tree, tree, bool); +extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t); +extern tree perform_direct_initialization_if_possible (tree, tree, bool, + tsubst_flags_t); extern tree in_charge_arg_for_name (tree); extern tree build_cxx_call (tree, int, tree *); #ifdef ENABLE_CHECKING @@ -4159,7 +4165,8 @@ extern tree force_rvalue (tree); extern tree ocp_convert (tree, tree, int, int); extern tree cp_convert (tree, tree); extern tree cp_convert_and_check (tree, tree); -extern tree convert_to_void (tree, const char */*implicit context*/); +extern tree convert_to_void (tree, const char */*implicit context*/, + tsubst_flags_t); extern tree convert_force (tree, tree, int); extern tree build_expr_type_conversion (int, tree, bool); extern tree type_promotes_to (tree); @@ -4336,14 +4343,17 @@ extern tree do_friend (tree, tree, tree, tree, enum overload_flags, bool); /* in init.c */ extern tree expand_member_init (tree); extern void emit_mem_initializers (tree); -extern tree build_aggr_init (tree, tree, int); +extern tree build_aggr_init (tree, tree, int, + tsubst_flags_t); extern int is_class_type (tree, int); extern tree get_type_value (tree); extern tree build_zero_init (tree, tree, bool); extern tree build_value_init (tree); extern tree build_offset_ref (tree, tree, bool); -extern tree build_new (tree, tree, tree, tree, int); -extern tree build_vec_init (tree, tree, tree, bool, int); +extern tree build_new (tree, tree, tree, tree, int, + tsubst_flags_t); +extern tree build_vec_init (tree, tree, tree, bool, int, + tsubst_flags_t); extern tree build_default_init (tree, tree); extern tree build_delete (tree, tree, special_function_kind, @@ -4482,7 +4492,7 @@ extern tree build_typeid (tree); extern tree get_tinfo_decl (tree); extern tree get_typeid (tree); extern tree build_headof (tree); -extern tree build_dynamic_cast (tree, tree); +extern tree build_dynamic_cast (tree, tree, tsubst_flags_t); extern void emit_support_tinfos (void); extern bool emit_tinfo_decl (tree); @@ -4613,7 +4623,8 @@ extern tree finish_stmt_expr_expr (tree, tree); extern tree finish_stmt_expr (tree, bool); extern tree stmt_expr_value_expr (tree); extern tree perform_koenig_lookup (tree, tree); -extern tree finish_call_expr (tree, tree, bool, bool); +extern tree finish_call_expr (tree, tree, bool, bool, + tsubst_flags_t); extern tree finish_increment_expr (tree, enum tree_code); extern tree finish_this_expr (void); extern tree finish_pseudo_destructor_expr (tree, tree, tree); @@ -4762,36 +4773,49 @@ extern bool comptypes (tree, tree, int); extern bool compparms (const_tree, const_tree); extern int comp_cv_qualification (const_tree, const_tree); extern int comp_cv_qual_signature (tree, tree); -extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code); +extern tree cxx_sizeof_or_alignof_expr (tree, enum tree_code, bool); extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool); -#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false) +extern tree cxx_sizeof_nowarn (tree); extern tree inline_conversion (tree); extern tree is_bitfield_expr_with_lowered_type (const_tree); extern tree unlowered_expr_type (const_tree); extern tree decay_conversion (tree); -extern tree build_class_member_access_expr (tree, tree, tree, bool); -extern tree finish_class_member_access_expr (tree, tree, bool); -extern tree build_x_indirect_ref (tree, const char *); -extern tree build_indirect_ref (tree, const char *); +extern tree build_class_member_access_expr (tree, tree, tree, bool, + tsubst_flags_t); +extern tree finish_class_member_access_expr (tree, tree, bool, + tsubst_flags_t); +extern tree build_x_indirect_ref (tree, const char *, + tsubst_flags_t); +extern tree cp_build_indirect_ref (tree, const char *, + tsubst_flags_t); extern tree build_array_ref (tree, tree); extern tree get_member_function_from_ptrfunc (tree *, tree); +extern tree cp_build_function_call (tree, tree, tsubst_flags_t); extern tree build_x_binary_op (enum tree_code, tree, enum tree_code, tree, - enum tree_code, bool *); -extern tree build_x_unary_op (enum tree_code, tree); + enum tree_code, bool *, + tsubst_flags_t); +extern tree build_x_unary_op (enum tree_code, tree, + tsubst_flags_t); +extern tree cp_build_unary_op (enum tree_code, tree, int, + tsubst_flags_t); extern tree unary_complex_lvalue (enum tree_code, tree); -extern tree build_x_conditional_expr (tree, tree, tree); +extern tree build_x_conditional_expr (tree, tree, tree, + tsubst_flags_t); extern tree build_x_compound_expr_from_list (tree, const char *); -extern tree build_x_compound_expr (tree, tree); -extern tree build_compound_expr (tree, tree); -extern tree build_static_cast (tree, tree); -extern tree build_reinterpret_cast (tree, tree); -extern tree build_const_cast (tree, tree); -extern tree build_c_cast (tree, tree); -extern tree build_x_modify_expr (tree, enum tree_code, tree); -extern tree build_modify_expr (tree, enum tree_code, tree); +extern tree build_x_compound_expr (tree, tree, tsubst_flags_t); +extern tree build_compound_expr (tree, tree, tsubst_flags_t); +extern tree build_static_cast (tree, tree, tsubst_flags_t); +extern tree build_reinterpret_cast (tree, tree, tsubst_flags_t); +extern tree build_const_cast (tree, tree, tsubst_flags_t); +extern tree build_c_cast (tree, tree, tsubst_flags_t); +extern tree build_x_modify_expr (tree, enum tree_code, tree, + tsubst_flags_t); +extern tree cp_build_modify_expr (tree, enum tree_code, tree, + tsubst_flags_t); extern tree convert_for_initialization (tree, tree, tree, int, - const char *, tree, int); + const char *, tree, int, + tsubst_flags_t); extern int comp_ptr_ttypes (tree, tree); extern bool comp_ptr_ttypes_const (tree, tree); extern int ptr_reasonably_similar (const_tree, const_tree); @@ -4805,21 +4829,22 @@ extern tree build_ptrmemfunc1 (tree, tree, tree); extern void expand_ptrmemfunc_cst (tree, tree *, tree *); extern tree type_after_usual_arithmetic_conversions (tree, tree); extern tree composite_pointer_type (tree, tree, tree, tree, - const char*); + const char*, tsubst_flags_t); extern tree merge_types (tree, tree); extern tree check_return_expr (tree, bool *); -#define cp_build_binary_op(code, arg1, arg2) \ - build_binary_op(code, arg1, arg2, 1) +extern tree cp_build_binary_op (enum tree_code, tree, tree, + tsubst_flags_t); #define cxx_sizeof(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, true) extern tree build_ptrmemfunc_access_expr (tree, tree); extern tree build_address (tree); extern tree build_nop (tree, tree); extern tree non_reference (tree); extern tree lookup_anon_field (tree, tree); -extern bool invalid_nonstatic_memfn_p (const_tree); +extern bool invalid_nonstatic_memfn_p (const_tree, tsubst_flags_t); extern tree convert_member_func_to_ptr (tree, tree); extern tree convert_ptrmem (tree, tree, bool, bool); -extern int lvalue_or_else (const_tree, enum lvalue_use); +extern int lvalue_or_else (const_tree, enum lvalue_use, + tsubst_flags_t); extern int lvalue_p (const_tree); /* in typeck2.c */ @@ -4840,7 +4865,7 @@ extern tree digest_init (tree, tree); extern tree build_scoped_ref (tree, tree, tree *); extern tree build_x_arrow (tree); extern tree build_m_component_ref (tree, tree); -extern tree build_functional_cast (tree, tree); +extern tree build_functional_cast (tree, tree, tsubst_flags_t); extern tree add_exception_specifier (tree, tree, int); extern tree merge_exception_specifiers (tree, tree); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 64a8716..fe1ed29 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -326,7 +326,7 @@ build_up_reference (tree type, tree arg, int flags, tree decl) /* If we had a way to wrap this up, and say, if we ever needed its address, transform all occurrences of the register, into a memory reference we could win better. */ - rval = build_unary_op (ADDR_EXPR, arg, 1); + rval = cp_build_unary_op (ADDR_EXPR, arg, 1, tf_warning_or_error); if (rval == error_mark_node) return error_mark_node; @@ -470,7 +470,7 @@ convert_to_reference (tree reftype, tree expr, int convtype, warning (0, "casting %qT to %qT does not dereference pointer", intype, reftype); - rval = build_unary_op (ADDR_EXPR, expr, 0); + rval = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0); @@ -480,7 +480,8 @@ convert_to_reference (tree reftype, tree expr, int convtype, else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, - "converting", 0, 0); + "converting", 0, 0, + tf_warning_or_error); if (rval == NULL_TREE || rval == error_mark_node) return rval; warn_ref_binding (reftype, intype, decl); @@ -630,7 +631,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags) if (code == VOID_TYPE && (convtype & CONV_STATIC)) { - e = convert_to_void (e, /*implicit=*/NULL); + e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error); return e; } @@ -734,7 +735,8 @@ ocp_convert (tree type, tree expr, int convtype, int flags) ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, build_tree_list (NULL_TREE, ctor), - type, flags); + type, flags, + tf_warning_or_error); if (ctor) return build_cplus_new (type, ctor); } @@ -763,18 +765,19 @@ ocp_convert (tree type, tree expr, int convtype, int flags) IMPLICIT is tells us the context of an implicit void conversion. */ tree -convert_to_void (tree expr, const char *implicit) +convert_to_void (tree expr, const char *implicit, tsubst_flags_t complain) { if (expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; if (!TREE_TYPE (expr)) return expr; - if (invalid_nonstatic_memfn_p (expr)) + if (invalid_nonstatic_memfn_p (expr, complain)) return error_mark_node; if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { - error ("pseudo-destructor is not called"); + if (complain & tf_error) + error ("pseudo-destructor is not called"); return error_mark_node; } if (VOID_TYPE_P (TREE_TYPE (expr))) @@ -788,10 +791,10 @@ convert_to_void (tree expr, const char *implicit) tree op2 = TREE_OPERAND (expr,2); tree new_op1 = convert_to_void (op1, (implicit && !TREE_SIDE_EFFECTS (op2) - ? "second operand of conditional" : NULL)); + ? "second operand of conditional" : NULL), complain); tree new_op2 = convert_to_void (op2, (implicit && !TREE_SIDE_EFFECTS (op1) - ? "third operand of conditional" : NULL)); + ? "third operand of conditional" : NULL), complain); expr = build3 (COND_EXPR, TREE_TYPE (new_op1), TREE_OPERAND (expr, 0), new_op1, new_op2); @@ -804,7 +807,7 @@ convert_to_void (tree expr, const char *implicit) tree op1 = TREE_OPERAND (expr,1); tree new_op1 = convert_to_void (op1, (implicit && !TREE_NO_WARNING (expr) - ? "right-hand operand of comma" : NULL)); + ? "right-hand operand of comma" : NULL), complain); if (new_op1 != op1) { @@ -834,14 +837,20 @@ convert_to_void (tree expr, const char *implicit) /* Can't load the value if we don't know the type. */ if (is_volatile && !is_complete) - warning (0, "object of incomplete type %qT will not be accessed in %s", - type, implicit ? implicit : "void context"); + { + if (complain & tf_warning) + warning (0, "object of incomplete type %qT will not be accessed in %s", + type, implicit ? implicit : "void context"); + } /* Don't load the value if this is an implicit dereference, or if the type needs to be handled by ctors/dtors. */ else if (is_volatile && (is_reference || TREE_ADDRESSABLE (type))) - warning (0, "object of type %qT will not be accessed in %s", - TREE_TYPE (TREE_OPERAND (expr, 0)), - implicit ? implicit : "void context"); + { + if (complain & tf_warning) + warning (0, "object of type %qT will not be accessed in %s", + TREE_TYPE (TREE_OPERAND (expr, 0)), + implicit ? implicit : "void context"); + } if (is_reference || !is_volatile || !is_complete || TREE_ADDRESSABLE (type)) expr = TREE_OPERAND (expr, 0); @@ -854,7 +863,7 @@ convert_to_void (tree expr, const char *implicit) tree type = TREE_TYPE (expr); int is_complete = COMPLETE_TYPE_P (complete_type (type)); - if (TYPE_VOLATILE (type) && !is_complete) + if (TYPE_VOLATILE (type) && !is_complete && (complain & tf_warning)) warning (0, "object %qE of incomplete type %qT will not be accessed in %s", expr, type, implicit ? implicit : "void context"); break; @@ -892,15 +901,19 @@ convert_to_void (tree expr, const char *implicit) { /* [over.over] enumerates the places where we can take the address of an overloaded function, and this is not one of them. */ - error ("%s cannot resolve address of overloaded function", - implicit ? implicit : "void cast"); + if (complain & tf_error) + error ("%s cannot resolve address of overloaded function", + implicit ? implicit : "void cast"); + else + return error_mark_node; expr = void_zero_node; } else if (implicit && probe == expr && is_overloaded_fn (probe)) { /* Only warn when there is no &. */ - warning (OPT_Waddress, "%s is a reference, not call, to function %qE", - implicit, expr); + if (complain & tf_warning) + warning (OPT_Waddress, "%s is a reference, not call, to function %qE", + implicit, expr); if (TREE_CODE (expr) == COMPONENT_REF) expr = TREE_OPERAND (expr, 0); } @@ -915,8 +928,10 @@ convert_to_void (tree expr, const char *implicit) { /* The middle end does not warn about expressions that have been explicitly cast to void, so we must do so here. */ - if (!TREE_SIDE_EFFECTS (expr)) - warning (OPT_Wunused_value, "%s has no effect", implicit); + if (!TREE_SIDE_EFFECTS (expr)) { + if (complain & tf_warning) + warning (OPT_Wunused_value, "%s has no effect", implicit); + } else { tree e; @@ -939,7 +954,7 @@ convert_to_void (tree expr, const char *implicit) code = TREE_CODE (e); class = TREE_CODE_CLASS (code); - if (class == tcc_comparison + if ((class == tcc_comparison || class == tcc_unary || (class == tcc_binary && !(code == MODIFY_EXPR @@ -948,6 +963,7 @@ convert_to_void (tree expr, const char *implicit) || code == PREINCREMENT_EXPR || code == POSTDECREMENT_EXPR || code == POSTINCREMENT_EXPR))) + && (complain & tf_warning)) warning (OPT_Wunused_value, "value computed is not used"); } } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8353b9b..df0b78c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5027,7 +5027,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 1; } - init = build_aggr_init (decl, init, flags); + init = build_aggr_init (decl, init, flags, tf_warning_or_error); if (building_stmt_tree ()) current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; @@ -5978,7 +5978,7 @@ register_dtor_fn (tree decl) addr = build_address (decl); /* The declared type of the parameter to "__cxa_atexit" is "void *". For plain "T*", we could just let the - machinery in build_function_call convert it -- but if the + machinery in cp_build_function_call convert it -- but if the type is "cv-qualified T *", then we need to convert it before passing it in, to avoid spurious errors. */ addr = build_nop (ptr_type_node, addr); @@ -5990,7 +5990,8 @@ register_dtor_fn (tree decl) other value. */ addr = null_pointer_node; args = tree_cons (NULL_TREE, - build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0), + cp_build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0, + tf_warning_or_error), NULL_TREE); if (targetm.cxx.use_aeabi_atexit ()) { @@ -6005,7 +6006,8 @@ register_dtor_fn (tree decl) } else args = tree_cons (NULL_TREE, cleanup, NULL_TREE); - return build_function_call (get_atexit_node (), args); + return cp_build_function_call (get_atexit_node (), args, + tf_warning_or_error); } /* DECL is a VAR_DECL with static storage duration. INIT, if present, @@ -7082,7 +7084,8 @@ compute_array_index_type (tree name, tree size) processing_template_decl = 0; itype = cp_build_binary_op (MINUS_EXPR, cp_convert (ssizetype, size), - cp_convert (ssizetype, integer_one_node)); + cp_convert (ssizetype, integer_one_node), + tf_warning_or_error); itype = fold (itype); processing_template_decl = saved_processing_template_decl; @@ -10820,7 +10823,8 @@ finish_enum (tree enumtype) saved_location = input_location; input_location = DECL_SOURCE_LOCATION (decl); value = perform_implicit_conversion (underlying_type, - DECL_INITIAL (decl)); + DECL_INITIAL (decl), + tf_warning_or_error); input_location = saved_location; /* Do not clobber shared ints. */ @@ -11282,7 +11286,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags) gcc_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE); cp_function_chain->x_current_class_ref - = build_indirect_ref (t, NULL); + = cp_build_indirect_ref (t, NULL, tf_warning_or_error); cp_function_chain->x_current_class_ptr = t; /* Constructors and destructors need to know whether they're "in @@ -12199,8 +12203,9 @@ cxx_maybe_build_cleanup (tree decl) fn = lookup_name (id); arg = build_address (decl); mark_used (decl); - cleanup = build_function_call (fn, build_tree_list (NULL_TREE, - arg)); + cleanup = cp_build_function_call (fn, build_tree_list (NULL_TREE, + arg), + tf_warning_or_error); } /* Handle ordinary C++ destructors. */ type = TREE_TYPE (decl); @@ -12224,7 +12229,7 @@ cxx_maybe_build_cleanup (tree decl) call = build_delete (TREE_TYPE (addr), addr, sfk_complete_destructor, flags, 0); if (cleanup) - cleanup = build_compound_expr (cleanup, call); + cleanup = build_compound_expr (cleanup, call, tf_warning_or_error); else cleanup = call; } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 367d9eb..078ca99 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -311,7 +311,7 @@ grok_array_decl (tree array_expr, tree index_exp) if (MAYBE_CLASS_TYPE_P (type) || MAYBE_CLASS_TYPE_P (TREE_TYPE (index_exp))) expr = build_new_op (ARRAY_REF, LOOKUP_NORMAL, array_expr, index_exp, NULL_TREE, - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, tf_warning_or_error); else { tree p1, p2, i1, i2; @@ -1190,7 +1190,7 @@ build_anon_union_vars (tree type, tree object) DECL_NAME (field), NULL_TREE); else ref = build_class_member_access_expr (object, field, NULL_TREE, - false); + false, tf_warning_or_error); if (DECL_NAME (field)) { @@ -2436,13 +2436,15 @@ get_guard_cond (tree guard) guard_value = integer_one_node; if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) guard_value = convert (TREE_TYPE (guard), guard_value); - guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value); + guard = cp_build_binary_op (BIT_AND_EXPR, guard, guard_value, + tf_warning_or_error); } guard_value = integer_zero_node; if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard))) guard_value = convert (TREE_TYPE (guard), guard_value); - return cp_build_binary_op (EQ_EXPR, guard, guard_value); + return cp_build_binary_op (EQ_EXPR, guard, guard_value, + tf_warning_or_error); } /* Return an expression which sets the GUARD variable, indicating that @@ -2458,7 +2460,8 @@ set_guard (tree guard) guard_init = integer_one_node; if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard))) guard_init = convert (TREE_TYPE (guard), guard_init); - return build_modify_expr (guard, NOP_EXPR, guard_init); + return cp_build_modify_expr (guard, NOP_EXPR, guard_init, + tf_warning_or_error); } /* Start the process of running a particular set of global constructors @@ -2787,17 +2790,21 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) else if (initp) guard_cond = cp_build_binary_op (EQ_EXPR, - build_unary_op (PREINCREMENT_EXPR, + cp_build_unary_op (PREINCREMENT_EXPR, guard, - /*noconvert=*/1), - integer_one_node); + /*noconvert=*/1, + tf_warning_or_error), + integer_one_node, + tf_warning_or_error); else guard_cond = cp_build_binary_op (EQ_EXPR, - build_unary_op (PREDECREMENT_EXPR, + cp_build_unary_op (PREDECREMENT_EXPR, guard, - /*noconvert=*/1), - integer_zero_node); + /*noconvert=*/1, + tf_warning_or_error), + integer_zero_node, + tf_warning_or_error); guard_if_stmt = begin_if_stmt (); finish_if_stmt_cond (guard_cond, guard_if_stmt); @@ -2849,8 +2856,9 @@ do_static_initialization_or_destruction (tree vars, bool initp) init_if_stmt = begin_if_stmt (); cond = initp ? integer_one_node : integer_zero_node; cond = cp_build_binary_op (EQ_EXPR, - initialize_p_decl, - cond); + initialize_p_decl, + cond, + tf_warning_or_error); finish_if_stmt_cond (cond, init_if_stmt); node = vars; @@ -2882,7 +2890,8 @@ do_static_initialization_or_destruction (tree vars, bool initp) priority_if_stmt = begin_if_stmt (); cond = cp_build_binary_op (EQ_EXPR, priority_decl, - build_int_cst (NULL_TREE, priority)); + build_int_cst (NULL_TREE, priority), + tf_warning_or_error); finish_if_stmt_cond (cond, priority_if_stmt); /* Process initializers with same priority. */ @@ -3031,7 +3040,8 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority, arguments = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, constructor_p), arguments); - finish_expr_stmt (build_function_call (fndecl, arguments)); + finish_expr_stmt (cp_build_function_call (fndecl, arguments, + tf_warning_or_error)); } } @@ -3534,7 +3544,7 @@ build_offset_ref_call_from_tree (tree fn, tree args) args = build_non_dependent_args (args); object = build_non_dependent_expr (object); if (TREE_CODE (fn) == DOTSTAR_EXPR) - object = build_unary_op (ADDR_EXPR, object, 0); + object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error); args = tree_cons (NULL_TREE, object, args); /* Now that the arguments are done, transform FN. */ fn = build_non_dependent_expr (fn); @@ -3548,13 +3558,14 @@ build_offset_ref_call_from_tree (tree fn, tree args) void B::g() { (this->*p)(); } */ if (TREE_CODE (fn) == OFFSET_REF) { - tree object_addr = build_unary_op (ADDR_EXPR, object, 0); + tree object_addr = cp_build_unary_op (ADDR_EXPR, object, 0, + tf_warning_or_error); fn = TREE_OPERAND (fn, 1); fn = get_member_function_from_ptrfunc (&object_addr, fn); args = tree_cons (NULL_TREE, object_addr, args); } - expr = build_function_call (fn, args); + expr = cp_build_function_call (fn, args, tf_warning_or_error); if (processing_template_decl && expr != error_mark_node) return build_min_non_dep_call_list (expr, orig_fn, orig_args); return expr; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 38111b1..5304381 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -176,8 +176,9 @@ do_get_exception_ptr (void) fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp)); } - return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), - NULL_TREE)); + return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), + NULL_TREE), + tf_warning_or_error); } /* Build up a call to __cxa_begin_catch, to tell the runtime that the @@ -196,8 +197,9 @@ do_begin_catch (void) fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp)); } - return build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), - NULL_TREE)); + return cp_build_function_call (fn, tree_cons (NULL_TREE, build_exc_ptr (), + NULL_TREE), + tf_warning_or_error); } /* Returns nonzero if cleaning up an exception of type TYPE (which can be @@ -235,7 +237,7 @@ do_end_catch (tree type) TREE_NOTHROW (fn) = 0; } - cleanup = build_function_call (fn, NULL_TREE); + cleanup = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error); TREE_NOTHROW (cleanup) = dtor_nothrow (type); return cleanup; @@ -377,7 +379,7 @@ initialize_handler_parm (tree decl, tree exp) pointer catch parm with the address of the temporary. */ if (TREE_CODE (init_type) == REFERENCE_TYPE && TYPE_PTR_P (TREE_TYPE (init_type))) - exp = build_unary_op (ADDR_EXPR, exp, 1); + exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error); exp = ocp_convert (init_type, exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0); @@ -434,7 +436,7 @@ expand_start_catch_block (tree decl) exp = build2 (POINTER_PLUS_EXPR, TREE_TYPE (exp), exp, fold_build1 (NEGATE_EXPR, sizetype, TYPE_SIZE_UNIT (TREE_TYPE (exp)))); - exp = build_indirect_ref (exp, NULL); + exp = cp_build_indirect_ref (exp, NULL, tf_warning_or_error); initialize_handler_parm (decl, exp); return type; } @@ -546,8 +548,10 @@ do_allocate_exception (tree type) fn = push_library_fn (fn, build_function_type (ptr_type_node, tmp)); } - return build_function_call (fn, tree_cons (NULL_TREE, size_in_bytes (type), - NULL_TREE)); + return cp_build_function_call (fn, + tree_cons (NULL_TREE, size_in_bytes (type), + NULL_TREE), + tf_warning_or_error); } /* Call __cxa_free_exception from a cleanup. This is never invoked @@ -566,7 +570,8 @@ do_free_exception (tree ptr) void_list_node)); } - return build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE)); + return cp_build_function_call (fn, tree_cons (NULL_TREE, ptr, NULL_TREE), + tf_warning_or_error); } /* Wrap all cleanups for TARGET_EXPRs in MUST_NOT_THROW_EXPR. @@ -644,7 +649,8 @@ build_throw (tree exp) return error_mark_node; } fn = OVL_CURRENT (fn); - exp = build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE)); + exp = cp_build_function_call (fn, tree_cons (NULL_TREE, exp, NULL_TREE), + tf_warning_or_error); } else if (exp) { @@ -708,7 +714,7 @@ build_throw (tree exp) allocate_expr = get_target_expr (allocate_expr); ptr = TARGET_EXPR_SLOT (allocate_expr); object = build_nop (build_pointer_type (temp_type), ptr); - object = build_indirect_ref (object, NULL); + object = cp_build_indirect_ref (object, NULL, tf_warning_or_error); elided = (TREE_CODE (exp) == TARGET_EXPR); @@ -733,7 +739,7 @@ build_throw (tree exp) (object, complete_ctor_identifier, build_tree_list (NULL_TREE, exp), TREE_TYPE (object), - flags)); + flags, tf_warning_or_error)); if (exp == error_mark_node) { error (" in thrown expression"); @@ -812,7 +818,7 @@ build_throw (tree exp) tmp = tree_cons (NULL_TREE, throw_type, tmp); tmp = tree_cons (NULL_TREE, ptr, tmp); /* ??? Indicate that this function call throws throw_type. */ - tmp = build_function_call (fn, tmp); + tmp = cp_build_function_call (fn, tmp, tf_warning_or_error); /* Tack on the initialization stuff. */ exp = build2 (COMPOUND_EXPR, TREE_TYPE (tmp), exp, tmp); @@ -831,7 +837,7 @@ build_throw (tree exp) /* ??? Indicate that this function call allows exceptions of the type of the enclosing catch block (if known). */ - exp = build_function_call (fn, NULL_TREE); + exp = cp_build_function_call (fn, NULL_TREE, tf_warning_or_error); } exp = build1 (THROW_EXPR, void_type_node, exp); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index e0700ea..dc4e988 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -39,8 +39,8 @@ along with GCC; see the file COPYING3. If not see static bool begin_init_stmts (tree *, tree *); static tree finish_init_stmts (bool, tree, tree); static void construct_virtual_base (tree, tree); -static void expand_aggr_init_1 (tree, tree, tree, tree, int); -static void expand_default_init (tree, tree, tree, tree, int); +static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t); +static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t); static tree build_vec_delete_1 (tree, tree, tree, special_function_kind, int); static void perform_member_init (tree, tree); static tree build_builtin_delete_call (tree); @@ -353,7 +353,8 @@ build_value_init_1 (tree type, bool have_ctor) return build_cplus_new (type, build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL)); + NULL_TREE, type, LOOKUP_NORMAL, + tf_warning_or_error)); else if (TREE_CODE (type) != UNION_TYPE) { tree field, init; @@ -401,7 +402,7 @@ build_value_init_1 (tree type, bool have_ctor) cp_gimplify_init_expr will know how to handle it. */ tree ctor = build_special_member_call (NULL_TREE, complete_ctor_identifier, - NULL_TREE, type, LOOKUP_NORMAL); + NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error); ctor = build_cplus_new (type, ctor); init = build2 (INIT_EXPR, void_type_node, @@ -487,7 +488,8 @@ perform_member_init (tree member, tree init) /* Get an lvalue for the data member. */ decl = build_class_member_access_expr (current_class_ref, member, /*access_path=*/NULL_TREE, - /*preserve_reference=*/true); + /*preserve_reference=*/true, + tf_warning_or_error); if (decl == error_mark_node) return; @@ -513,10 +515,12 @@ perform_member_init (tree member, tree init) /* Initialization of one array from another. */ finish_expr_stmt (build_vec_init (decl, NULL_TREE, TREE_VALUE (init), /*explicit_default_init_p=*/false, - /* from_array=*/1)); + /* from_array=*/1, + tf_warning_or_error)); } else - finish_expr_stmt (build_aggr_init (decl, init, 0)); + finish_expr_stmt (build_aggr_init (decl, init, 0, + tf_warning_or_error)); } else { @@ -544,7 +548,8 @@ perform_member_init (tree member, tree init) init = build_x_compound_expr_from_list (init, "member initializer"); if (init) - finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); + finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, + tf_warning_or_error)); } if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) @@ -553,7 +558,8 @@ perform_member_init (tree member, tree init) expr = build_class_member_access_expr (current_class_ref, member, /*access_path=*/NULL_TREE, - /*preserve_reference=*/false); + /*preserve_reference=*/false, + tf_warning_or_error); expr = build_delete (type, expr, sfk_complete_destructor, LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0); @@ -855,9 +861,11 @@ emit_mem_initializers (tree mem_inits) base_addr = build_base_path (PLUS_EXPR, current_class_ptr, subobject, 1); expand_aggr_init_1 (subobject, NULL_TREE, - build_indirect_ref (base_addr, NULL), + cp_build_indirect_ref (base_addr, NULL, + tf_warning_or_error), arguments, - LOOKUP_NORMAL); + LOOKUP_NORMAL, + tf_warning_or_error); expand_cleanup_for_base (subobject, NULL_TREE); } @@ -938,7 +946,7 @@ expand_virtual_init (tree binfo, tree decl) TREE_TYPE (vtt_parm), vtt_parm, vtt_index); - vtbl2 = build_indirect_ref (vtbl2, NULL); + vtbl2 = cp_build_indirect_ref (vtbl2, NULL, tf_warning_or_error); vtbl2 = convert (TREE_TYPE (vtbl), vtbl2); /* The actual initializer is the VTT value only in the subobject @@ -953,13 +961,15 @@ expand_virtual_init (tree binfo, tree decl) } /* Compute the location of the vtpr. */ - vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL), + vtbl_ptr = build_vfield_ref (cp_build_indirect_ref (decl, NULL, + tf_warning_or_error), TREE_TYPE (binfo)); gcc_assert (vtbl_ptr != error_mark_node); /* Assign the vtable to the vptr. */ vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0); - finish_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl)); + finish_expr_stmt (cp_build_modify_expr (vtbl_ptr, NOP_EXPR, vtbl, + tf_warning_or_error)); } /* If an exception is thrown in a constructor, those base classes already @@ -981,7 +991,8 @@ expand_cleanup_for_base (tree binfo, tree flag) base_dtor_identifier, NULL_TREE, binfo, - LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, + tf_warning_or_error); if (flag) expr = fold_build3 (COND_EXPR, void_type_node, c_common_truthvalue_conversion (flag), @@ -1025,7 +1036,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); + LOOKUP_COMPLAIN, tf_warning_or_error); finish_then_clause (inner_if_stmt); finish_if_stmt (inner_if_stmt); @@ -1230,7 +1241,7 @@ expand_member_init (tree name) perform the initialization, but not both, as it would be ambiguous. */ tree -build_aggr_init (tree exp, tree init, int flags) +build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) { tree stmt_expr; tree compound_stmt; @@ -1257,7 +1268,8 @@ build_aggr_init (tree exp, tree init, int flags) initialization form -- unless the initializer is "()". */ if (init && TREE_CODE (init) == TREE_LIST) { - error ("bad array initializer"); + if (complain & tf_error) + error ("bad array initializer"); return error_mark_node; } /* Must arrange to initialize each element of EXP @@ -1270,7 +1282,8 @@ build_aggr_init (tree exp, tree init, int flags) stmt_expr = build_vec_init (exp, NULL_TREE, init, /*explicit_default_init_p=*/false, itype && same_type_p (itype, - TREE_TYPE (exp))); + TREE_TYPE (exp)), + complain); TREE_READONLY (exp) = was_const; TREE_THIS_VOLATILE (exp) = was_volatile; TREE_TYPE (exp) = type; @@ -1287,7 +1300,7 @@ build_aggr_init (tree exp, tree init, int flags) destroy_temps = stmts_are_full_exprs_p (); current_stmt_tree ()->stmts_are_full_exprs_p = 0; expand_aggr_init_1 (TYPE_BINFO (type), exp, exp, - init, LOOKUP_NORMAL|flags); + init, LOOKUP_NORMAL|flags, complain); stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; TREE_READONLY (exp) = was_const; @@ -1297,7 +1310,8 @@ build_aggr_init (tree exp, tree init, int flags) } static void -expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) +expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags, + tsubst_flags_t complain) { tree type = TREE_TYPE (exp); tree ctor_name; @@ -1364,9 +1378,10 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) else ctor_name = base_ctor_identifier; - rval = build_special_member_call (exp, ctor_name, parms, binfo, flags); + rval = build_special_member_call (exp, ctor_name, parms, binfo, flags, + complain); if (TREE_SIDE_EFFECTS (rval)) - finish_expr_stmt (convert_to_void (rval, NULL)); + finish_expr_stmt (convert_to_void (rval, NULL, complain)); } /* This function is responsible for initializing EXP with INIT @@ -1390,7 +1405,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags) for its description. */ static void -expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags) +expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, + tsubst_flags_t complain) { tree type = TREE_TYPE (exp); @@ -1417,7 +1433,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags) /* We know that expand_default_init can handle everything we want at this point. */ - expand_default_init (binfo, true_exp, exp, init, flags); + expand_default_init (binfo, true_exp, exp, init, flags, complain); } /* Report an error if TYPE is not a user-defined, class type. If @@ -1574,7 +1590,8 @@ build_offset_ref (tree type, tree member, bool address_p) if (flag_ms_extensions) { PTRMEM_OK_P (member) = 1; - return build_unary_op (ADDR_EXPR, member, 0); + return cp_build_unary_op (ADDR_EXPR, member, 0, + tf_warning_or_error); } error ("invalid use of non-static member function %qD", TREE_OPERAND (member, 1)); @@ -1765,7 +1782,7 @@ avoid_placement_new_aliasing (tree t, tree placement) static tree build_new_1 (tree placement, tree type, tree nelts, tree init, - bool globally_qualified_p) + bool globally_qualified_p, tsubst_flags_t complain) { tree size, rval; /* True iff this is a call to "operator new[]" instead of just @@ -1855,11 +1872,13 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, TREE_CODE (elt_type) == ARRAY_TYPE; elt_type = TREE_TYPE (elt_type)) nelts = cp_build_binary_op (MULT_EXPR, nelts, - array_type_nelts_top (elt_type)); + array_type_nelts_top (elt_type), + complain); if (TREE_CODE (elt_type) == VOID_TYPE) { - error ("invalid type %<void%> for new"); + if (complain & tf_error) + error ("invalid type %<void%> for new"); return error_mark_node; } @@ -1869,7 +1888,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init); if (CP_TYPE_CONST_P (elt_type) && !is_initialized) { - error ("uninitialized const in %<new%> of %q#T", elt_type); + if (complain & tf_error) + error ("uninitialized const in %<new%> of %q#T", elt_type); return error_mark_node; } @@ -1907,19 +1927,22 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (!get_global_value_if_present (get_identifier (alloc_name), &alloc_fn)) { - error ("call to Java constructor with %qs undefined", alloc_name); + if (complain & tf_error) + error ("call to Java constructor with %qs undefined", alloc_name); return error_mark_node; } else if (really_overloaded_fn (alloc_fn)) { - error ("%qD should never be overloaded", alloc_fn); + if (complain & tf_error) + error ("%qD should never be overloaded", alloc_fn); return error_mark_node; } alloc_fn = OVL_CURRENT (alloc_fn); class_addr = build1 (ADDR_EXPR, jclass_node, class_decl); - alloc_call = (build_function_call + alloc_call = (cp_build_function_call (alloc_fn, - build_tree_list (NULL_TREE, class_addr))); + build_tree_list (NULL_TREE, class_addr), + complain)); } else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type)) { @@ -1952,20 +1975,25 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, fns = lookup_fnfields (elt_type, fnname, /*protect=*/2); if (fns == NULL_TREE) { - error ("no suitable %qD found in class %qT", fnname, elt_type); + if (complain & tf_error) + error ("no suitable %qD found in class %qT", fnname, elt_type); return error_mark_node; } if (TREE_CODE (fns) == TREE_LIST) { - error ("request for member %qD is ambiguous", fnname); - print_candidates (fns); + if (complain & tf_error) + { + error ("request for member %qD is ambiguous", fnname); + print_candidates (fns); + } return error_mark_node; } alloc_call = build_new_method_call (build_dummy_object (elt_type), fns, args, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, - &alloc_fn); + &alloc_fn, + complain); } else { @@ -2085,7 +2113,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, size_ptr_type = build_pointer_type (sizetype); cookie_ptr = build2 (POINTER_PLUS_EXPR, size_ptr_type, fold_convert (size_ptr_type, data_addr), cookie_ptr); - cookie = build_indirect_ref (cookie_ptr, NULL); + cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); cookie_expr = build2 (MODIFY_EXPR, sizetype, cookie, nelts); @@ -2096,7 +2124,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, fold_build1 (NEGATE_EXPR, sizetype, size_in_bytes (sizetype))); - cookie = build_indirect_ref (cookie_ptr, NULL); + cookie = cp_build_indirect_ref (cookie_ptr, NULL, complain); cookie = build2 (MODIFY_EXPR, sizetype, cookie, size_in_bytes(elt_type)); cookie_expr = build2 (COMPOUND_EXPR, TREE_TYPE (cookie_expr), @@ -2119,7 +2147,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, { bool stable; - init_expr = build_indirect_ref (data_addr, NULL); + init_expr = cp_build_indirect_ref (data_addr, NULL, complain); if (array_p) { @@ -2131,15 +2159,21 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, explicit_default_init_p = true; } else if (init) - pedwarn ("ISO C++ forbids initialization in array new"); - + { + if (complain & tf_error) + pedwarn ("ISO C++ forbids initialization in array new"); + else + return error_mark_node; + } init_expr = build_vec_init (init_expr, cp_build_binary_op (MINUS_EXPR, outer_nelts, - integer_one_node), + integer_one_node, + complain), init, explicit_default_init_p, - /*from_array=*/0); + /*from_array=*/0, + complain); /* An array initialization is stable because the initialization of each element is a full-expression, so the temporaries don't @@ -2156,7 +2190,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, init_expr = build_special_member_call (init_expr, complete_ctor_identifier, init, elt_type, - LOOKUP_NORMAL); + LOOKUP_NORMAL, + complain); stable = stabilize_init (init_expr, &init_preeval_expr); } else @@ -2171,7 +2206,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, gcc_assert (TREE_CODE (init) != CONSTRUCTOR || TREE_TYPE (init) != NULL_TREE); - init_expr = build_modify_expr (init_expr, INIT_EXPR, init); + init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init, + complain); stable = stabilize_init (init_expr, &init_preeval_expr); } } @@ -2263,8 +2299,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, if (check_new) { tree ifexp = cp_build_binary_op (NE_EXPR, alloc_node, - integer_zero_node); - rval = build_conditional_expr (ifexp, rval, alloc_node); + integer_zero_node, + complain); + rval = build_conditional_expr (ifexp, rval, alloc_node, + complain); } /* Perform the allocation before anything else, so that ALLOC_NODE @@ -2299,7 +2337,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init, tree build_new (tree placement, tree type, tree nelts, tree init, - int use_global_new) + int use_global_new, tsubst_flags_t complain) { tree rval; tree orig_placement; @@ -2333,7 +2371,12 @@ build_new (tree placement, tree type, tree nelts, tree init, if (nelts) { if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false)) - pedwarn ("size in array new must have integral type"); + { + if (complain & tf_error) + pedwarn ("size in array new must have integral type"); + else + return error_mark_node; + } nelts = cp_save_expr (cp_convert (sizetype, nelts)); } @@ -2342,13 +2385,17 @@ build_new (tree placement, tree type, tree nelts, tree init, returned by new.'' ARM 5.3.3 */ if (TREE_CODE (type) == REFERENCE_TYPE) { - error ("new cannot be applied to a reference type"); + if (complain & tf_error) + error ("new cannot be applied to a reference type"); + else + return error_mark_node; type = TREE_TYPE (type); } if (TREE_CODE (type) == FUNCTION_TYPE) { - error ("new cannot be applied to a function type"); + if (complain & tf_error) + error ("new cannot be applied to a function type"); return error_mark_node; } @@ -2358,7 +2405,7 @@ build_new (tree placement, tree type, tree nelts, tree init, if (!complete_type_or_else (type, NULL_TREE)) return error_mark_node; - rval = build_new_1 (placement, type, nelts, init, use_global_new); + rval = build_new_1 (placement, type, nelts, init, use_global_new, complain); if (rval == error_mark_node) return error_mark_node; @@ -2464,10 +2511,11 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, convert (sizetype, maxindex)); tbase = create_temporary_var (ptype); - tbase_init = build_modify_expr (tbase, NOP_EXPR, - fold_build2 (POINTER_PLUS_EXPR, ptype, - fold_convert (ptype, base), - virtual_size)); + tbase_init = cp_build_modify_expr (tbase, NOP_EXPR, + fold_build2 (POINTER_PLUS_EXPR, ptype, + fold_convert (ptype, base), + virtual_size), + tf_warning_or_error); DECL_REGISTER (tbase) = 1; controller = build3 (BIND_EXPR, void_type_node, tbase, NULL_TREE, NULL_TREE); @@ -2478,14 +2526,17 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, fold_convert (ptype, base))); tmp = fold_build1 (NEGATE_EXPR, sizetype, size_exp); body = build_compound_expr - (body, build_modify_expr (tbase, NOP_EXPR, - build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp))); + (body, cp_build_modify_expr (tbase, NOP_EXPR, + build2 (POINTER_PLUS_EXPR, ptype, tbase, tmp), + tf_warning_or_error), + tf_warning_or_error); body = build_compound_expr (body, build_delete (ptype, tbase, sfk_complete_destructor, - LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1)); + LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 1), + tf_warning_or_error); loop = build1 (LOOP_EXPR, void_type_node, body); - loop = build_compound_expr (tbase_init, loop); + loop = build_compound_expr (tbase_init, loop, tf_warning_or_error); no_destructor: /* If the delete flag is one, or anything else with the low bit set, @@ -2511,7 +2562,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, cp_build_binary_op (MINUS_EXPR, cp_convert (string_type_node, base), - cookie_size)); + cookie_size, + tf_warning_or_error)); /* True size with header. */ virtual_size = size_binop (PLUS_EXPR, virtual_size, cookie_size); } @@ -2530,7 +2582,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, else if (!body) body = deallocate_expr; else - body = build_compound_expr (body, deallocate_expr); + body = build_compound_expr (body, deallocate_expr, tf_warning_or_error); if (!body) body = integer_zero_node; @@ -2553,7 +2605,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type, /* Pre-evaluate the SAVE_EXPR outside of the BIND_EXPR. */ body = build2 (COMPOUND_EXPR, void_type_node, base, body); - return convert_to_void (body, /*implicit=*/NULL); + return convert_to_void (body, /*implicit=*/NULL, tf_warning_or_error); } /* Create an unnamed variable of the indicated TYPE. */ @@ -2588,7 +2640,8 @@ get_temp_regvar (tree type, tree init) decl = create_temporary_var (type); add_decl_expr (decl); - finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); + finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init, + tf_warning_or_error)); return decl; } @@ -2616,7 +2669,7 @@ get_temp_regvar (tree type, tree init) tree build_vec_init (tree base, tree maxindex, tree init, bool explicit_default_init_p, - int from_array) + int from_array, tsubst_flags_t complain) { tree rval; tree base2 = NULL_TREE; @@ -2737,14 +2790,16 @@ build_vec_init (tree base, tree maxindex, tree init, current_stmt_tree ()->stmts_are_full_exprs_p = 1; if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) - finish_expr_stmt (build_aggr_init (baseref, elt, 0)); + finish_expr_stmt (build_aggr_init (baseref, elt, 0, complain)); else - finish_expr_stmt (build_modify_expr (baseref, NOP_EXPR, - elt)); + finish_expr_stmt (cp_build_modify_expr (baseref, NOP_EXPR, + elt, complain)); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0)); - finish_expr_stmt (build_unary_op (PREDECREMENT_EXPR, iterator, 0)); + finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0, + complain)); + finish_expr_stmt (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, + complain)); } /* Clear out INIT so that we don't get confused below. */ @@ -2766,7 +2821,8 @@ build_vec_init (tree base, tree maxindex, tree init, && TYPE_NEEDS_CONSTRUCTING (type) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) { - error ("initializer ends prematurely"); + if (complain & tf_error) + error ("initializer ends prematurely"); return error_mark_node; } } @@ -2794,7 +2850,8 @@ build_vec_init (tree base, tree maxindex, tree init, finish_for_cond (build2 (NE_EXPR, boolean_type_node, iterator, build_int_cst (TREE_TYPE (iterator), -1)), for_stmt); - finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0), + finish_for_expr (cp_build_unary_op (PREDECREMENT_EXPR, iterator, 0, + complain), for_stmt); to = build1 (INDIRECT_REF, type, base); @@ -2809,11 +2866,13 @@ build_vec_init (tree base, tree maxindex, tree init, from = NULL_TREE; if (from_array == 2) - elt_init = build_modify_expr (to, NOP_EXPR, from); + elt_init = cp_build_modify_expr (to, NOP_EXPR, from, + complain); else if (TYPE_NEEDS_CONSTRUCTING (type)) - elt_init = build_aggr_init (to, from, 0); + elt_init = build_aggr_init (to, from, 0, complain); else if (from) - elt_init = build_modify_expr (to, NOP_EXPR, from); + elt_init = cp_build_modify_expr (to, NOP_EXPR, from, + complain); else gcc_unreachable (); } @@ -2825,23 +2884,26 @@ build_vec_init (tree base, tree maxindex, tree init, elt_init = build_vec_init (build1 (INDIRECT_REF, type, base), 0, 0, /*explicit_default_init_p=*/false, - 0); + 0, complain); } else if (!TYPE_NEEDS_CONSTRUCTING (type)) - elt_init = (build_modify_expr + elt_init = (cp_build_modify_expr (to, INIT_EXPR, build_zero_init (type, size_one_node, - /*static_storage_p=*/false))); + /*static_storage_p=*/false), + complain)); else - elt_init = build_aggr_init (to, init, 0); + elt_init = build_aggr_init (to, init, 0, complain); current_stmt_tree ()->stmts_are_full_exprs_p = 1; finish_expr_stmt (elt_init); current_stmt_tree ()->stmts_are_full_exprs_p = 0; - finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base, 0)); + finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base, 0, + complain)); if (base2) - finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0)); + finish_expr_stmt (cp_build_unary_op (PREINCREMENT_EXPR, base2, 0, + complain)); finish_for_stmt (for_stmt); } @@ -2851,13 +2913,15 @@ build_vec_init (tree base, tree maxindex, tree init, && from_array != 2) { tree e; - tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator); + tree m = cp_build_binary_op (MINUS_EXPR, maxindex, iterator, + complain); /* Flatten multi-dimensional array since build_vec_delete only expects one-dimensional array. */ if (TREE_CODE (type) == ARRAY_TYPE) m = cp_build_binary_op (MULT_EXPR, m, - array_type_nelts_total (type)); + array_type_nelts_total (type), + complain); finish_cleanup_try_block (try_block); e = build_vec_delete_1 (rval, m, @@ -2875,7 +2939,7 @@ build_vec_init (tree base, tree maxindex, tree init, /* Now convert make the result have the correct type. */ atype = build_pointer_type (atype); stmt_expr = build1 (NOP_EXPR, atype, stmt_expr); - stmt_expr = build_indirect_ref (stmt_expr, NULL); + stmt_expr = cp_build_indirect_ref (stmt_expr, NULL, complain); current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps; return stmt_expr; @@ -2911,7 +2975,8 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags) /*args=*/NULL_TREE, /*conversion_path=*/NULL_TREE, flags, - /*fn_p=*/NULL); + /*fn_p=*/NULL, + tf_warning_or_error); } /* Generate a call to a destructor. TYPE is the type to cast ADDR to. @@ -2993,7 +3058,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /* Don't check PROTECT here; leave that decision to the destructor. If the destructor is accessible, call it, else report error. */ - addr = build_unary_op (ADDR_EXPR, addr, 0); + addr = cp_build_unary_op (ADDR_EXPR, addr, 0, tf_warning_or_error); if (TREE_SIDE_EFFECTS (addr)) addr = save_expr (addr); @@ -3065,7 +3130,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, /*alloc_fn=*/NULL_TREE); } - expr = build_dtor_call (build_indirect_ref (addr, NULL), + expr = build_dtor_call (cp_build_indirect_ref (addr, NULL, + tf_warning_or_error), auto_delete, flags); if (do_delete) expr = build2 (COMPOUND_EXPR, void_type_node, expr, do_delete); @@ -3079,7 +3145,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete, ifexp = integer_one_node; else /* Handle deleting a null pointer. */ - ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node)); + ifexp = fold (cp_build_binary_op (NE_EXPR, addr, integer_zero_node, + tf_warning_or_error)); if (ifexp != integer_one_node) expr = build3 (COND_EXPR, void_type_node, @@ -3123,7 +3190,8 @@ push_base_cleanups (void) NULL_TREE, base_binfo, (LOOKUP_NORMAL - | LOOKUP_NONVIRTUAL)); + | LOOKUP_NONVIRTUAL), + tf_warning_or_error); expr = build3 (COND_EXPR, void_type_node, cond, expr, void_zero_node); finish_decl_cleanup (NULL_TREE, expr); @@ -3142,7 +3210,8 @@ push_base_cleanups (void) expr = build_special_member_call (current_class_ref, base_dtor_identifier, NULL_TREE, base_binfo, - LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, + tf_warning_or_error); finish_decl_cleanup (NULL_TREE, expr); } @@ -3158,7 +3227,8 @@ push_base_cleanups (void) tree this_member = (build_class_member_access_expr (current_class_ref, member, /*access_path=*/NULL_TREE, - /*preserve_reference=*/false)); + /*preserve_reference=*/false, + tf_warning_or_error)); tree this_type = TREE_TYPE (member); expr = build_delete (this_type, this_member, sfk_complete_destructor, @@ -3211,7 +3281,7 @@ build_vec_delete (tree base, tree maxindex, build_pointer_type (sizetype), base, cookie_addr); - maxindex = build_indirect_ref (cookie_addr, NULL); + maxindex = cp_build_indirect_ref (cookie_addr, NULL, tf_warning_or_error); } else if (TREE_CODE (type) == ARRAY_TYPE) { @@ -3219,7 +3289,7 @@ build_vec_delete (tree base, tree maxindex, bad name. */ maxindex = array_type_nelts_total (type); type = strip_array_types (type); - base = build_unary_op (ADDR_EXPR, base, 1); + base = cp_build_unary_op (ADDR_EXPR, base, 1, tf_warning_or_error); if (TREE_SIDE_EFFECTS (base)) { base_init = get_target_expr (base); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index c8061bb..5d50f85 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -674,7 +674,8 @@ do_build_assign_ref (tree fndecl) build_tree_list (NULL_TREE, converted_parm), base_binfo, - LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL, + tf_warning_or_error)); } /* Assign to each of the non-static data members. */ @@ -729,7 +730,8 @@ do_build_assign_ref (tree fndecl) init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); if (DECL_NAME (field)) - init = build_modify_expr (comp, NOP_EXPR, init); + init = cp_build_modify_expr (comp, NOP_EXPR, init, + tf_warning_or_error); else init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init); finish_expr_stmt (init); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 8156822..8a9c3e2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4333,19 +4333,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, { case RID_DYNCAST: postfix_expression - = build_dynamic_cast (type, expression); + = build_dynamic_cast (type, expression, tf_warning_or_error); break; case RID_STATCAST: postfix_expression - = build_static_cast (type, expression); + = build_static_cast (type, expression, tf_warning_or_error); break; case RID_REINTCAST: postfix_expression - = build_reinterpret_cast (type, expression); + = build_reinterpret_cast (type, expression, + tf_warning_or_error); break; case RID_CONSTCAST: postfix_expression - = build_const_cast (type, expression); + = build_const_cast (type, expression, tf_warning_or_error); break; default: gcc_unreachable (); @@ -4644,12 +4645,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, (instance, fn, args, NULL_TREE, (idk == CP_ID_KIND_QUALIFIED ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL), - /*fn_p=*/NULL)); + /*fn_p=*/NULL, + tf_warning_or_error)); else postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, - /*koenig_p=*/false); + /*koenig_p=*/false, + tf_warning_or_error); } else if (TREE_CODE (postfix_expression) == OFFSET_REF || TREE_CODE (postfix_expression) == MEMBER_REF @@ -4662,13 +4665,15 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/true, - koenig_p); + koenig_p, + tf_warning_or_error); else /* All other function calls. */ postfix_expression = finish_call_expr (postfix_expression, args, /*disallow_virtual=*/false, - koenig_p); + koenig_p, + tf_warning_or_error); /* The POSTFIX_EXPRESSION is certainly no longer an id. */ idk = CP_ID_KIND_NONE; @@ -4937,7 +4942,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, (name, BINFO_TYPE (BASELINK_ACCESS_BINFO (name)), scope); postfix_expression = finish_class_member_access_expr (postfix_expression, name, - template_p); + template_p, + tf_warning_or_error); } } @@ -5250,7 +5256,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) if (TYPE_P (operand)) return cxx_sizeof_or_alignof_type (operand, op, true); else - return cxx_sizeof_or_alignof_expr (operand, op); + return cxx_sizeof_or_alignof_expr (operand, op, true); } case RID_NEW: @@ -5287,7 +5293,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) /* Create the complete representation. */ return build_x_unary_op ((keyword == RID_REALPART ? REALPART_EXPR : IMAGPART_EXPR), - expression); + expression, + tf_warning_or_error); } break; @@ -5362,14 +5369,16 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p) { case INDIRECT_REF: non_constant_p = "`*'"; - expression = build_x_indirect_ref (cast_expression, "unary *"); + expression = build_x_indirect_ref (cast_expression, "unary *", + tf_warning_or_error); break; case ADDR_EXPR: non_constant_p = "`&'"; /* Fall through. */ case BIT_NOT_EXPR: - expression = build_x_unary_op (unary_operator, cast_expression); + expression = build_x_unary_op (unary_operator, cast_expression, + tf_warning_or_error); break; case PREINCREMENT_EXPR: @@ -5500,7 +5509,8 @@ cp_parser_new_expression (cp_parser* parser) return error_mark_node; /* Create a representation of the new-expression. */ - return build_new (placement, type, nelts, initializer, global_scope_p); + return build_new (placement, type, nelts, initializer, global_scope_p, + tf_warning_or_error); } /* Parse a new-placement. @@ -5870,7 +5880,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p) return error_mark_node; /* Perform the cast. */ - expr = build_c_cast (type, expr); + expr = build_c_cast (type, expr, tf_warning_or_error); return expr; } } @@ -6059,7 +6069,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p) overloaded_p = false; lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type, - &overloaded_p); + &overloaded_p, tf_warning_or_error); lhs_type = tree_type; /* If the binary operator required the use of an overloaded operator, @@ -6115,7 +6125,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr) /* Build the conditional-expression. */ return build_x_conditional_expr (logical_or_expr, expr, - assignment_expr); + assignment_expr, + tf_warning_or_error); } /* Parse an assignment-expression. @@ -6170,7 +6181,8 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p) /* Build the assignment expression. */ expr = build_x_modify_expr (expr, assignment_operator, - rhs); + rhs, + tf_warning_or_error); } } } @@ -6290,7 +6302,8 @@ cp_parser_expression (cp_parser* parser, bool cast_p) expression = assignment_expression; else expression = build_x_compound_expr (expression, - assignment_expression); + assignment_expression, + tf_warning_or_error); /* If the next token is not a comma, then we are done with the expression. */ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA)) @@ -6410,7 +6423,8 @@ cp_parser_builtin_offsetof (cp_parser *parser) cp_parser_require (parser, CPP_COMMA, "`,'"); /* Build the (type *)null that begins the traditional offsetof macro. */ - expr = build_static_cast (build_pointer_type (type), null_pointer_node); + expr = build_static_cast (build_pointer_type (type), null_pointer_node, + tf_warning_or_error); /* Parse the offsetof-member-designator. We begin as if we saw "expr->". */ expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr, @@ -10320,7 +10334,8 @@ cp_parser_template_argument (cp_parser* parser) if (cp_parser_parse_definitely (parser)) { if (address_p) - argument = build_x_unary_op (ADDR_EXPR, argument); + argument = build_x_unary_op (ADDR_EXPR, argument, + tf_warning_or_error); return argument; } } @@ -17181,7 +17196,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type) /*allow_expansion_p=*/true, /*non_constant_p=*/NULL); - cast = build_functional_cast (type, expression_list); + cast = build_functional_cast (type, expression_list, + tf_warning_or_error); /* [expr.const]/1: In an integral constant expression "only type conversions to integral or enumeration type can be used". */ if (TREE_CODE (type) == TYPE_DECL) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 628a445..bc33efc 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10684,7 +10684,7 @@ tsubst_copy_and_build (tree t, r = convert_from_reference (r); } else - r = build_x_indirect_ref (r, "unary *"); + r = build_x_indirect_ref (r, "unary *", complain); return r; } @@ -10706,8 +10706,9 @@ tsubst_copy_and_build (tree t, if (integral_constant_expression_p && !cast_valid_in_integral_constant_expression_p (type)) { - error ("a cast to a type other than an integral or " - "enumeration type cannot appear in a constant-expression"); + if (complain & tf_error) + error ("a cast to a type other than an integral or " + "enumeration type cannot appear in a constant-expression"); return error_mark_node; } @@ -10716,15 +10717,15 @@ tsubst_copy_and_build (tree t, switch (TREE_CODE (t)) { case CAST_EXPR: - return build_functional_cast (type, op); + return build_functional_cast (type, op, complain); case REINTERPRET_CAST_EXPR: - return build_reinterpret_cast (type, op); + return build_reinterpret_cast (type, op, complain); case CONST_CAST_EXPR: - return build_const_cast (type, op); + return build_const_cast (type, op, complain); case DYNAMIC_CAST_EXPR: - return build_dynamic_cast (type, op); + return build_dynamic_cast (type, op, complain); case STATIC_CAST_EXPR: - return build_static_cast (type, op); + return build_static_cast (type, op, complain); default: gcc_unreachable (); } @@ -10734,7 +10735,7 @@ tsubst_copy_and_build (tree t, case POSTINCREMENT_EXPR: op1 = tsubst_non_call_postfix_expression (TREE_OPERAND (t, 0), args, complain, in_decl); - return build_x_unary_op (TREE_CODE (t), op1); + return build_x_unary_op (TREE_CODE (t), op1, complain); case PREDECREMENT_EXPR: case PREINCREMENT_EXPR: @@ -10745,7 +10746,8 @@ tsubst_copy_and_build (tree t, case UNARY_PLUS_EXPR: /* Unary + */ case REALPART_EXPR: case IMAGPART_EXPR: - return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0))); + return build_x_unary_op (TREE_CODE (t), RECUR (TREE_OPERAND (t, 0)), + complain); case ADDR_EXPR: op1 = TREE_OPERAND (t, 0); @@ -10757,7 +10759,7 @@ tsubst_copy_and_build (tree t, in_decl); if (TREE_CODE (op1) == LABEL_DECL) return finish_label_address_expr (DECL_NAME (op1)); - return build_x_unary_op (ADDR_EXPR, op1); + return build_x_unary_op (ADDR_EXPR, op1, complain); case PLUS_EXPR: case MINUS_EXPR: @@ -10800,7 +10802,8 @@ tsubst_copy_and_build (tree t, (TREE_NO_WARNING (TREE_OPERAND (t, 1)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, + complain); case SCOPE_REF: return tsubst_qualified_id (t, args, complain, in_decl, /*done=*/true, @@ -10816,7 +10819,8 @@ tsubst_copy_and_build (tree t, (TREE_NO_WARNING (TREE_OPERAND (t, 1)) ? ERROR_MARK : TREE_CODE (TREE_OPERAND (t, 1))), - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, + complain); case SIZEOF_EXPR: if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))) @@ -10849,16 +10853,19 @@ tsubst_copy_and_build (tree t, --skip_evaluation; } if (TYPE_P (op1)) - return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), true); + return cxx_sizeof_or_alignof_type (op1, TREE_CODE (t), + complain & tf_error); else - return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t)); + return cxx_sizeof_or_alignof_expr (op1, TREE_CODE (t), + complain & tf_error); case MODOP_EXPR: { tree r = build_x_modify_expr (RECUR (TREE_OPERAND (t, 0)), TREE_CODE (TREE_OPERAND (t, 1)), - RECUR (TREE_OPERAND (t, 2))); + RECUR (TREE_OPERAND (t, 2)), + complain); /* TREE_NO_WARNING must be set if either the expression was parenthesized or it uses an operator such as >>= rather than plain assignment. In the former case, it was already @@ -10896,7 +10903,8 @@ tsubst_copy_and_build (tree t, RECUR (TREE_OPERAND (t, 1)), RECUR (TREE_OPERAND (t, 2)), init, - NEW_EXPR_USE_GLOBAL (t)); + NEW_EXPR_USE_GLOBAL (t), + complain); } case DELETE_EXPR: @@ -10908,7 +10916,8 @@ tsubst_copy_and_build (tree t, case COMPOUND_EXPR: return build_x_compound_expr (RECUR (TREE_OPERAND (t, 0)), - RECUR (TREE_OPERAND (t, 1))); + RECUR (TREE_OPERAND (t, 1)), + complain); case CALL_EXPR: { @@ -10982,25 +10991,29 @@ tsubst_copy_and_build (tree t, if (!BASELINK_P (TREE_OPERAND (function, 1))) return finish_call_expr (function, call_args, /*disallow_virtual=*/false, - /*koenig_p=*/false); + /*koenig_p=*/false, + complain); else return (build_new_method_call (TREE_OPERAND (function, 0), TREE_OPERAND (function, 1), call_args, NULL_TREE, qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL, - /*fn_p=*/NULL)); + /*fn_p=*/NULL, + complain)); } return finish_call_expr (function, call_args, /*disallow_virtual=*/qualified_p, - koenig_p); + koenig_p, + complain); } case COND_EXPR: return build_x_conditional_expr (RECUR (TREE_OPERAND (t, 0)), RECUR (TREE_OPERAND (t, 1)), - RECUR (TREE_OPERAND (t, 2))); + RECUR (TREE_OPERAND (t, 2)), + complain); case PSEUDO_DTOR_EXPR: return finish_pseudo_destructor_expr @@ -11184,7 +11197,8 @@ tsubst_copy_and_build (tree t, return finish_non_static_data_member (member, object, NULL_TREE); return finish_class_member_access_expr (object, member, - /*template_p=*/false); + /*template_p=*/false, + complain); } case THROW_EXPR: diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c index 8bd51c8..d17ef64 100644 --- a/gcc/cp/rtti.c +++ b/gcc/cp/rtti.c @@ -104,7 +104,7 @@ static GTY (()) VEC(tinfo_s,gc) *tinfo_descs; static tree ifnonnull (tree, tree); static tree tinfo_name (tree); -static tree build_dynamic_cast_1 (tree, tree); +static tree build_dynamic_cast_1 (tree, tree, tsubst_flags_t); static tree throw_bad_cast (void); static tree throw_bad_typeid (void); static tree get_tinfo_decl_dynamic (tree); @@ -188,7 +188,9 @@ build_headof (tree exp) index = build_int_cst (NULL_TREE, -2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE); - offset = build_vtbl_ref (build_indirect_ref (exp, NULL), index); + offset = build_vtbl_ref (cp_build_indirect_ref (exp, NULL, + tf_warning_or_error), + index); type = build_qualified_type (ptr_type_node, cp_type_quals (TREE_TYPE (exp))); @@ -272,7 +274,7 @@ get_tinfo_decl_dynamic (tree exp) /* Otherwise return the type_info for the static type of the expr. */ t = get_tinfo_ptr (TYPE_MAIN_VARIANT (type)); - return build_indirect_ref (t, NULL); + return cp_build_indirect_ref (t, NULL, tf_warning_or_error); } static bool @@ -463,7 +465,8 @@ get_typeid (tree type) if (!type) return error_mark_node; - return build_indirect_ref (get_tinfo_ptr (type), NULL); + return cp_build_indirect_ref (get_tinfo_ptr (type), NULL, + tf_warning_or_error); } /* Check whether TEST is null before returning RESULT. If TEST is used in @@ -483,7 +486,7 @@ ifnonnull (tree test, tree result) paper. */ static tree -build_dynamic_cast_1 (tree type, tree expr) +build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) { enum tree_code tc = TREE_CODE (type); tree exprtype = TREE_TYPE (expr); @@ -626,8 +629,9 @@ build_dynamic_cast_1 (tree type, tree expr) && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE) { tree expr = throw_bad_cast (); - warning (0, "dynamic_cast of %q#D to %q#T can never succeed", - old_expr, type); + if (complain & tf_warning) + warning (0, "dynamic_cast of %q#D to %q#T can never succeed", + old_expr, type); /* Bash it to the expected type. */ TREE_TYPE (expr) = type; return expr; @@ -640,8 +644,9 @@ build_dynamic_cast_1 (tree type, tree expr) if (TREE_CODE (op) == VAR_DECL && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE) { - warning (0, "dynamic_cast of %q#D to %q#T can never succeed", - op, type); + if (complain & tf_warning) + warning (0, "dynamic_cast of %q#D to %q#T can never succeed", + op, type); retval = build_int_cst (type, 0); return retval; } @@ -650,7 +655,8 @@ build_dynamic_cast_1 (tree type, tree expr) /* Use of dynamic_cast when -fno-rtti is prohibited. */ if (!flag_rtti) { - error ("%<dynamic_cast%> not permitted with -fno-rtti"); + if (complain & tf_error) + error ("%<dynamic_cast%> not permitted with -fno-rtti"); return error_mark_node; } @@ -658,10 +664,10 @@ build_dynamic_cast_1 (tree type, tree expr) static_type = TYPE_MAIN_VARIANT (TREE_TYPE (exprtype)); td2 = get_tinfo_decl (target_type); mark_used (td2); - td2 = build_unary_op (ADDR_EXPR, td2, 0); + td2 = cp_build_unary_op (ADDR_EXPR, td2, 0, complain); td3 = get_tinfo_decl (static_type); mark_used (td3); - td3 = build_unary_op (ADDR_EXPR, td3, 0); + td3 = cp_build_unary_op (ADDR_EXPR, td3, 0, complain); /* Determine how T and V are related. */ boff = dcast_base_hint (static_type, target_type); @@ -671,7 +677,7 @@ build_dynamic_cast_1 (tree type, tree expr) expr1 = expr; if (tc == REFERENCE_TYPE) - expr1 = build_unary_op (ADDR_EXPR, expr1, 0); + expr1 = cp_build_unary_op (ADDR_EXPR, expr1, 0, complain); elems[0] = expr1; elems[1] = td3; @@ -726,13 +732,14 @@ build_dynamic_cast_1 (tree type, tree expr) errstr = "source type is not polymorphic"; fail: - error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)", - expr, exprtype, type, errstr); + if (complain & tf_error) + error ("cannot dynamic_cast %qE (of type %q#T) to type %q#T (%s)", + expr, exprtype, type, errstr); return error_mark_node; } tree -build_dynamic_cast (tree type, tree expr) +build_dynamic_cast (tree type, tree expr, tsubst_flags_t complain) { if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -744,7 +751,7 @@ build_dynamic_cast (tree type, tree expr) return convert_from_reference (expr); } - return convert_from_reference (build_dynamic_cast_1 (type, expr)); + return convert_from_reference (build_dynamic_cast_1 (type, expr, complain)); } /* Return the runtime bit mask encoding the qualifiers of TYPE. */ @@ -876,7 +883,8 @@ tinfo_base_init (tinfo_s *ti, tree target) } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); - vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); + vtable_ptr = cp_build_unary_op (ADDR_EXPR, vtable_ptr, 0, + tf_warning_or_error); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 74d9ae5..8966bf5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -536,7 +536,7 @@ simplify_loop_decl_cond (tree *cond_p, tree body) *cond_p = boolean_true_node; if_stmt = begin_if_stmt (); - cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0); + cond = cp_build_unary_op (TRUTH_NOT_EXPR, cond, 0, tf_warning_or_error); finish_if_stmt_cond (cond, if_stmt); finish_break_stmt (); finish_then_clause (if_stmt); @@ -614,10 +614,11 @@ finish_expr_stmt (tree expr) { if (warn_sequence_point) verify_sequence_points (expr); - expr = convert_to_void (expr, "statement"); + expr = convert_to_void (expr, "statement", tf_warning_or_error); } else if (!type_dependent_expression_p (expr)) - convert_to_void (build_non_dependent_expr (expr), "statement"); + convert_to_void (build_non_dependent_expr (expr), "statement", + tf_warning_or_error); if (check_for_bare_parameter_packs (expr)) expr = error_mark_node; @@ -872,10 +873,12 @@ finish_for_expr (tree expr, tree for_stmt) { if (warn_sequence_point) verify_sequence_points (expr); - expr = convert_to_void (expr, "3rd expression in for"); + expr = convert_to_void (expr, "3rd expression in for", + tf_warning_or_error); } else if (!type_dependent_expression_p (expr)) - convert_to_void (build_non_dependent_expr (expr), "3rd expression in for"); + convert_to_void (build_non_dependent_expr (expr), "3rd expression in for", + tf_warning_or_error); expr = maybe_cleanup_point_expr_void (expr); if (check_for_bare_parameter_packs (expr)) expr = error_mark_node; @@ -1247,7 +1250,7 @@ finish_asm_stmt (int volatile_p, tree string, tree output_operands, otherwise we'll get an error. Gross, but ... */ STRIP_NOPS (operand); - if (!lvalue_or_else (operand, lv_asm)) + if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error)) operand = error_mark_node; if (operand != error_mark_node @@ -1505,7 +1508,8 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) return build_class_member_access_expr (object, decl, /*access_path=*/NULL_TREE, - /*preserve_reference=*/false); + /*preserve_reference=*/false, + tf_warning_or_error); } } @@ -1643,7 +1647,8 @@ finish_qualified_id_expr (tree qualifying_class, (maybe_dummy_object (qualifying_class, NULL), expr, BASELINK_ACCESS_BINFO (expr), - /*preserve_reference=*/false)); + /*preserve_reference=*/false, + tf_warning_or_error)); else if (done) /* The expression is a qualified name whose address is not being taken. */ @@ -1832,7 +1837,8 @@ perform_koenig_lookup (tree fn, tree args) Returns code for the call. */ tree -finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) +finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p, + tsubst_flags_t complain) { tree result; tree orig_fn; @@ -1931,7 +1937,8 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) result = build_new_method_call (object, fn, args, NULL_TREE, (disallow_virtual ? LOOKUP_NONVIRTUAL : 0), - /*fn_p=*/NULL); + /*fn_p=*/NULL, + complain); } else if (is_overloaded_fn (fn)) { @@ -1943,7 +1950,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) if (!result) /* A call to a namespace-scope function. */ - result = build_new_function_call (fn, args, koenig_p); + result = build_new_function_call (fn, args, koenig_p, complain); } else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) { @@ -1960,11 +1967,11 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) /* If the "function" is really an object of class type, it might have an overloaded `operator ()'. */ result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE, - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, complain); if (!result) /* A call where the function is unknown. */ - result = build_function_call (fn, args); + result = cp_build_function_call (fn, args, complain); if (processing_template_decl) { @@ -1981,7 +1988,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p) tree finish_increment_expr (tree expr, enum tree_code code) { - return build_x_unary_op (code, expr); + return build_x_unary_op (code, expr, tf_warning_or_error); } /* Finish a use of `this'. Returns an expression for `this'. */ @@ -2070,7 +2077,7 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor) tree finish_unary_op_expr (enum tree_code code, tree expr) { - tree result = build_x_unary_op (code, expr); + tree result = build_x_unary_op (code, expr, tf_warning_or_error); /* Inside a template, build_x_unary_op does not fold the expression. So check whether the result is folded before setting TREE_NEGATED_INT. */ @@ -2952,7 +2959,8 @@ finish_id_expression (tree id_expression, /* A set of member functions. */ decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0); return finish_class_member_access_expr (decl, id_expression, - /*template_p=*/false); + /*template_p=*/false, + tf_warning_or_error); } decl = baselink_for_fns (decl); @@ -3119,7 +3127,8 @@ simplify_aggr_init_expr (tree *tp) SLOT. */ push_deferring_access_checks (dk_no_check); call_expr = build_aggr_init (slot, call_expr, - DIRECT_BIND | LOOKUP_ONLYCONVERTING); + DIRECT_BIND | LOOKUP_ONLYCONVERTING, + tf_warning_or_error); pop_deferring_access_checks (); call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); } @@ -3668,7 +3677,8 @@ finish_omp_clauses (tree clauses) } t = build_special_member_call (NULL_TREE, complete_ctor_identifier, - t, inner_type, LOOKUP_NORMAL); + t, inner_type, LOOKUP_NORMAL, + tf_warning_or_error); if (targetm.cxx.cdtor_returns_this () || errorcount) /* Because constructors and destructors return this, @@ -3690,7 +3700,8 @@ finish_omp_clauses (tree clauses) t = build_int_cst (build_pointer_type (inner_type), 0); t = build1 (INDIRECT_REF, inner_type, t); t = build_special_member_call (t, complete_dtor_identifier, - NULL, inner_type, LOOKUP_NORMAL); + NULL, inner_type, LOOKUP_NORMAL, + tf_warning_or_error); if (targetm.cxx.cdtor_returns_this () || errorcount) /* Because constructors and destructors return this, @@ -3713,7 +3724,8 @@ finish_omp_clauses (tree clauses) t = build1 (INDIRECT_REF, inner_type, t); t = build_special_member_call (t, ansi_assopname (NOP_EXPR), build_tree_list (NULL, t), - inner_type, LOOKUP_NORMAL); + inner_type, LOOKUP_NORMAL, + tf_warning_or_error); /* We'll have called convert_from_reference on the call, which may well have added an indirect_ref. It's unneeded here, @@ -3937,7 +3949,7 @@ finish_omp_for (location_t locus, tree decl, tree init, tree cond, if (!processing_template_decl) init = fold_build_cleanup_point_expr (TREE_TYPE (init), init); - init = build_modify_expr (decl, NOP_EXPR, init); + init = cp_build_modify_expr (decl, NOP_EXPR, init, tf_warning_or_error); if (cond && TREE_SIDE_EFFECTS (cond) && COMPARISON_CLASS_P (cond)) { int n = TREE_SIDE_EFFECTS (TREE_OPERAND (cond, 1)) != 0; @@ -4006,7 +4018,7 @@ void finish_omp_barrier (void) { tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER]; - tree stmt = finish_call_expr (fn, NULL, false, false); + tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); finish_expr_stmt (stmt); } @@ -4014,7 +4026,7 @@ void finish_omp_flush (void) { tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE]; - tree stmt = finish_call_expr (fn, NULL, false, false); + tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error); finish_expr_stmt (stmt); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 927b3de..027f1c9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -1992,7 +1992,7 @@ tree build_dummy_object (tree type) { tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node); - return build_indirect_ref (decl, NULL); + return cp_build_indirect_ref (decl, NULL, tf_warning_or_error); } /* We've gotten a reference to a member of TYPE. Return *this if appropriate, @@ -2569,10 +2569,10 @@ stabilize_expr (tree exp, tree* initp) } else { - exp = build_unary_op (ADDR_EXPR, exp, 1); + exp = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error); init_expr = get_target_expr (exp); exp = TARGET_EXPR_SLOT (init_expr); - exp = build_indirect_ref (exp, 0); + exp = cp_build_indirect_ref (exp, 0, tf_warning_or_error); } *initp = init_expr; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 036f93e..2e8151b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -47,9 +47,11 @@ along with GCC; see the file COPYING3. If not see static tree pfn_from_ptrmemfunc (tree); static tree delta_from_ptrmemfunc (tree); -static tree convert_for_assignment (tree, tree, const char *, tree, int); +static tree convert_for_assignment (tree, tree, const char *, tree, int, + tsubst_flags_t); static tree cp_pointer_int_sum (enum tree_code, tree, tree); -static tree rationalize_conditional_expr (enum tree_code, tree); +static tree rationalize_conditional_expr (enum tree_code, tree, + tsubst_flags_t); 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); @@ -59,7 +61,8 @@ static void casts_away_constness_r (tree *, tree *); static bool casts_away_constness (tree, tree); static void maybe_warn_about_returning_address_of_local (tree); static tree lookup_destructor (tree, tree, tree); -static int convert_arguments (int, tree *, tree, tree, tree, int); +static int convert_arguments (int, tree *, tree, tree, tree, int, + tsubst_flags_t); /* Do `exp = require_complete_type (exp);' to make sure exp does not have an incomplete type. (That includes void types.) @@ -394,7 +397,8 @@ type_after_usual_arithmetic_conversions (tree t1, tree t2) case. See that function for documentation fo the parameters. */ static tree -composite_pointer_type_r (tree t1, tree t2, const char* location) +composite_pointer_type_r (tree t1, tree t2, const char* location, + tsubst_flags_t complain) { tree pointee1; tree pointee2; @@ -426,12 +430,14 @@ composite_pointer_type_r (tree t1, tree t2, const char* location) && TREE_CODE (pointee2) == POINTER_TYPE) || (TYPE_PTR_TO_MEMBER_P (pointee1) && TYPE_PTR_TO_MEMBER_P (pointee2))) - result_type = composite_pointer_type_r (pointee1, pointee2, location); + result_type = composite_pointer_type_r (pointee1, pointee2, location, + complain); else { - pedwarn ("%s between distinct pointer types %qT and %qT " - "lacks a cast", - location, t1, t2); + if (complain & tf_error) + pedwarn ("%s between distinct pointer types %qT and %qT " + "lacks a cast", + location, t1, t2); result_type = void_type_node; } result_type = cp_build_qualified_type (result_type, @@ -442,7 +448,8 @@ composite_pointer_type_r (tree t1, tree t2, const char* location) if (TYPE_PTR_TO_MEMBER_P (t1)) { if (!same_type_p (TYPE_PTRMEM_CLASS_TYPE (t1), - TYPE_PTRMEM_CLASS_TYPE (t2))) + TYPE_PTRMEM_CLASS_TYPE (t2)) + && (complain & tf_error)) pedwarn ("%s between distinct pointer types %qT and %qT " "lacks a cast", location, t1, t2); @@ -466,7 +473,7 @@ composite_pointer_type_r (tree t1, tree t2, const char* location) tree composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, - const char* location) + const char* location, tsubst_flags_t complain) { tree class1; tree class2; @@ -504,7 +511,7 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, tree attributes; tree result_type; - if (pedantic && TYPE_PTRFN_P (t2)) + if (pedantic && TYPE_PTRFN_P (t2) && (complain & tf_error)) pedwarn ("ISO C++ forbids %s between pointer of type %<void *%> " "and pointer-to-function", location); result_type @@ -543,8 +550,9 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, (cp_build_qualified_type (class2, TYPE_QUALS (class1)))); else { - error ("%s between distinct pointer types %qT and %qT " - "lacks a cast", location, t1, t2); + if (complain & tf_error) + error ("%s between distinct pointer types %qT and %qT " + "lacks a cast", location, t1, t2); return error_mark_node; } } @@ -563,13 +571,14 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2, t2 = build_ptrmem_type (class1, TYPE_PTRMEM_POINTED_TO_TYPE (t2)); else { - error ("%s between distinct pointer-to-member types %qT and %qT " - "lacks a cast", location, t1, t2); + if (complain & tf_error) + error ("%s between distinct pointer-to-member types %qT and %qT " + "lacks a cast", location, t1, t2); return error_mark_node; } } - return composite_pointer_type_r (t1, t2, location); + return composite_pointer_type_r (t1, t2, location, complain); } /* Return the merged type of two types. @@ -764,7 +773,7 @@ common_type (tree t1, tree t2) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2)) || (TYPE_PTRMEMFUNC_P (t1) && TYPE_PTRMEMFUNC_P (t2))) return composite_pointer_type (t1, t2, error_mark_node, error_mark_node, - "conversion"); + "conversion", tf_warning_or_error); else gcc_unreachable (); } @@ -1299,10 +1308,27 @@ cxx_sizeof_or_alignof_type (tree type, enum tree_code op, bool complain) complain); } +/* Return the size of the type, without producing any warnings for + types whose size cannot be taken. This routine should be used only + in some other routine that has already produced a diagnostic about + using the size of such a type. */ +tree +cxx_sizeof_nowarn (tree type) +{ + if (TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == VOID_TYPE + || TREE_CODE (type) == ERROR_MARK) + return size_one_node; + else if (!COMPLETE_TYPE_P (type)) + return size_zero_node; + else + return cxx_sizeof_or_alignof_type (type, SIZEOF_EXPR, false); +} + /* Process a sizeof expression where the operand is an expression. */ static tree -cxx_sizeof_expr (tree e) +cxx_sizeof_expr (tree e, tsubst_flags_t complain) { if (e == error_mark_node) return error_mark_node; @@ -1320,24 +1346,33 @@ cxx_sizeof_expr (tree e) && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) { - error ("invalid application of %<sizeof%> to a bit-field"); + if (complain & tf_error) + error ("invalid application of %<sizeof%> to a bit-field"); + else + return error_mark_node; e = char_type_node; } else if (is_overloaded_fn (e)) { - pedwarn ("ISO C++ forbids applying %<sizeof%> to an expression of " - "function type"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids applying %<sizeof%> to an expression of " + "function type"); + else + return error_mark_node; e = char_type_node; } else if (type_unknown_p (e)) { - cxx_incomplete_type_error (e, TREE_TYPE (e)); + if (complain & tf_error) + cxx_incomplete_type_error (e, TREE_TYPE (e)); + else + return error_mark_node; e = char_type_node; } else e = TREE_TYPE (e); - return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, true); + return cxx_sizeof_or_alignof_type (e, SIZEOF_EXPR, complain & tf_error); } /* Implement the __alignof keyword: Return the minimum required @@ -1346,7 +1381,7 @@ cxx_sizeof_expr (tree e) "aligned" __attribute__ specification). */ static tree -cxx_alignof_expr (tree e) +cxx_alignof_expr (tree e, tsubst_flags_t complain) { tree t; @@ -1368,7 +1403,10 @@ cxx_alignof_expr (tree e) && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) { - error ("invalid application of %<__alignof%> to a bit-field"); + if (complain & tf_error) + error ("invalid application of %<__alignof%> to a bit-field"); + else + return error_mark_node; t = size_one_node; } else if (TREE_CODE (e) == COMPONENT_REF @@ -1376,8 +1414,11 @@ cxx_alignof_expr (tree e) t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (e, 1))); else if (is_overloaded_fn (e)) { - pedwarn ("ISO C++ forbids applying %<__alignof%> to an expression of " - "function type"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids applying %<__alignof%> to an expression of " + "function type"); + else + return error_mark_node; if (TREE_CODE (e) == FUNCTION_DECL) t = size_int (DECL_ALIGN_UNIT (e)); else @@ -1385,11 +1426,15 @@ cxx_alignof_expr (tree e) } else if (type_unknown_p (e)) { - cxx_incomplete_type_error (e, TREE_TYPE (e)); + if (complain & tf_error) + cxx_incomplete_type_error (e, TREE_TYPE (e)); + else + return error_mark_node; t = size_one_node; } else - return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, true); + return cxx_sizeof_or_alignof_type (TREE_TYPE (e), ALIGNOF_EXPR, + complain & tf_error); return fold_convert (size_type_node, t); } @@ -1398,12 +1443,12 @@ cxx_alignof_expr (tree e) is an expression. */ tree -cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) +cxx_sizeof_or_alignof_expr (tree e, enum tree_code op, bool complain) { if (op == SIZEOF_EXPR) - return cxx_sizeof_expr (e); + return cxx_sizeof_expr (e, complain? tf_warning_or_error : tf_none); else - return cxx_alignof_expr (e); + return cxx_alignof_expr (e, complain? tf_warning_or_error : tf_none); } /* EXPR is being used in a context that is not a function call. @@ -1423,11 +1468,12 @@ cxx_sizeof_or_alignof_expr (tree e, enum tree_code op) violates these rules. */ bool -invalid_nonstatic_memfn_p (const_tree expr) +invalid_nonstatic_memfn_p (const_tree expr, tsubst_flags_t complain) { if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE) { - error ("invalid use of non-static member function"); + if (complain & tf_error) + error ("invalid use of non-static member function"); return true; } return false; @@ -1536,10 +1582,10 @@ decay_conversion (tree exp) error ("void value not ignored as it ought to be"); return error_mark_node; } - if (invalid_nonstatic_memfn_p (exp)) + if (invalid_nonstatic_memfn_p (exp, tf_warning_or_error)) return error_mark_node; if (code == FUNCTION_TYPE || is_overloaded_fn (exp)) - return build_unary_op (ADDR_EXPR, exp, 0); + return cp_build_unary_op (ADDR_EXPR, exp, 0, tf_warning_or_error); if (code == ARRAY_TYPE) { tree adr; @@ -1574,7 +1620,7 @@ decay_conversion (tree exp) } /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ - adr = build_unary_op (ADDR_EXPR, exp, 1); + adr = cp_build_unary_op (ADDR_EXPR, exp, 1, tf_warning_or_error); return cp_convert (ptrtype, adr); } @@ -1715,7 +1761,8 @@ string_conv_p (const_tree totype, const_tree exp, int warn) get it there. */ static tree -rationalize_conditional_expr (enum tree_code code, tree t) +rationalize_conditional_expr (enum tree_code code, tree t, + tsubst_flags_t complain) { /* For MIN_EXPR or MAX_EXPR, fold-const.c has arranged things so that the first operand is always the one to be used if both operands @@ -1733,15 +1780,20 @@ rationalize_conditional_expr (enum tree_code code, tree t) ? LE_EXPR : GE_EXPR), op0, TREE_CODE (op0), op1, TREE_CODE (op1), - /*overloaded_p=*/NULL), - build_unary_op (code, op0, 0), - build_unary_op (code, op1, 0)); + /*overloaded_p=*/NULL, + complain), + cp_build_unary_op (code, op0, 0, complain), + cp_build_unary_op (code, op1, 0, complain), + complain); } return build_conditional_expr (TREE_OPERAND (t, 0), - build_unary_op (code, TREE_OPERAND (t, 1), 0), - build_unary_op (code, TREE_OPERAND (t, 2), 0)); + cp_build_unary_op (code, TREE_OPERAND (t, 1), 0, + complain), + cp_build_unary_op (code, TREE_OPERAND (t, 2), 0, + complain), + complain); } /* Given the TYPE of an anonymous union field inside T, return the @@ -1794,7 +1846,8 @@ lookup_anon_field (tree t, tree type) tree build_class_member_access_expr (tree object, tree member, - tree access_path, bool preserve_reference) + tree access_path, bool preserve_reference, + tsubst_flags_t complain) { tree object_type; tree member_scope; @@ -1815,8 +1868,9 @@ build_class_member_access_expr (tree object, tree member, return error_mark_node; if (!CLASS_TYPE_P (object_type)) { - error ("request for member %qD in %qE, which is of non-class type %qT", - member, object, object_type); + if (complain & tf_error) + error ("request for member %qD in %qE, which is of non-class type %qT", + member, object, object_type); return error_mark_node; } @@ -1841,10 +1895,13 @@ build_class_member_access_expr (tree object, tree member, member_scope = TYPE_CONTEXT (member_scope); if (!member_scope || !DERIVED_FROM_P (member_scope, object_type)) { - if (TREE_CODE (member) == FIELD_DECL) - error ("invalid use of nonstatic data member %qE", member); - else - error ("%qD is not a member of %qT", member, object_type); + if (complain & tf_error) + { + if (TREE_CODE (member) == FIELD_DECL) + error ("invalid use of nonstatic data member %qE", member); + else + error ("%qD is not a member of %qT", member, object_type); + } return error_mark_node; } @@ -1854,7 +1911,7 @@ build_class_member_access_expr (tree object, tree member, { tree temp = unary_complex_lvalue (ADDR_EXPR, object); if (temp) - object = build_indirect_ref (temp, NULL); + object = cp_build_indirect_ref (temp, NULL, complain); } /* In [expr.ref], there is an explicit list of the valid choices for @@ -1894,10 +1951,13 @@ build_class_member_access_expr (tree object, tree member, offsetof macro. */ if (null_object_p && kind == bk_via_virtual) { - error ("invalid access to non-static data member %qD of " - "NULL object", - member); - error ("(perhaps the %<offsetof%> macro was used incorrectly)"); + if (complain & tf_error) + { + error ("invalid access to non-static data member %qD of " + "NULL object", + member); + error ("(perhaps the %<offsetof%> macro was used incorrectly)"); + } return error_mark_node; } @@ -1920,7 +1980,8 @@ build_class_member_access_expr (tree object, tree member, if (null_object_p && warn_invalid_offsetof && CLASSTYPE_NON_POD_P (object_type) && !DECL_FIELD_IS_BASE (member) - && !skip_evaluation) + && !skip_evaluation + && (complain & tf_warning)) { warning (OPT_Winvalid_offsetof, "invalid access to non-static data member %qD " @@ -1950,7 +2011,8 @@ build_class_member_access_expr (tree object, tree member, object = build_class_member_access_expr (object, anonymous_union, /*access_path=*/NULL_TREE, - preserve_reference); + preserve_reference, + complain); } /* Compute the type of the field, as described in [expr.ref]. */ @@ -2011,7 +2073,8 @@ build_class_member_access_expr (tree object, tree member, } else { - error ("invalid use of %qD", member); + if (complain & tf_error) + error ("invalid use of %qD", member); return error_mark_node; } @@ -2117,7 +2180,8 @@ check_template_keyword (tree decl) be a template via the use of the "A::template B" syntax. */ tree -finish_class_member_access_expr (tree object, tree name, bool template_p) +finish_class_member_access_expr (tree object, tree name, bool template_p, + tsubst_flags_t complain) { tree expr; tree object_type; @@ -2165,8 +2229,9 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) return error_mark_node; if (!CLASS_TYPE_P (object_type)) { - error ("request for member %qD in %qE, which is of non-class type %qT", - name, object, object_type); + if (complain & tf_error) + error ("request for member %qD in %qE, which is of non-class type %qT", + name, object, object_type); return error_mark_node; } @@ -2203,8 +2268,9 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) name a member of OBJECT_TYPE. */ if (TREE_CODE (scope) == NAMESPACE_DECL) { - error ("%<%D::%D%> is not a member of %qT", - scope, name, object_type); + if (complain & tf_error) + error ("%<%D::%D%> is not a member of %qT", + scope, name, object_type); return error_mark_node; } @@ -2218,7 +2284,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) return error_mark_node; if (!access_path) { - error ("%qT is not a base of %qT", scope, object_type); + if (complain & tf_error) + error ("%qT is not a base of %qT", scope, object_type); return error_mark_node; } } @@ -2237,7 +2304,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) /*want_type=*/false); if (member == NULL_TREE) { - error ("%qD has no member named %qE", object_type, name); + if (complain & tf_error) + error ("%qD has no member named %qE", object_type, name); return error_mark_node; } if (member == error_mark_node) @@ -2252,7 +2320,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) template = lookup_template_function (template, template_args); else { - error ("%qD is not a member template function", name); + if (complain & tf_error) + error ("%qD is not a member template function", name); return error_mark_node; } } @@ -2265,7 +2334,8 @@ finish_class_member_access_expr (tree object, tree name, bool template_p) check_template_keyword (member); expr = build_class_member_access_expr (object, member, access_path, - /*preserve_reference=*/false); + /*preserve_reference=*/false, + complain); if (processing_template_decl && expr != error_mark_node) { if (BASELINK_P (member)) @@ -2318,7 +2388,8 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) Must also handle REFERENCE_TYPEs for C++. */ tree -build_x_indirect_ref (tree expr, const char *errorstring) +build_x_indirect_ref (tree expr, const char *errorstring, + tsubst_flags_t complain) { tree orig_expr = expr; tree rval; @@ -2331,9 +2402,9 @@ build_x_indirect_ref (tree expr, const char *errorstring) } rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE, - NULL_TREE, /*overloaded_p=*/NULL); + NULL_TREE, /*overloaded_p=*/NULL, complain); if (!rval) - rval = build_indirect_ref (expr, errorstring); + rval = cp_build_indirect_ref (expr, errorstring, complain); if (processing_template_decl && rval != error_mark_node) return build_min_non_dep (INDIRECT_REF, rval, orig_expr); @@ -2341,9 +2412,17 @@ build_x_indirect_ref (tree expr, const char *errorstring) return rval; } +/* Helper function called from c-common. */ tree build_indirect_ref (tree ptr, const char *errorstring) { + return cp_build_indirect_ref (ptr, errorstring, tf_warning_or_error); +} + +tree +cp_build_indirect_ref (tree ptr, const char *errorstring, + tsubst_flags_t complain) +{ tree pointer, type; if (ptr == error_mark_node) @@ -2385,7 +2464,8 @@ build_indirect_ref (tree ptr, const char *errorstring) { /* A pointer to incomplete type (other than cv void) can be dereferenced [expr.unary.op]/1 */ - error ("%qT is not a pointer-to-object type", type); + if (complain & tf_error) + error ("%qT is not a pointer-to-object type", type); return error_mark_node; } else if (TREE_CODE (pointer) == ADDR_EXPR @@ -2407,6 +2487,9 @@ build_indirect_ref (tree ptr, const char *errorstring) return ref; } } + else if (!(complain & tf_error)) + /* Don't emit any errors; we'll just return ERROR_MARK_NODE later. */ + ; /* `pointer' won't be an error_mark_node if we were given a pointer to member, so it's cool to check for this here. */ else if (TYPE_PTR_TO_MEMBER_P (type)) @@ -2462,7 +2545,8 @@ build_array_ref (tree array, tree idx) return build_conditional_expr (TREE_OPERAND (array, 0), build_array_ref (TREE_OPERAND (array, 1), idx), - build_array_ref (TREE_OPERAND (array, 2), idx)); + build_array_ref (TREE_OPERAND (array, 2), idx), + tf_warning_or_error); default: break; @@ -2568,8 +2652,10 @@ build_array_ref (tree array, tree idx) warn_array_subscript_with_type_char (idx); - return build_indirect_ref (cp_build_binary_op (PLUS_EXPR, ar, ind), - "array indexing"); + return cp_build_indirect_ref (cp_build_binary_op (PLUS_EXPR, ar, ind, + tf_warning_or_error), + "array indexing", + tf_warning_or_error); } } @@ -2627,13 +2713,17 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) switch (TARGET_PTRMEMFUNC_VBIT_LOCATION) { case ptrmemfunc_vbit_in_pfn: - e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node); - idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node); + e1 = cp_build_binary_op (BIT_AND_EXPR, idx, integer_one_node, + tf_warning_or_error); + idx = cp_build_binary_op (MINUS_EXPR, idx, integer_one_node, + tf_warning_or_error); break; case ptrmemfunc_vbit_in_delta: - e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node); - delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node); + e1 = cp_build_binary_op (BIT_AND_EXPR, delta, integer_one_node, + tf_warning_or_error); + delta = cp_build_binary_op (RSHIFT_EXPR, delta, integer_one_node, + tf_warning_or_error); break; default: @@ -2667,12 +2757,12 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) /* Next extract the vtable pointer from the object. */ vtbl = build1 (NOP_EXPR, build_pointer_type (vtbl_ptr_type_node), instance_ptr); - vtbl = build_indirect_ref (vtbl, NULL); + vtbl = cp_build_indirect_ref (vtbl, NULL, tf_warning_or_error); /* Finally, extract the function pointer from the vtable. */ e2 = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtbl), vtbl, fold_convert (sizetype, idx)); - e2 = build_indirect_ref (e2, NULL); + e2 = cp_build_indirect_ref (e2, NULL, tf_warning_or_error); TREE_CONSTANT (e2) = 1; TREE_INVARIANT (e2) = 1; @@ -2680,10 +2770,11 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) vtable entry is treated as a function pointer. */ if (TARGET_VTABLE_USES_DESCRIPTORS) e2 = build1 (NOP_EXPR, TREE_TYPE (e2), - build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1)); + cp_build_unary_op (ADDR_EXPR, e2, /*noconvert=*/1, + tf_warning_or_error)); e2 = fold_convert (TREE_TYPE (e3), e2); - e1 = build_conditional_expr (e1, e2, e3); + e1 = build_conditional_expr (e1, e2, e3, tf_warning_or_error); /* Make sure this doesn't get evaluated first inside one of the branches of the COND_EXPR. */ @@ -2696,9 +2787,16 @@ get_member_function_from_ptrfunc (tree *instance_ptrptr, tree function) return function; } +/* Used by the C-common bits. */ tree build_function_call (tree function, tree params) { + return cp_build_function_call (function, params, tf_warning_or_error); +} + +tree +cp_build_function_call (tree function, tree params, tsubst_flags_t complain) +{ tree fntype, fndecl; tree name = NULL_TREE; int is_method; @@ -2725,7 +2823,7 @@ build_function_call (tree function, tree params) fndecl = function; /* Convert anything with function type to a pointer-to-function. */ - if (pedantic && DECL_MAIN_P (function)) + if (pedantic && DECL_MAIN_P (function) && (complain & tf_error)) pedwarn ("ISO C++ forbids calling %<::main%> from within program"); /* Differs from default_conversion by not setting TREE_ADDRESSABLE @@ -2751,9 +2849,10 @@ build_function_call (tree function, tree params) if (TYPE_PTRMEMFUNC_P (fntype)) { - error ("must use %<.*%> or %<->*%> to call pointer-to-member " - "function in %<%E (...)%>", - original); + if (complain & tf_error) + error ("must use %<.*%> or %<->*%> to call pointer-to-member " + "function in %<%E (...)%>", + original); return error_mark_node; } @@ -2765,7 +2864,8 @@ build_function_call (tree function, tree params) || is_method || TREE_CODE (function) == TEMPLATE_ID_EXPR)) { - error ("%qE cannot be used as a function", original); + if (complain & tf_error) + error ("%qE cannot be used as a function", original); return error_mark_node; } @@ -2783,7 +2883,8 @@ build_function_call (tree function, tree params) /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ nargs = convert_arguments (nargs, argarray, parm_types, - params, fndecl, LOOKUP_NORMAL); + params, fndecl, LOOKUP_NORMAL, + complain); if (nargs < 0) return error_mark_node; @@ -2818,7 +2919,8 @@ build_function_call (tree function, tree params) static int convert_arguments (int nargs, tree *argarray, - tree typelist, tree values, tree fndecl, int flags) + tree typelist, tree values, tree fndecl, int flags, + tsubst_flags_t complain) { tree typetail, valtail; const char *called_thing = 0; @@ -2853,14 +2955,20 @@ convert_arguments (int nargs, tree *argarray, if (type == void_type_node) { - if (fndecl) - { - error ("too many arguments to %s %q+#D", called_thing, fndecl); - error ("at this point in file"); - } - else - error ("too many arguments to function"); - return i; + if (complain & tf_error) + { + if (fndecl) + { + error ("too many arguments to %s %q+#D", + called_thing, fndecl); + error ("at this point in file"); + } + else + error ("too many arguments to function"); + return i; + } + else + return -1; } /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. @@ -2888,18 +2996,21 @@ convert_arguments (int nargs, tree *argarray, if (!COMPLETE_TYPE_P (complete_type (type))) { - if (fndecl) - error ("parameter %P of %qD has incomplete type %qT", - i, fndecl, type); - else - error ("parameter %P has incomplete type %qT", i, type); + if (complain & tf_error) + { + if (fndecl) + error ("parameter %P of %qD has incomplete type %qT", + i, fndecl, type); + else + error ("parameter %P has incomplete type %qT", i, type); + } parmval = error_mark_node; } else { parmval = convert_for_initialization (NULL_TREE, type, val, flags, - "argument passing", fndecl, i); + "argument passing", fndecl, i, complain); parmval = convert_for_arg_passing (type, parmval); } @@ -2957,13 +3068,17 @@ convert_arguments (int nargs, tree *argarray, } else { - if (fndecl) - { - error ("too few arguments to %s %q+#D", called_thing, fndecl); - error ("at this point in file"); - } - else - error ("too few arguments to function"); + if (complain & tf_error) + { + if (fndecl) + { + error ("too few arguments to %s %q+#D", + called_thing, fndecl); + error ("at this point in file"); + } + else + error ("too few arguments to function"); + } return -1; } } @@ -2985,7 +3100,8 @@ convert_arguments (int nargs, tree *argarray, tree build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, - tree arg2, enum tree_code arg2_code, bool *overloaded_p) + tree arg2, enum tree_code arg2_code, bool *overloaded_p, + tsubst_flags_t complain) { tree orig_arg1; tree orig_arg2; @@ -3007,7 +3123,7 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, expr = build_m_component_ref (arg1, arg2); else expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE, - overloaded_p); + overloaded_p, complain); /* Check for cases such as x+y<<z which users are likely to misinterpret. But don't warn about obj << x + y, since that is a @@ -3026,6 +3142,15 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, return expr; } +/* For the c-common bits. */ +tree +build_binary_op (enum tree_code code, tree op0, tree op1, + int convert_p ATTRIBUTE_UNUSED) +{ + return cp_build_binary_op(code, op0, op1, tf_warning_or_error); +} + + /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. This function differs from `build' in several ways: @@ -3045,8 +3170,8 @@ build_x_binary_op (enum tree_code code, tree arg1, enum tree_code arg1_code, multiple inheritance, and deal with pointer to member functions. */ tree -build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, - int convert_p ATTRIBUTE_UNUSED) +cp_build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, + tsubst_flags_t complain) { tree op0, op1; enum tree_code code0, code1; @@ -3127,8 +3252,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, tree t = instantiate_type (TREE_TYPE (op1), op0, tf_none); if (t != error_mark_node) { - pedwarn ("assuming cast to type %qT from overloaded function", - TREE_TYPE (t)); + if (complain & tf_error) + pedwarn ("assuming cast to type %qT from overloaded function", + TREE_TYPE (t)); op0 = t; } } @@ -3137,8 +3263,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, tree t = instantiate_type (TREE_TYPE (op0), op1, tf_none); if (t != error_mark_node) { - pedwarn ("assuming cast to type %qT from overloaded function", - TREE_TYPE (t)); + if (complain & tf_error) + pedwarn ("assuming cast to type %qT from overloaded function", + TREE_TYPE (t)); op1 = t; } } @@ -3288,10 +3415,14 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (op1) == INTEGER_CST) { if (tree_int_cst_lt (op1, integer_zero_node)) - warning (0, "right shift count is negative"); + { + if (complain & tf_warning) + warning (0, "right shift count is negative"); + } else { - if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) + if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0 + && (complain & tf_warning)) warning (0, "right shift count >= width of type"); } } @@ -3311,9 +3442,15 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (op1) == INTEGER_CST) { if (tree_int_cst_lt (op1, integer_zero_node)) - warning (0, "left shift count is negative"); + { + if (complain & tf_warning) + warning (0, "left shift count is negative"); + } else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning (0, "left shift count >= width of type"); + { + if (complain & tf_warning) + warning (0, "left shift count >= width of type"); + } } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ @@ -3332,13 +3469,19 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (op1) == INTEGER_CST) { if (tree_int_cst_lt (op1, integer_zero_node)) - warning (0, (code == LROTATE_EXPR) - ? G_("left rotate count is negative") - : G_("right rotate count is negative")); + { + if (complain & tf_warning) + warning (0, (code == LROTATE_EXPR) + ? G_("left rotate count is negative") + : G_("right rotate count is negative")); + } else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0) - warning (0, (code == LROTATE_EXPR) - ? G_("left rotate count >= width of type") - : G_("right rotate count >= width of type")); + { + if (complain & tf_warning) + warning (0, (code == LROTATE_EXPR) + ? G_("left rotate count >= width of type") + : G_("right rotate count >= width of type")); + } } /* Convert the shift-count to an integer, regardless of size of value being shifted. */ @@ -3349,11 +3492,13 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case EQ_EXPR: case NE_EXPR: - if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1)) + if ((complain & tf_warning) + && (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))) warning (OPT_Wfloat_equal, "comparing floating point with == or != is unsafe"); - if ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1)) - || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0))) + if ((complain & tf_warning) + && ((TREE_CODE (orig_op0) == STRING_CST && !integer_zerop (op1)) + || (TREE_CODE (orig_op1) == STRING_CST && !integer_zerop (op0)))) warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); build_type = boolean_type_node; @@ -3365,14 +3510,17 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE) || (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1))) result_type = composite_pointer_type (type0, type1, op0, op1, - "comparison"); + "comparison", complain); else if ((code0 == POINTER_TYPE || TYPE_PTRMEM_P (type0)) && null_ptr_cst_p (op1)) { if (TREE_CODE (op0) == ADDR_EXPR && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0))) - warning (OPT_Waddress, "the address of %qD will never be NULL", - TREE_OPERAND (op0, 0)); + { + if (complain & tf_warning) + warning (OPT_Waddress, "the address of %qD will never be NULL", + TREE_OPERAND (op0, 0)); + } result_type = type0; } else if ((code1 == POINTER_TYPE || TYPE_PTRMEM_P (type1)) @@ -3380,19 +3528,28 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, { if (TREE_CODE (op1) == ADDR_EXPR && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0))) - warning (OPT_Waddress, "the address of %qD will never be NULL", - TREE_OPERAND (op1, 0)); + { + if (complain & tf_warning) + warning (OPT_Waddress, "the address of %qD will never be NULL", + TREE_OPERAND (op1, 0)); + } result_type = type1; } else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - pedwarn ("ISO C++ forbids comparison between pointer and integer"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids comparison between pointer and integer"); + else + return error_mark_node; } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - pedwarn ("ISO C++ forbids comparison between pointer and integer"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids comparison between pointer and integer"); + else + return error_mark_node; } else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1)) { @@ -3404,12 +3561,16 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, tree e1 = cp_build_binary_op (EQ_EXPR, pfn0, fold_convert (TREE_TYPE (pfn0), - integer_zero_node)); + integer_zero_node), + complain); tree e2 = cp_build_binary_op (BIT_AND_EXPR, delta0, - integer_one_node); - e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node); - op0 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e1, e2); + integer_one_node, + complain); + e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node, + complain); + op0 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e1, e2, + complain); op1 = cp_convert (TREE_TYPE (op0), integer_one_node); } else @@ -3420,7 +3581,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, result_type = TREE_TYPE (op0); } else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (op0)) - return cp_build_binary_op (code, op1, op0); + return cp_build_binary_op (code, op1, op0, complain); else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_P (type1)) { tree type; @@ -3434,7 +3595,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, tree delta0; tree delta1; - type = composite_pointer_type (type0, type1, op0, op1, "comparison"); + type = composite_pointer_type (type0, type1, op0, op1, "comparison", + complain); if (!same_type_p (TREE_TYPE (op0), type)) op0 = cp_convert_and_check (type, op0); @@ -3469,20 +3631,26 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, e1 = cp_build_binary_op (BIT_AND_EXPR, delta0, - integer_one_node); - e1 = cp_build_binary_op (EQ_EXPR, e1, integer_zero_node); + integer_one_node, + complain); + e1 = cp_build_binary_op (EQ_EXPR, e1, integer_zero_node, + complain); e2 = cp_build_binary_op (BIT_AND_EXPR, delta1, - integer_one_node); - e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node); - e1 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1); + integer_one_node, + complain); + e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node, + complain); + e1 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1, + complain); e2 = cp_build_binary_op (EQ_EXPR, pfn0, fold_convert (TREE_TYPE (pfn0), - integer_zero_node)); - e2 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1); - e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1); - e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2); + integer_zero_node), + complain); + e2 = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1, complain); + e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1, complain); + e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2, complain); } else { @@ -3495,18 +3663,19 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, pointer-to-member is any member with a zero PFN; the DELTA field is unspecified. */ - e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1); + e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1, complain); e2 = cp_build_binary_op (EQ_EXPR, pfn0, fold_convert (TREE_TYPE (pfn0), - integer_zero_node)); - e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2); + integer_zero_node), + complain); + e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2, complain); } e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1); - e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1); + e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1, complain); if (code == EQ_EXPR) return e; - return cp_build_binary_op (EQ_EXPR, e, integer_zero_node); + return cp_build_binary_op (EQ_EXPR, e, integer_zero_node, complain); } else { @@ -3527,7 +3696,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, shorten = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (type0, type1, op0, op1, - "comparison"); + "comparison", complain); break; case LE_EXPR: @@ -3536,7 +3705,10 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, case GT_EXPR: if (TREE_CODE (orig_op0) == STRING_CST || TREE_CODE (orig_op1) == STRING_CST) - warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); + { + if (complain & tf_warning) + warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour"); + } build_type = boolean_type_node; if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) @@ -3544,7 +3716,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) result_type = composite_pointer_type (type0, type1, op0, op1, - "comparison"); + "comparison", complain); else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) result_type = type0; @@ -3554,12 +3726,18 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - pedwarn ("ISO C++ forbids comparison between pointer and integer"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids comparison between pointer and integer"); + else + return error_mark_node; } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - pedwarn ("ISO C++ forbids comparison between pointer and integer"); + if (complain & tf_error) + pedwarn ("ISO C++ forbids comparison between pointer and integer"); + else + return error_mark_node; } break; @@ -3573,7 +3751,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, build_type = integer_type_node; if (code0 != REAL_TYPE || code1 != REAL_TYPE) { - error ("unordered comparison on non-floating point argument"); + if (complain & tf_error) + error ("unordered comparison on non-floating point argument"); return error_mark_node; } common = 1; @@ -3611,8 +3790,9 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (!result_type) { - error ("invalid operands of types %qT and %qT to binary %qO", - TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); + if (complain & tf_error) + error ("invalid operands of types %qT and %qT to binary %qO", + TREE_TYPE (orig_op0), TREE_TYPE (orig_op1), code); return error_mark_node; } @@ -3742,7 +3922,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, if (TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0)) - != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1))) + != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)) + && (complain & tf_warning)) { warning (OPT_Wsign_compare, "comparison between types %q#T and %q#T", TREE_TYPE (orig_op0), TREE_TYPE (orig_op1)); @@ -3779,7 +3960,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && int_fits_type_p (orig_op0, c_common_signed_type (result_type))))) /* OK */; - else + else if (complain & tf_warning) warning (OPT_Wsign_compare, "comparison between signed and unsigned integer expressions"); @@ -3824,7 +4005,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && bits < HOST_BITS_PER_LONG && unsignedp) { mask = (~ (HOST_WIDE_INT) 0) << bits; - if ((mask & constant) != mask) + if ((mask & constant) != mask + && (complain & tf_warning)) warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant"); } } @@ -3832,7 +4014,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && (TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (result_type)) && (TYPE_PRECISION (TREE_TYPE (primop1)) - < TYPE_PRECISION (result_type))) + < TYPE_PRECISION (result_type)) + && (complain & tf_warning)) warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned"); } } @@ -3848,7 +4031,8 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1, && code != EQ_EXPR && code != NE_EXPR) /* Or if one of OP0 or OP1 is neither a pointer nor NULL. */ || (!null_ptr_cst_p (orig_op0) && TREE_CODE (TREE_TYPE (op0)) != POINTER_TYPE) - || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE))) + || (!null_ptr_cst_p (orig_op1) && TREE_CODE (TREE_TYPE (op1)) != POINTER_TYPE)) + && (complain & tf_warning)) /* Some sort of arithmetic operation involving NULL was performed. Note that pointer-difference and pointer-addition have already been handled above, and so we don't end up here in @@ -3934,7 +4118,8 @@ pointer_diff (tree op0, tree op1, tree ptrtype) op0 = cp_build_binary_op (MINUS_EXPR, cp_convert (restype, op0), - cp_convert (restype, op1)); + cp_convert (restype, op1), + tf_warning_or_error); /* This generates an error if op1 is a pointer to an incomplete type. */ if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (op1)))) @@ -3955,7 +4140,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype) and XARG is the operand. */ tree -build_x_unary_op (enum tree_code code, tree xarg) +build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain) { tree orig_expr = xarg; tree exp; @@ -3987,7 +4172,7 @@ build_x_unary_op (enum tree_code code, tree xarg) /* Don't look for a function. */; else exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE, - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, complain); if (!exp && code == ADDR_EXPR) { /* A pointer to member-function can be formed only by saying @@ -3998,10 +4183,10 @@ build_x_unary_op (enum tree_code code, tree xarg) if (TREE_CODE (xarg) != OFFSET_REF || !TYPE_P (TREE_OPERAND (xarg, 0))) { - error ("invalid use of %qE to form a pointer-to-member-function", - xarg); - if (TREE_CODE (xarg) != OFFSET_REF) - inform (" a qualified-id is required"); + error ("invalid use of %qE to form a pointer-to-member-function", + xarg); + if (TREE_CODE (xarg) != OFFSET_REF) + inform (" a qualified-id is required"); return error_mark_node; } else @@ -4028,9 +4213,9 @@ build_x_unary_op (enum tree_code code, tree xarg) PTRMEM_OK_P (xarg) = ptrmem; } } - else if (TREE_CODE (xarg) == TARGET_EXPR) + else if (TREE_CODE (xarg) == TARGET_EXPR && (complain & tf_warning)) warning (0, "taking address of temporary"); - exp = build_unary_op (ADDR_EXPR, xarg, 0); + exp = cp_build_unary_op (ADDR_EXPR, xarg, 0, complain); } if (processing_template_decl && exp != error_mark_node) @@ -4063,7 +4248,8 @@ condition_conversion (tree expr) tree t; if (processing_template_decl) return expr; - t = perform_implicit_conversion (boolean_type_node, expr); + t = perform_implicit_conversion (boolean_type_node, expr, + tf_warning_or_error); t = fold_build_cleanup_point_expr (boolean_type_node, t); return t; } @@ -4105,7 +4291,8 @@ build_nop (tree type, tree expr) (such as from short to int). */ tree -build_unary_op (enum tree_code code, tree xarg, int noconvert) +cp_build_unary_op (enum tree_code code, tree xarg, int noconvert, + tsubst_flags_t complain) { /* No default_conversion here. It causes trouble for ADDR_EXPR. */ tree arg = xarg; @@ -4184,7 +4371,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) break; case TRUTH_NOT_EXPR: - arg = perform_implicit_conversion (boolean_type_node, arg); + arg = perform_implicit_conversion (boolean_type_node, arg, + complain); val = invert_truthvalue (arg); if (arg != error_mark_node) return val; @@ -4234,9 +4422,9 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) tree real, imag; arg = stabilize_reference (arg); - real = build_unary_op (REALPART_EXPR, arg, 1); - imag = build_unary_op (IMAGPART_EXPR, arg, 1); - real = build_unary_op (code, real, 1); + real = cp_build_unary_op (REALPART_EXPR, arg, 1, complain); + imag = cp_build_unary_op (IMAGPART_EXPR, arg, 1, complain); + real = cp_build_unary_op (code, real, 1, complain); if (real == error_mark_node || imag == error_mark_node) return error_mark_node; return build2 (COMPLEX_EXPR, TREE_TYPE (arg), @@ -4264,10 +4452,15 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) /* Report something read-only. */ if (CP_TYPE_CONST_P (TREE_TYPE (arg)) - || TREE_READONLY (arg)) - readonly_error (arg, ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? "increment" : "decrement")); + || TREE_READONLY (arg)) + { + if (complain & tf_error) + readonly_error (arg, ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? "increment" : "decrement")); + else + return error_mark_node; + } { tree inc; @@ -4281,9 +4474,14 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) /* ARM $5.2.5 last annotation says this should be forbidden. */ if (TREE_CODE (argtype) == ENUMERAL_TYPE) - pedwarn ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? G_("ISO C++ forbids incrementing an enum") - : G_("ISO C++ forbids decrementing an enum")); + { + if (complain & tf_error) + pedwarn ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) + ? G_("ISO C++ forbids incrementing an enum") + : G_("ISO C++ forbids decrementing an enum")); + else + return error_mark_node; + } /* Compute the increment. */ @@ -4292,18 +4490,29 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) tree type = complete_type (TREE_TYPE (argtype)); if (!COMPLETE_OR_VOID_TYPE_P (type)) - error (((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR)) - ? G_("cannot increment a pointer to incomplete type %qT") - : G_("cannot decrement a pointer to incomplete type %qT"), - TREE_TYPE (argtype)); + { + if (complain & tf_error) + error (((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR)) + ? G_("cannot increment a pointer to incomplete type %qT") + : G_("cannot decrement a pointer to incomplete type %qT"), + TREE_TYPE (argtype)); + else + return error_mark_node; + } else if ((pedantic || warn_pointer_arith) - && !TYPE_PTROB_P (argtype)) - pedwarn ((code == PREINCREMENT_EXPR - || code == POSTINCREMENT_EXPR) - ? G_("ISO C++ forbids incrementing a pointer of type %qT") - : G_("ISO C++ forbids decrementing a pointer of type %qT"), - argtype); + && !TYPE_PTROB_P (argtype)) + { + if (complain & tf_error) + pedwarn ((code == PREINCREMENT_EXPR + || code == POSTINCREMENT_EXPR) + ? G_("ISO C++ forbids incrementing a pointer of type %qT") + : G_("ISO C++ forbids decrementing a pointer of type %qT"), + argtype); + else + return error_mark_node; + } + inc = cxx_sizeof_nowarn (TREE_TYPE (argtype)); } else @@ -4314,7 +4523,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) /* Complain about anything else that is not a true lvalue. */ if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR) - ? lv_increment : lv_decrement))) + ? lv_increment : lv_decrement), + complain)) return error_mark_node; /* Forbid using -- on `bool'. */ @@ -4322,8 +4532,9 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) { if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR) { - error ("invalid use of Boolean expression as operand " - "to %<operator--%>"); + if (complain & tf_error) + error ("invalid use of Boolean expression as operand " + "to %<operator--%>"); return error_mark_node; } val = boolean_increment (code, arg); @@ -4351,8 +4562,13 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) return arg; } else if (pedantic && DECL_MAIN_P (arg)) - /* ARM $3.4 */ - pedwarn ("ISO C++ forbids taking address of function %<::main%>"); + { + /* ARM $3.4 */ + if (complain & tf_error) + pedwarn ("ISO C++ forbids taking address of function %<::main%>"); + else + return error_mark_node; + } /* Let &* cancel out to simplify resulting code. */ if (TREE_CODE (arg) == INDIRECT_REF) @@ -4405,13 +4621,15 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) if (! flag_ms_extensions) { tree name = DECL_NAME (fn); - if (current_class_type - && TREE_OPERAND (arg, 0) == current_class_ref) - /* An expression like &memfn. */ - pedwarn ("ISO C++ forbids taking the address of an unqualified" - " or parenthesized non-static member function to form" - " a pointer to member function. Say %<&%T::%D%>", - base, name); + if (!(complain & tf_error)) + return error_mark_node; + else if (current_class_type + && TREE_OPERAND (arg, 0) == current_class_ref) + /* An expression like &memfn. */ + pedwarn ("ISO C++ forbids taking the address of an unqualified" + " or parenthesized non-static member function to form" + " a pointer to member function. Say %<&%T::%D%>", + base, name); else pedwarn ("ISO C++ forbids taking the address of a bound member" " function to form a pointer to member function." @@ -4437,8 +4655,16 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) case CONVERT_EXPR: case FLOAT_EXPR: case FIX_TRUNC_EXPR: - if (! lvalue_p (arg) && pedantic) - pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression"); + /* Even if we're not being pedantic, we cannot allow this + extension when we're instantiating in a SFINAE + context. */ + if (! lvalue_p (arg) && (pedantic || complain == tf_none)) + { + if (complain & tf_error) + pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression"); + else + return error_mark_node; + } break; case BASELINK: @@ -4457,12 +4683,13 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) tree t; if (!PTRMEM_OK_P (arg)) - return build_unary_op (code, arg, 0); + return cp_build_unary_op (code, arg, 0, complain); t = TREE_OPERAND (arg, 1); if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) { - error ("cannot create pointer to reference member %qD", t); + if (complain & tf_error) + error ("cannot create pointer to reference member %qD", t); return error_mark_node; } @@ -4481,7 +4708,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) if (TREE_CODE (argtype) != FUNCTION_TYPE && TREE_CODE (argtype) != METHOD_TYPE && TREE_CODE (arg) != OFFSET_REF - && !lvalue_or_else (arg, lv_addressof)) + && !lvalue_or_else (arg, lv_addressof, complain)) return error_mark_node; if (argtype != error_mark_node) @@ -4520,8 +4747,9 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) } else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) { - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); + if (complain & tf_error) + error ("attempt to take address of bit-field structure member %qD", + TREE_OPERAND (arg, 1)); return error_mark_node; } else @@ -4554,10 +4782,18 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) return fold_if_not_in_template (build1 (code, argtype, arg)); } - error ("%s", errstring); + if (complain & tf_error) + error ("%s", errstring); return error_mark_node; } +/* Hook for the c-common bits that build a unary op. */ +tree +build_unary_op (enum tree_code code, tree xarg, int noconvert) +{ + return cp_build_unary_op (code, xarg, noconvert, tf_warning_or_error); +} + /* Apply unary lvalue-demanding operator CODE to the expression ARG for certain kinds of expressions which are not really lvalues but which we can accept as lvalues. @@ -4577,7 +4813,8 @@ unary_complex_lvalue (enum tree_code code, tree arg) /* Handle (a, b) used as an "lvalue". */ if (TREE_CODE (arg) == COMPOUND_EXPR) { - tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0); + tree real_result = cp_build_unary_op (code, TREE_OPERAND (arg, 1), 0, + tf_warning_or_error); return build2 (COMPOUND_EXPR, TREE_TYPE (real_result), TREE_OPERAND (arg, 0), real_result); } @@ -4585,7 +4822,7 @@ unary_complex_lvalue (enum tree_code code, tree arg) /* Handle (a ? b : c) used as an "lvalue". */ if (TREE_CODE (arg) == COND_EXPR || TREE_CODE (arg) == MIN_EXPR || TREE_CODE (arg) == MAX_EXPR) - return rationalize_conditional_expr (code, arg); + return rationalize_conditional_expr (code, arg, tf_warning_or_error); /* Handle (a = b), (++a), and (--a) used as an "lvalue". */ if (TREE_CODE (arg) == MODIFY_EXPR @@ -4610,7 +4847,8 @@ unary_complex_lvalue (enum tree_code code, tree arg) if (TREE_CODE (arg) == MODIFY_EXPR || TREE_CODE (arg) == INIT_EXPR) { - tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0); + tree real_result = cp_build_unary_op (code, TREE_OPERAND (arg, 0), 0, + tf_warning_or_error); arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); TREE_NO_WARNING (arg) = 1; @@ -4727,7 +4965,8 @@ cxx_mark_addressable (tree exp) /* Build and return a conditional expression IFEXP ? OP1 : OP2. */ tree -build_x_conditional_expr (tree ifexp, tree op1, tree op2) +build_x_conditional_expr (tree ifexp, tree op1, tree op2, + tsubst_flags_t complain) { tree orig_ifexp = ifexp; tree orig_op1 = op1; @@ -4750,7 +4989,7 @@ build_x_conditional_expr (tree ifexp, tree op1, tree op2) op2 = build_non_dependent_expr (op2); } - expr = build_conditional_expr (ifexp, op1, op2); + expr = build_conditional_expr (ifexp, op1, op2, complain); if (processing_template_decl && expr != error_mark_node) return build_min_non_dep (COND_EXPR, expr, orig_ifexp, orig_op1, orig_op2); @@ -4770,7 +5009,8 @@ tree build_x_compound_expr_from_list (tree list, const char *msg) pedwarn ("%s expression list treated as compound expression", msg); for (list = TREE_CHAIN (list); list; list = TREE_CHAIN (list)) - expr = build_x_compound_expr (expr, TREE_VALUE (list)); + expr = build_x_compound_expr (expr, TREE_VALUE (list), + tf_warning_or_error); } return expr; @@ -4779,7 +5019,7 @@ tree build_x_compound_expr_from_list (tree list, const char *msg) /* Handle overloading of the ',' operator when needed. */ tree -build_x_compound_expr (tree op1, tree op2) +build_x_compound_expr (tree op1, tree op2, tsubst_flags_t complain) { tree result; tree orig_op1 = op1; @@ -4795,9 +5035,9 @@ build_x_compound_expr (tree op1, tree op2) } result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE, - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, complain); if (!result) - result = build_compound_expr (op1, op2); + result = build_compound_expr (op1, op2, complain); if (processing_template_decl && result != error_mark_node) return build_min_non_dep (COMPOUND_EXPR, result, orig_op1, orig_op2); @@ -4808,9 +5048,9 @@ build_x_compound_expr (tree op1, tree op2) /* Build a compound expression. */ tree -build_compound_expr (tree lhs, tree rhs) +build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain) { - lhs = convert_to_void (lhs, "left-hand operand of comma"); + lhs = convert_to_void (lhs, "left-hand operand of comma", complain); if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; @@ -4893,9 +5133,11 @@ convert_ptrmem (tree type, tree expr, bool allow_inverse_p, cond = cp_build_binary_op (EQ_EXPR, expr, - build_int_cst (TREE_TYPE (expr), -1)); + build_int_cst (TREE_TYPE (expr), -1), + tf_warning_or_error); op1 = build_nop (ptrdiff_type_node, expr); - op2 = cp_build_binary_op (PLUS_EXPR, op1, delta); + op2 = cp_build_binary_op (PLUS_EXPR, op1, delta, + tf_warning_or_error); expr = fold_build3 (COND_EXPR, ptrdiff_type_node, cond, op1, op2); @@ -4944,7 +5186,7 @@ ignore_overflows (tree expr, tree orig) static tree build_static_cast_1 (tree type, tree expr, bool c_cast_p, - bool *valid_p) + bool *valid_p, tsubst_flags_t complain) { tree intype; tree result; @@ -5018,7 +5260,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, t(e);" is well-formed, for some invented temporary variable t. */ result = perform_direct_initialization_if_possible (type, expr, - c_cast_p); + c_cast_p, complain); if (result) { result = convert_from_reference (result); @@ -5039,7 +5281,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, Any expression can be explicitly converted to type cv void. */ if (TREE_CODE (type) == VOID_TYPE) - return convert_to_void (expr, /*implicit=*/NULL); + return convert_to_void (expr, /*implicit=*/NULL, complain); /* [expr.static.cast] @@ -5145,7 +5387,7 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p, /* Return an expression representing static_cast<TYPE>(EXPR). */ tree -build_static_cast (tree type, tree expr) +build_static_cast (tree type, tree expr, tsubst_flags_t complain) { tree result; bool valid_p; @@ -5168,12 +5410,14 @@ build_static_cast (tree type, tree expr) && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) expr = TREE_OPERAND (expr, 0); - result = build_static_cast_1 (type, expr, /*c_cast_p=*/false, &valid_p); + result = build_static_cast_1 (type, expr, /*c_cast_p=*/false, &valid_p, + complain); if (valid_p) return result; - error ("invalid static_cast from type %qT to type %qT", - TREE_TYPE (expr), type); + if (complain & tf_error) + error ("invalid static_cast from type %qT to type %qT", + TREE_TYPE (expr), type); return error_mark_node; } @@ -5217,7 +5461,7 @@ convert_member_func_to_ptr (tree type, tree expr) static tree build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, - bool *valid_p) + bool *valid_p, tsubst_flags_t complain) { tree intype; @@ -5242,9 +5486,10 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, { if (! real_lvalue_p (expr)) { - error ("invalid cast of an rvalue expression of type " - "%qT to type %qT", - intype, type); + if (complain & tf_error) + error ("invalid cast of an rvalue expression of type " + "%qT to type %qT", + intype, type); return error_mark_node; } @@ -5252,18 +5497,19 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, "B" are related class types; the reinterpret_cast does not adjust the pointer. */ if (TYPE_PTR_P (intype) + && (complain & tf_warning) && (comptypes (TREE_TYPE (intype), TREE_TYPE (type), COMPARE_BASE | COMPARE_DERIVED))) warning (0, "casting %qT to %qT does not dereference pointer", intype, type); - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = cp_build_unary_op (ADDR_EXPR, expr, 0, complain); if (expr != error_mark_node) expr = build_reinterpret_cast_1 (build_pointer_type (TREE_TYPE (type)), expr, c_cast_p, - valid_p); + valid_p, complain); if (expr != error_mark_node) - expr = build_indirect_ref (expr, 0); + expr = cp_build_indirect_ref (expr, 0, complain); return expr; } @@ -5301,8 +5547,13 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, if (CP_INTEGRAL_TYPE_P (type) && TYPE_PTR_P (intype)) { if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) - pedwarn ("cast from %qT to %qT loses precision", - intype, type); + { + if (complain & tf_error) + pedwarn ("cast from %qT to %qT loses precision", + intype, type); + else + return error_mark_node; + } } /* [expr.reinterpret.cast] A value of integral or enumeration type can be explicitly @@ -5322,6 +5573,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, check_for_casting_away_constness (intype, type, REINTERPRET_CAST_EXPR); /* Warn about possible alignment problems. */ if (STRICT_ALIGNMENT && warn_cast_align + && (complain & tf_warning) && !VOID_TYPE_P (type) && TREE_CODE (TREE_TYPE (intype)) != FUNCTION_TYPE && COMPLETE_TYPE_P (TREE_TYPE (type)) @@ -5341,7 +5593,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype)) || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type))) { - if (pedantic) + if (pedantic && (complain & tf_warning)) /* Only issue a warning, as we have always supported this where possible, and it is necessary in some cases. DR 195 addresses this issue, but as of 2004/10/26 is still in @@ -5357,7 +5609,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, { if (valid_p) *valid_p = false; - error ("invalid cast from type %qT to type %qT", intype, type); + if (complain & tf_error) + error ("invalid cast from type %qT to type %qT", intype, type); return error_mark_node; } @@ -5365,7 +5618,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p, } tree -build_reinterpret_cast (tree type, tree expr) +build_reinterpret_cast (tree type, tree expr, tsubst_flags_t complain) { if (type == error_mark_node || expr == error_mark_node) return error_mark_node; @@ -5382,7 +5635,7 @@ build_reinterpret_cast (tree type, tree expr) } return build_reinterpret_cast_1 (type, expr, /*c_cast_p=*/false, - /*valid_p=*/NULL); + /*valid_p=*/NULL, complain); } /* Perform a const_cast from EXPR to TYPE. If the cast is valid, @@ -5477,7 +5730,8 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, } if (reference_type) { - expr = build_unary_op (ADDR_EXPR, expr, 0); + expr = cp_build_unary_op (ADDR_EXPR, expr, 0, + complain? tf_warning_or_error : tf_none); expr = build_nop (reference_type, expr); return convert_from_reference (expr); } @@ -5501,7 +5755,7 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain, } tree -build_const_cast (tree type, tree expr) +build_const_cast (tree type, tree expr, tsubst_flags_t complain) { if (type == error_mark_node || error_operand_p (expr)) return error_mark_node; @@ -5517,7 +5771,7 @@ build_const_cast (tree type, tree expr) return convert_from_reference (t); } - return build_const_cast_1 (type, expr, /*complain=*/true, + return build_const_cast_1 (type, expr, complain & tf_error, /*valid_p=*/NULL); } @@ -5525,7 +5779,7 @@ build_const_cast (tree type, tree expr) TYPE of expression EXPR. */ tree -build_c_cast (tree type, tree expr) +build_c_cast (tree type, tree expr, tsubst_flags_t complain) { tree value = expr; tree result; @@ -5563,12 +5817,16 @@ build_c_cast (tree type, tree expr) NIHCL uses it. It is not valid ISO C++ however. */ if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE) { - pedwarn ("ISO C++ forbids casting to an array type %qT", type); + if (complain & tf_error) + pedwarn ("ISO C++ forbids casting to an array type %qT", type); + else + return error_mark_node; type = build_pointer_type (TREE_TYPE (type)); } else { - error ("ISO C++ forbids casting to an array type %qT", type); + if (complain & tf_error) + error ("ISO C++ forbids casting to an array type %qT", type); return error_mark_node; } } @@ -5576,7 +5834,8 @@ build_c_cast (tree type, tree expr) if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) { - error ("invalid cast to function type %qT", type); + if (complain & tf_error) + error ("invalid cast to function type %qT", type); return error_mark_node; } @@ -5588,11 +5847,11 @@ build_c_cast (tree type, tree expr) /* Or a static cast. */ result = build_static_cast_1 (type, value, /*c_cast_p=*/true, - &valid_p); + &valid_p, complain); /* Or a reinterpret_cast. */ if (!valid_p) result = build_reinterpret_cast_1 (type, value, /*c_cast_p=*/true, - &valid_p); + &valid_p, complain); /* The static_cast or reinterpret_cast may be followed by a const_cast. */ if (valid_p @@ -5624,6 +5883,13 @@ build_c_cast (tree type, tree expr) return error_mark_node; } +/* For use from the C common bits. */ +tree +build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +{ + return cp_build_modify_expr (lhs, modifycode, rhs, tf_warning_or_error); +} + /* Build an assignment expression of lvalue LHS from value RHS. MODIFYCODE is the code for a binary operator that we use to combine the old value of LHS with RHS to get the new value. @@ -5632,7 +5898,8 @@ build_c_cast (tree type, tree expr) C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. */ tree -build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, + tsubst_flags_t complain) { tree result; tree newrhs = rhs; @@ -5657,13 +5924,13 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) TREE_OPERAND (lhs, 1)); return build2 (COMPOUND_EXPR, lhstype, lhs, - build_modify_expr (TREE_OPERAND (lhs, 0), - modifycode, rhs)); + cp_build_modify_expr (TREE_OPERAND (lhs, 0), + modifycode, rhs, complain)); /* Handle (a, b) used as an "lvalue". */ case COMPOUND_EXPR: - newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), - modifycode, rhs); + newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 1), + modifycode, rhs, complain); if (newrhs == error_mark_node) return error_mark_node; return build2 (COMPOUND_EXPR, lhstype, @@ -5674,7 +5941,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs), stabilize_reference (TREE_OPERAND (lhs, 0)), TREE_OPERAND (lhs, 1)); - newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); + newrhs = cp_build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs, + complain); if (newrhs == error_mark_node) return error_mark_node; return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs); @@ -5683,7 +5951,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) case MAX_EXPR: /* MIN_EXPR and MAX_EXPR are currently only permitted as lvalues, when neither operand has side-effects. */ - if (!lvalue_or_else (lhs, lv_assign)) + if (!lvalue_or_else (lhs, lv_assign, complain)) return error_mark_node; gcc_assert (!TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0)) @@ -5709,7 +5977,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (VOID_TYPE_P (TREE_TYPE (rhs))) { - error ("void value not ignored as it ought to be"); + if (complain & tf_error) + error ("void value not ignored as it ought to be"); return error_mark_node; } @@ -5717,15 +5986,16 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) /* Check this here to avoid odd errors when trying to convert a throw to the type of the COND_EXPR. */ - if (!lvalue_or_else (lhs, lv_assign)) + if (!lvalue_or_else (lhs, lv_assign, complain)) return error_mark_node; cond = build_conditional_expr (TREE_OPERAND (lhs, 0), - build_modify_expr (TREE_OPERAND (lhs, 1), - modifycode, rhs), - build_modify_expr (TREE_OPERAND (lhs, 2), - modifycode, rhs)); + cp_build_modify_expr (TREE_OPERAND (lhs, 1), + modifycode, rhs, complain), + cp_build_modify_expr (TREE_OPERAND (lhs, 2), + modifycode, rhs, complain), + complain); if (cond == error_mark_node) return cond; @@ -5757,7 +6027,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { result = build_special_member_call (lhs, complete_ctor_identifier, build_tree_list (NULL_TREE, rhs), - lhstype, LOOKUP_NORMAL); + lhstype, LOOKUP_NORMAL, + complain); if (result == NULL_TREE) return error_mark_node; return result; @@ -5778,7 +6049,8 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, make_node (NOP_EXPR), - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, + complain); if (result == NULL_TREE) return error_mark_node; return result; @@ -5795,11 +6067,13 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) || MAYBE_CLASS_TYPE_P (lhstype))); lhs = stabilize_reference (lhs); - newrhs = cp_build_binary_op (modifycode, lhs, rhs); + newrhs = cp_build_binary_op (modifycode, lhs, rhs, + complain); if (newrhs == error_mark_node) { - error (" in evaluation of %<%Q(%#T, %#T)%>", modifycode, - TREE_TYPE (lhs), TREE_TYPE (rhs)); + if (complain & tf_error) + error (" in evaluation of %<%Q(%#T, %#T)%>", modifycode, + TREE_TYPE (lhs), TREE_TYPE (rhs)); return error_mark_node; } @@ -5811,7 +6085,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) } /* The left-hand side must be an lvalue. */ - if (!lvalue_or_else (lhs, lv_assign)) + if (!lvalue_or_else (lhs, lv_assign, complain)) return error_mark_node; /* Warn about modifying something that is `const'. Don't warn if @@ -5826,7 +6100,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) effectively const. */ || (CLASS_TYPE_P (lhstype) && C_TYPE_FIELDS_READONLY (lhstype)))) - readonly_error (lhs, "assignment"); + { + if (complain & tf_error) + readonly_error (lhs, "assignment"); + else + return error_mark_node; + } /* If storing into a structure or union member, it has probably been given type `int'. Compute the type that would go with the actual @@ -5867,8 +6146,9 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) if (!same_or_base_type_p (TYPE_MAIN_VARIANT (lhstype), TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))) { - error ("incompatible types in assignment of %qT to %qT", - TREE_TYPE (rhs), lhstype); + if (complain & tf_error) + error ("incompatible types in assignment of %qT to %qT", + TREE_TYPE (rhs), lhstype); return error_mark_node; } @@ -5877,10 +6157,13 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { /* This routine is used for both initialization and assignment. Make sure the diagnostic message differentiates the context. */ - if (modifycode == INIT_EXPR) - error ("array used as initializer"); - else - error ("invalid array assignment"); + if (complain & tf_error) + { + if (modifycode == INIT_EXPR) + error ("array used as initializer"); + else + error ("invalid array assignment"); + } return error_mark_node; } @@ -5888,12 +6171,13 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ? 1 + (modifycode != INIT_EXPR): 0; return build_vec_init (lhs, NULL_TREE, newrhs, /*explicit_default_init_p=*/false, - from_array); + from_array, complain); } if (modifycode == INIT_EXPR) newrhs = convert_for_initialization (lhs, lhstype, newrhs, LOOKUP_NORMAL, - "initialization", NULL_TREE, 0); + "initialization", NULL_TREE, 0, + complain); else { /* Avoid warnings on enum bit fields. */ @@ -5901,12 +6185,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) && TREE_CODE (lhstype) == INTEGER_TYPE) { newrhs = convert_for_assignment (olhstype, newrhs, "assignment", - NULL_TREE, 0); + NULL_TREE, 0, complain); newrhs = convert_force (lhstype, newrhs, 0); } else newrhs = convert_for_assignment (lhstype, newrhs, "assignment", - NULL_TREE, 0); + NULL_TREE, 0, complain); if (TREE_CODE (newrhs) == CALL_EXPR && TYPE_NEEDS_CONSTRUCTING (lhstype)) newrhs = build_cplus_new (lhstype, newrhs); @@ -5952,11 +6236,12 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) return result; } return convert_for_assignment (olhstype, result, "assignment", - NULL_TREE, 0); + NULL_TREE, 0, complain); } tree -build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) +build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs, + tsubst_flags_t complain) { if (processing_template_decl) return build_min_nt (MODOP_EXPR, lhs, @@ -5966,14 +6251,15 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) { tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, make_node (modifycode), - /*overloaded_p=*/NULL); + /*overloaded_p=*/NULL, + complain); if (rval) { TREE_NO_WARNING (rval) = 1; return rval; } } - return build_modify_expr (lhs, modifycode, rhs); + return cp_build_modify_expr (lhs, modifycode, rhs, complain); } /* Helper function for get_delta_difference which assumes FROM is a base @@ -6151,7 +6437,8 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) if (same_type_p (to_type, pfn_type)) return pfn; else if (integer_zerop (n)) - return build_reinterpret_cast (to_type, pfn); + return build_reinterpret_cast (to_type, pfn, + tf_warning_or_error); } if (TREE_SIDE_EFFECTS (pfn)) @@ -6170,15 +6457,16 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p) gcc_assert (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (delta), ptrdiff_type_node)); if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta) - n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node); - delta = cp_build_binary_op (PLUS_EXPR, delta, n); + n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node, + tf_warning_or_error); + delta = cp_build_binary_op (PLUS_EXPR, delta, n, tf_warning_or_error); return build_ptrmemfunc1 (to_type, delta, npfn); } /* Handle null pointer to member function conversions. */ if (integer_zerop (pfn)) { - pfn = build_c_cast (type, integer_zero_node); + pfn = build_c_cast (type, integer_zero_node, tf_warning_or_error); return build_ptrmemfunc1 (to_type, integer_zero_node, pfn); @@ -6314,7 +6602,8 @@ delta_from_ptrmemfunc (tree t) static tree convert_for_assignment (tree type, tree rhs, - const char *errtype, tree fndecl, int parmnum) + const char *errtype, tree fndecl, int parmnum, + tsubst_flags_t complain) { tree rhstype; enum tree_code coder; @@ -6338,7 +6627,8 @@ convert_for_assignment (tree type, tree rhs, /* The RHS of an assignment cannot have void type. */ if (coder == VOID_TYPE) { - error ("void value not ignored as it ought to be"); + if (complain & tf_error) + error ("void value not ignored as it ought to be"); return error_mark_node; } @@ -6391,16 +6681,20 @@ convert_for_assignment (tree type, tree rhs, rhs = cp_convert (strip_top_quals (type), rhs); else { - /* If the right-hand side has unknown type, then it is an - overloaded function. Call instantiate_type to get error - messages. */ - if (rhstype == unknown_type_node) - instantiate_type (type, rhs, tf_warning_or_error); - else if (fndecl) - error ("cannot convert %qT to %qT for argument %qP to %qD", - rhstype, type, parmnum, fndecl); - else - error ("cannot convert %qT to %qT in %s", rhstype, type, errtype); + if (complain & tf_error) + { + /* If the right-hand side has unknown type, then it is an + overloaded function. Call instantiate_type to get error + messages. */ + if (rhstype == unknown_type_node) + instantiate_type (type, rhs, tf_warning_or_error); + else if (fndecl) + error ("cannot convert %qT to %qT for argument %qP to %qD", + rhstype, type, parmnum, fndecl); + else + error ("cannot convert %qT to %qT in %s", rhstype, type, + errtype); + } return error_mark_node; } } @@ -6409,7 +6703,8 @@ convert_for_assignment (tree type, tree rhs, const enum tree_code codel = TREE_CODE (type); if ((codel == POINTER_TYPE || codel == REFERENCE_TYPE) && coder == codel - && check_missing_format_attribute (type, rhstype)) + && check_missing_format_attribute (type, rhstype) + && (complain & tf_warning)) warning (OPT_Wmissing_format_attribute, "%s might be a candidate for a format attribute", errtype); @@ -6421,14 +6716,15 @@ convert_for_assignment (tree type, tree rhs, && type == boolean_type_node && TREE_CODE (rhs) == MODIFY_EXPR && !TREE_NO_WARNING (rhs) - && TREE_TYPE (rhs) != boolean_type_node) + && TREE_TYPE (rhs) != boolean_type_node + && (complain & tf_warning)) { warning (OPT_Wparentheses, "suggest parentheses around assignment used as truth value"); TREE_NO_WARNING (rhs) = 1; } - return perform_implicit_conversion (strip_top_quals (type), rhs); + return perform_implicit_conversion (strip_top_quals (type), rhs, complain); } /* Convert RHS to be of type TYPE. @@ -6449,7 +6745,8 @@ convert_for_assignment (tree type, tree rhs, tree convert_for_initialization (tree exp, tree type, tree rhs, int flags, - const char *errtype, tree fndecl, int parmnum) + const char *errtype, tree fndecl, int parmnum, + tsubst_flags_t complain) { enum tree_code codel = TREE_CODE (type); tree rhstype; @@ -6517,7 +6814,8 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, if (MAYBE_CLASS_TYPE_P (type)) return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); - return convert_for_assignment (type, rhs, errtype, fndecl, parmnum); + return convert_for_assignment (type, rhs, errtype, fndecl, parmnum, + complain); } /* If RETVAL is the address of, or a reference to, a local variable or @@ -6810,7 +7108,8 @@ check_return_expr (tree retval, bool *no_warning) to the type of return value's location to handle the case that functype is smaller than the valtype. */ retval = convert_for_initialization - (NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0); + (NULL_TREE, functype, retval, flags, "return", NULL_TREE, 0, + tf_warning_or_error); retval = convert (valtype, retval); /* If the conversion failed, treat this just like `return;'. */ @@ -7174,11 +7473,11 @@ non_reference (tree t) how the lvalue is being used and so selects the error message. */ int -lvalue_or_else (const_tree ref, enum lvalue_use use) +lvalue_or_else (const_tree ref, enum lvalue_use use, tsubst_flags_t complain) { int win = lvalue_p (ref); - if (!win) + if (!win && (complain & tf_error)) lvalue_error (use); return win; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index c48a785..4fdb07f 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -707,7 +707,8 @@ digest_init (tree type, tree init) tree *exp; init = convert_for_initialization (0, type, init, LOOKUP_NORMAL, - "initialization", NULL_TREE, 0); + "initialization", NULL_TREE, 0, + tf_warning_or_error); exp = &init; /* Skip any conversions since we'll be outputting the underlying @@ -751,7 +752,8 @@ digest_init (tree type, tree init) return convert_for_initialization (NULL_TREE, type, init, LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING, - "initialization", NULL_TREE, 0); + "initialization", NULL_TREE, 0, + tf_warning_or_error); } } @@ -849,7 +851,8 @@ process_init_constructor_array (tree type, tree init) TARGET_EXPRs. If the type in question is a class, just build one up; if it's an array, recurse. */ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (type))) - next = build_functional_cast (TREE_TYPE (type), NULL_TREE); + next = build_functional_cast (TREE_TYPE (type), NULL_TREE, + tf_warning_or_error); else next = build_constructor (NULL_TREE, NULL); next = digest_init (TREE_TYPE (type), next); @@ -936,7 +939,8 @@ process_init_constructor_record (tree type, tree init) for us, so build up TARGET_EXPRs. If the type in question is a class, just build one up; if it's an array, recurse. */ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (field))) - next = build_functional_cast (TREE_TYPE (field), NULL_TREE); + next = build_functional_cast (TREE_TYPE (field), NULL_TREE, + tf_warning_or_error); else next = build_constructor (NULL_TREE, NULL); @@ -1165,7 +1169,8 @@ build_x_arrow (tree expr) { while ((expr = build_new_op (COMPONENT_REF, LOOKUP_NORMAL, expr, NULL_TREE, NULL_TREE, - /*overloaded_p=*/NULL))) + /*overloaded_p=*/NULL, + tf_warning_or_error))) { if (expr == error_mark_node) return error_mark_node; @@ -1205,7 +1210,7 @@ build_x_arrow (tree expr) return expr; } - return build_indirect_ref (last_rval, NULL); + return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error); } if (types_memoized) @@ -1297,7 +1302,7 @@ build_m_component_ref (tree datum, tree component) datum = build2 (POINTER_PLUS_EXPR, ptype, fold_convert (ptype, datum), build_nop (sizetype, component)); - return build_indirect_ref (datum, 0); + return cp_build_indirect_ref (datum, 0, tf_warning_or_error); } else return build2 (OFFSET_REF, type, datum, component); @@ -1306,7 +1311,7 @@ build_m_component_ref (tree datum, tree component) /* Return a tree node for the expression TYPENAME '(' PARMS ')'. */ tree -build_functional_cast (tree exp, tree parms) +build_functional_cast (tree exp, tree parms, tsubst_flags_t complain) { /* This is either a call to a constructor, or a C cast in C++'s `functional' notation. */ @@ -1337,7 +1342,7 @@ build_functional_cast (tree exp, tree parms) /* This must build a C cast. */ parms = build_x_compound_expr_from_list (parms, "functional cast"); - return build_c_cast (type, parms); + return build_c_cast (type, parms, complain); } /* Prepare to evaluate as a call to a constructor. If this expression @@ -1358,7 +1363,7 @@ build_functional_cast (tree exp, tree parms) conversion is equivalent (in definedness, and if defined in meaning) to the corresponding cast expression. */ if (parms && TREE_CHAIN (parms) == NULL_TREE) - return build_c_cast (type, TREE_VALUE (parms)); + return build_c_cast (type, TREE_VALUE (parms), complain); /* [expr.type.conv] @@ -1378,7 +1383,7 @@ build_functional_cast (tree exp, tree parms) /* Call the constructor. */ exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms, - type, LOOKUP_NORMAL); + type, LOOKUP_NORMAL, complain); if (exp == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 05e9c26..4adfe1d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2008-03-25 Douglas Gregor <doug.gregor@gmail.com> + + * g++.dg/template/sfinae4.C: New. + * g++.dg/template/sfinae5.C: New. + * g++.dg/template/sfinae6.C: New. + * g++.dg/template/sfinae6_neg.C: New. + * g++.dg/template/sfinae7.C: New. + * g++.dg/template/sfinae8.C: New. + * g++.dg/template/sfinae9.C: New. + * g++.dg/template/sfinae10.C: New. + * g++.dg/template/sfinae11.C: New. + * g++.dg/template/sfinae12.C: New. + * g++.dg/template/sfinae13.C: New. + * g++.dg/template/sfinae14C: New. + 2008-03-25 Naveen.H.S <naveen.hs@kpitcummins.com> * gcc.target/sh/sh2a-bclr.c: New test. diff --git a/gcc/testsuite/g++.dg/template/sfinae10.C b/gcc/testsuite/g++.dg/template/sfinae10.C new file mode 100644 index 0000000..e0680db --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae10.C @@ -0,0 +1,181 @@ +// DR 339 +// +// Test of the use of various unary operators with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#define DEFINE_PREFIX_UNARY_TRAIT(Name,Op) \ +template<typename T> \ + typename enable_if<(sizeof(Op create_a<T>(), 1) > 0), \ + yes_type>::type \ + JOIN(check_,Name)(int); \ + \ +template<typename T> \ + no_type JOIN(check_,Name)(...); \ + \ +template<typename T> \ +struct Name \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,Name)<T&>(0)) == sizeof(yes_type)); \ +} + +#define DEFINE_POSTFIX_UNARY_TRAIT(Name,Op) \ +template<typename T> \ + typename enable_if<(sizeof(create_a<T>() Op, 1) > 0), \ + yes_type>::type \ + JOIN(check_,Name)(int); \ + \ +template<typename T> \ + no_type JOIN(check_,Name)(...); \ + \ +template<typename T> \ +struct Name \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,Name)<T&>(0)) == sizeof(yes_type)); \ +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct W { + W operator+(); + W operator-(); + int operator*(); + W operator~(); + bool operator!(); + W& operator++(); + W& operator--(); + W& operator++(int); + W& operator--(int); +}; + +struct X { }; +X operator+(X); +X operator-(X); +int operator*(X); +X operator~(X); +bool operator!(X); +X& operator++(X&); +X& operator--(X&); +X& operator++(X&, int); +X& operator--(X&, int); + +struct Y { }; + +struct Z { +private: + Z operator+(); // { dg-error "is private" } + Z operator-(); // { dg-error "is private" } + int operator*(); // { dg-error "is private" } + Z operator~(); // { dg-error "is private" } + bool operator!(); // { dg-error "is private" } + Z& operator++(); // { dg-error "is private" } + Z& operator--(); // { dg-error "is private" } + Z& operator++(int); // { dg-error "is private" } + Z& operator--(int); // { dg-error "is private" } +}; + +// has_unary_plus +DEFINE_PREFIX_UNARY_TRAIT(has_unary_plus, +); // { dg-error "within this context" } +STATIC_ASSERT((has_unary_plus<int>::value)); +STATIC_ASSERT((!has_unary_plus<int X::*>::value)); +STATIC_ASSERT((has_unary_plus<W>::value)); +STATIC_ASSERT((has_unary_plus<X>::value)); +STATIC_ASSERT((!has_unary_plus<Y>::value)); + +// is_negatable +DEFINE_PREFIX_UNARY_TRAIT(is_negatable, -); // { dg-error "within this context" } +STATIC_ASSERT((is_negatable<int>::value)); +STATIC_ASSERT((!is_negatable<int X::*>::value)); +STATIC_ASSERT((is_negatable<W>::value)); +STATIC_ASSERT((is_negatable<X>::value)); +STATIC_ASSERT((!is_negatable<Y>::value)); + +// is_dereferenceable +DEFINE_PREFIX_UNARY_TRAIT(is_dereferenceable, *); // { dg-error "within this context" } +STATIC_ASSERT((!is_dereferenceable<int>::value)); +STATIC_ASSERT((is_dereferenceable<int*>::value)); +STATIC_ASSERT((is_dereferenceable<W>::value)); +STATIC_ASSERT((is_dereferenceable<X>::value)); +STATIC_ASSERT((!is_dereferenceable<Y>::value)); + +// has_bitwise_not +DEFINE_PREFIX_UNARY_TRAIT(has_bitwise_not, ~); // { dg-error "within this context" } +STATIC_ASSERT((has_bitwise_not<int>::value)); +STATIC_ASSERT((!has_bitwise_not<int*>::value)); +STATIC_ASSERT((has_bitwise_not<W>::value)); +STATIC_ASSERT((has_bitwise_not<X>::value)); +STATIC_ASSERT((!has_bitwise_not<Y>::value)); + +// has_truth_not +DEFINE_PREFIX_UNARY_TRAIT(has_truth_not, !); // { dg-error "within this context" } +STATIC_ASSERT((has_truth_not<int>::value)); +STATIC_ASSERT((has_truth_not<int*>::value)); +STATIC_ASSERT((has_truth_not<W>::value)); +STATIC_ASSERT((has_truth_not<X>::value)); +STATIC_ASSERT((!has_truth_not<Y>::value)); + +// has_preincrement +DEFINE_PREFIX_UNARY_TRAIT(has_preincrement, ++); // { dg-error "within this context" } +STATIC_ASSERT((has_preincrement<int>::value)); +STATIC_ASSERT((has_preincrement<int*>::value)); +STATIC_ASSERT((!has_preincrement<int X::*>::value)); +STATIC_ASSERT((has_preincrement<W>::value)); +STATIC_ASSERT((has_preincrement<X>::value)); +STATIC_ASSERT((!has_preincrement<Y>::value)); + +// has_predecrement +DEFINE_PREFIX_UNARY_TRAIT(has_predecrement, --); // { dg-error "within this context" } +STATIC_ASSERT((has_predecrement<int>::value)); +STATIC_ASSERT((has_predecrement<int*>::value)); +STATIC_ASSERT((!has_predecrement<int X::*>::value)); +STATIC_ASSERT((has_predecrement<W>::value)); +STATIC_ASSERT((has_predecrement<X>::value)); +STATIC_ASSERT((!has_predecrement<Y>::value)); + +// has_postincrement +DEFINE_POSTFIX_UNARY_TRAIT(has_postincrement, ++); // { dg-error "within this context" } +STATIC_ASSERT((has_postincrement<int>::value)); +STATIC_ASSERT((has_postincrement<int*>::value)); +STATIC_ASSERT((!has_postincrement<int X::*>::value)); +STATIC_ASSERT((has_postincrement<W>::value)); +STATIC_ASSERT((has_postincrement<X>::value)); +STATIC_ASSERT((!has_postincrement<Y>::value)); + +// has_postdecrement +DEFINE_POSTFIX_UNARY_TRAIT(has_postdecrement, --); // { dg-error "within this context" } +STATIC_ASSERT((has_postdecrement<int>::value)); +STATIC_ASSERT((has_postdecrement<int*>::value)); +STATIC_ASSERT((!has_postdecrement<int X::*>::value)); +STATIC_ASSERT((has_postdecrement<W>::value)); +STATIC_ASSERT((has_postdecrement<X>::value)); +STATIC_ASSERT((!has_postdecrement<Y>::value)); + +// Check for private members +STATIC_ASSERT((has_unary_plus<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((is_negatable<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((is_dereferenceable<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_bitwise_not<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_truth_not<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_preincrement<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_predecrement<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_postincrement<Z>::value)); // { dg-error "instantiated from here" } +STATIC_ASSERT((has_postdecrement<Z>::value)); // { dg-error "instantiated from here" } + diff --git a/gcc/testsuite/g++.dg/template/sfinae11.C b/gcc/testsuite/g++.dg/template/sfinae11.C new file mode 100644 index 0000000..a813055 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae11.C @@ -0,0 +1,53 @@ +// DR 339 +// +// Test of the use of the comma operator with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +template<typename T, typename U> + typename enable_if<(sizeof(create_a<T>(), create_a<U>()) > 0), + yes_type>::type + check_comma(int); + +template<typename T, typename U> no_type check_comma(...); + +template<typename T, typename U> +struct has_comma +{ + static const bool value = + (sizeof(check_comma<T, U>(0)) == sizeof(yes_type)); +}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct X { }; +struct Y { }; +struct Z { }; + +bool operator,(X&, Y); +bool operator,(X, Z); +void operator,(const Y&, const Z&); + +STATIC_ASSERT((has_comma<int, float>::value)); +STATIC_ASSERT((has_comma<int, X>::value)); +STATIC_ASSERT((has_comma<X, X>::value)); +STATIC_ASSERT((has_comma<X, Y>::value)); +STATIC_ASSERT((has_comma<X&, Y>::value)); +STATIC_ASSERT((has_comma<X, Z>::value)); +STATIC_ASSERT((!has_comma<Y, Z>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae12.C b/gcc/testsuite/g++.dg/template/sfinae12.C new file mode 100644 index 0000000..c51211b --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae12.C @@ -0,0 +1,47 @@ +// DR 339 +// +// Test of the use of the ternary operator with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +template<typename T, typename U, typename V> +typename enable_if< + (sizeof((create_a<T>()? create_a<U>() : create_a<V>()), 0) > 0), + yes_type>::type + check_ternary(int); + +template<typename T, typename U, typename V> no_type check_ternary(...); + +template<typename T, typename U, typename V> +struct has_ternary +{ + static const bool value = + (sizeof(check_ternary<T, U, V>(0)) == sizeof(yes_type)); +}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct X { }; +struct Y { operator bool(); }; + +STATIC_ASSERT((has_ternary<int, float, double>::value)); +STATIC_ASSERT((has_ternary<bool, double, double>::value)); +STATIC_ASSERT((!has_ternary<int, float*, double>::value)); +STATIC_ASSERT((!has_ternary<X, double, double>::value)); +STATIC_ASSERT((has_ternary<Y, double, double>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae13.C b/gcc/testsuite/g++.dg/template/sfinae13.C new file mode 100644 index 0000000..b659685 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae13.C @@ -0,0 +1,86 @@ +// DR 339 +// +// Test of the use of casts with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#define CHECK_CAST(CastKind) \ +template<typename T, typename U> \ + typename enable_if<(sizeof((JOIN(CastKind,_cast)<U>(create_a<T>())), 0) > 0), \ + yes_type>::type \ + JOIN(check_,JOIN(CastKind,_cast))(int); \ + \ +template<typename T, typename U> \ + no_type JOIN(check_,JOIN(CastKind,_cast))(...); \ + \ +template<typename T, typename U> \ +struct JOIN(has_,JOIN(CastKind,_cast)) \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,JOIN(CastKind,_cast))<T, U>(0)) == sizeof(yes_type)); \ +} + +template<typename T, typename U> +typename enable_if<(sizeof(((U)create_a<T>()), 0) > 0), yes_type>::type + check_c_cast(int); + +template<typename T, typename U> no_type check_c_cast(...); + +template<typename T, typename U> +struct has_c_cast +{ + static const bool value = + (sizeof(check_c_cast<T, U>(0)) == sizeof(yes_type)); +}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +CHECK_CAST(static); +CHECK_CAST(dynamic); +CHECK_CAST(const); +CHECK_CAST(reinterpret); + +struct X { virtual void f(); }; +struct Y { operator bool(); }; +struct Z : public X { }; + +STATIC_ASSERT((has_static_cast<int, float>::value)); +STATIC_ASSERT((!has_static_cast<X, Y>::value)); +STATIC_ASSERT((has_static_cast<Z, X>::value)); + +STATIC_ASSERT(!(has_dynamic_cast<int, float>::value)); +STATIC_ASSERT(!(has_dynamic_cast<X, Y>::value)); +STATIC_ASSERT(!(has_dynamic_cast<X, Z>::value)); +STATIC_ASSERT(!(has_dynamic_cast<Y, Z>::value)); +STATIC_ASSERT((has_dynamic_cast<X*, Z*>::value)); +STATIC_ASSERT((has_dynamic_cast<X*, Y*>::value)); +STATIC_ASSERT(!(has_dynamic_cast<Y*, Z*>::value)); + +STATIC_ASSERT(!(has_const_cast<int, float>::value)); +STATIC_ASSERT((has_const_cast<const int*, int*>::value)); +STATIC_ASSERT((has_const_cast<int*, const int*>::value)); +STATIC_ASSERT(!(has_const_cast<const int*, float*>::value)); + +STATIC_ASSERT((has_reinterpret_cast<int*, float*>::value)); +STATIC_ASSERT(!(has_reinterpret_cast<void*, char>::value)); +STATIC_ASSERT(!(has_reinterpret_cast<const X, X>::value)); + +STATIC_ASSERT((has_c_cast<int, float>::value)); +STATIC_ASSERT(!(has_c_cast<X, Y>::value)); +STATIC_ASSERT(!(has_c_cast<void*, char>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae14.C b/gcc/testsuite/g++.dg/template/sfinae14.C new file mode 100644 index 0000000..93eba43a --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae14.C @@ -0,0 +1,79 @@ +// DR 339 +// +// Test of the use of the new and new[] operators with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +template<typename T> +typename enable_if<(sizeof(new T, 0) > 0), yes_type>::type + check_new(int); + +template<typename T> no_type check_new(...); + +template<typename T> +struct has_new +{ + static const bool value = + (sizeof(check_new<T>(0)) == sizeof(yes_type)); +}; + +template<typename T, typename U> +typename enable_if<(sizeof((new T(create_a<U>())), 0) > 0), + yes_type>::type + check_new_one_arg(int); + +template<typename T, typename U> no_type check_new_one_arg(...); + +template<typename T, typename U> +struct has_new_one_arg +{ + static const bool value = + (sizeof(check_new_one_arg<T, U>(0)) == sizeof(yes_type)); +}; + +template<typename T, typename U, U N> +typename enable_if<(sizeof(new T[N], 0) > 0), yes_type>::type + check_array_new(int); + +template<typename T, typename U, U N> no_type check_array_new(...); + +template<typename T, typename U, U N> +struct has_array_new +{ + static const bool value = + (sizeof(check_array_new<T, U, N>(0)) == sizeof(yes_type)); +}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct X { + X(int); +}; + +struct Y { int foo; }; + +STATIC_ASSERT((has_new<Y>::value)); +STATIC_ASSERT(!(has_new<X>::value)); +STATIC_ASSERT((has_new_one_arg<Y, Y>::value)); +STATIC_ASSERT((has_new_one_arg<X, float>::value)); +STATIC_ASSERT(!(has_new_one_arg<X, int X::*>::value)); + +STATIC_ASSERT((has_array_new<Y, int, 5>::value)); +STATIC_ASSERT(!(has_array_new<X, int Y::*, &Y::foo>::value)); +STATIC_ASSERT((has_array_new<X, int, 5>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae4.C b/gcc/testsuite/g++.dg/template/sfinae4.C new file mode 100644 index 0000000..a965051 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae4.C @@ -0,0 +1,35 @@ +// DR 339 +// +// Test of the use of free functions with SFINAE +void foo(int) { } +template<typename T> void foo(T*) { } + +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +template<typename T> + typename enable_if<(sizeof(foo(create_a<T const&>()), 1) > 0), + yes_type>::type + check_has_foo(const volatile T&); + +no_type check_has_foo(...); + +template<typename T> +struct has_foo +{ + static const bool value = + (sizeof(check_has_foo(create_a<T const&>())) == sizeof(yes_type)); +}; + +struct X { }; + +int a1[has_foo<int>::value? 1 : -1]; +int a2[has_foo<long>::value? 1 : -1]; +int a3[has_foo<int*>::value? 1 : -1]; +int a4[has_foo<X>::value? -1 : 1]; +int a5[has_foo<int X::*>::value? -1 : 1]; diff --git a/gcc/testsuite/g++.dg/template/sfinae5.C b/gcc/testsuite/g++.dg/template/sfinae5.C new file mode 100644 index 0000000..516e5cc --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae5.C @@ -0,0 +1,47 @@ +// DR 339 +// +// Test of the use of member functions with SFINAE +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +template<typename T> + typename enable_if<(sizeof(create_a<T>().foo(), 1) > 0), + yes_type>::type + check_has_member_foo(const volatile T&); + +no_type check_has_member_foo(...); + +template<typename T> +struct has_foo +{ + static const bool value = + (sizeof(check_has_member_foo(create_a<T const&>())) == sizeof(yes_type)); +}; + +struct X { }; +struct Y { + void foo(); +}; +struct Z { + void foo(int); +}; + +struct A { + int foo; +}; + +struct B { + static int foo(); +}; + +int a1[has_foo<X>::value? -1 : 1]; +int a2[has_foo<Y>::value? 1 : -1]; +int a3[has_foo<Z>::value? -1 : 1]; +int a4[has_foo<int>::value? -1 : 1]; +int a5[has_foo<A>::value? -1 : 1]; +int a6[has_foo<B>::value? 1 : -1]; diff --git a/gcc/testsuite/g++.dg/template/sfinae6.C b/gcc/testsuite/g++.dg/template/sfinae6.C new file mode 100644 index 0000000..64567aa --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae6.C @@ -0,0 +1,83 @@ +// DR 339 +// +// Test of the use of the function call operator with SFINAE +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); + +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +template<typename F, typename T1, typename T2> + typename enable_if<sizeof(create_a<F>()(create_a<T1>(), create_a<T2>()), 1), + yes_type>::type + check_is_callable2(type<F>, type<T1>, type<T2>); + +no_type check_is_callable2(...); + +template<typename F, typename T1, typename T2 = T1> +struct is_callable2 +{ + static const bool value = + (sizeof(check_is_callable2(type<F>(), type<T1>(), type<T2>())) + == sizeof(yes_type)); +}; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + + +struct A; +struct B; + +struct A { + A(B); +}; + +struct B { + B(A); +}; + +struct F1 { }; + +struct F2 { + bool operator()(int, float); +}; + +struct F3 { + bool operator()(int); +}; + +struct F4 { + void operator()(A, A); + void operator()(B, B); +}; + +struct F5 { + void operator()(A, A); + +private: + void operator()(B, B); +}; + +STATIC_ASSERT((is_callable2<int(*)(int, int), long, int>::value)); +STATIC_ASSERT((!is_callable2<int(*)(int, int), int*, int>::value)); +STATIC_ASSERT((!is_callable2<F1, int, int>::value)); +STATIC_ASSERT((is_callable2<F2, int, int>::value)); +STATIC_ASSERT((!is_callable2<F2, int*, int>::value)); +STATIC_ASSERT((!is_callable2<F3, int, int>::value)); +STATIC_ASSERT((is_callable2<F4, A, A>::value)); +STATIC_ASSERT((is_callable2<F4, B, B>::value)); +STATIC_ASSERT((!is_callable2<F4, A, B>::value)); +STATIC_ASSERT((is_callable2<F5, A, A>::value)); +STATIC_ASSERT((!is_callable2<F5, A, B>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae6_neg.C b/gcc/testsuite/g++.dg/template/sfinae6_neg.C new file mode 100644 index 0000000..2df4ade --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae6_neg.C @@ -0,0 +1,58 @@ +// DR 339 +// +// Test of the use of the function call operator with SFINAE +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); + +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +template<typename F, typename T1, typename T2> + typename enable_if<sizeof(create_a<F>()(create_a<T1>(), create_a<T2>()), 1), + yes_type>::type + check_is_callable2(type<F>, type<T1>, type<T2>); + +no_type check_is_callable2(...); + +template<typename F, typename T1, typename T2 = T1> +struct is_callable2 +{ + static const bool value = + (sizeof(check_is_callable2(type<F>(), type<T1>(), type<T2>())) + == sizeof(yes_type)); // { dg-error "within this context" } +}; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + + +struct A; +struct B; + +struct A { + A(B); +}; + +struct B { + B(A); +}; + +struct F { + void operator()(A, A); + +private: + void operator()(B, B); // { dg-error "is private" } +}; + +STATIC_ASSERT((is_callable2<F, B, B>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae7.C b/gcc/testsuite/g++.dg/template/sfinae7.C new file mode 100644 index 0000000..8551eb27 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae7.C @@ -0,0 +1,199 @@ +// DR 339 +// +// Test of the use of various binary operators with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#define DEFINE_INFIX_BINARY_TRAIT(Name,Op) \ +template<typename T, typename U> \ + typename enable_if<(sizeof(create_a<T>() Op create_a<U>(), 1) > 0), \ + yes_type>::type \ + JOIN(check_,Name)(type<T>, type<U>); \ + \ +no_type JOIN(check_,Name)(...); \ + \ +template<typename T, typename U = T> \ +struct Name \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,Name)(type<T>(), type<U>())) == sizeof(yes_type)); \ +} + +template<typename T, typename U> + typename enable_if<(sizeof(create_a<T>()[create_a<U>()], 1) > 0), + yes_type>::type + check_subscript(int); + +template<typename T, typename U> + no_type check_subscript(...); + +template<typename T, typename U> +struct can_subscript +{ + static const bool value = + (sizeof(check_subscript<T, U>(0)) == sizeof(yes_type)); +}; + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct X { }; +struct Y { int operator[](X); }; + +// is_addable +DEFINE_INFIX_BINARY_TRAIT(is_addable, +); +X operator+(X, X); +X operator+(X, Y); +STATIC_ASSERT((is_addable<int>::value)); +STATIC_ASSERT((is_addable<int, long>::value)); +STATIC_ASSERT((is_addable<X>::value)); +STATIC_ASSERT((is_addable<int*, int>::value)); +STATIC_ASSERT((!is_addable<int*>::value)); +STATIC_ASSERT((is_addable<X, Y>::value)); +STATIC_ASSERT((!is_addable<Y>::value)); + +// is_subtractable +DEFINE_INFIX_BINARY_TRAIT(is_subtractable, -); +X operator-(X, X); +X operator-(X, Y); +STATIC_ASSERT((is_subtractable<int>::value)); +STATIC_ASSERT((is_subtractable<int, long>::value)); +STATIC_ASSERT((is_subtractable<X>::value)); +STATIC_ASSERT((is_subtractable<int*, int>::value)); +STATIC_ASSERT((is_subtractable<int*>::value)); +STATIC_ASSERT((is_subtractable<X, Y>::value)); +STATIC_ASSERT((!is_subtractable<Y>::value)); +STATIC_ASSERT((!is_subtractable<int X::*>::value)); + +// is_multiplicable +DEFINE_INFIX_BINARY_TRAIT(is_multiplicable, *); +X operator*(X, X); +X operator*(X, Y); +STATIC_ASSERT((is_multiplicable<int>::value)); +STATIC_ASSERT((is_multiplicable<int, long>::value)); +STATIC_ASSERT((is_multiplicable<X>::value)); +STATIC_ASSERT((!is_multiplicable<int*, int>::value)); +STATIC_ASSERT((!is_multiplicable<int*>::value)); +STATIC_ASSERT((is_multiplicable<X, Y>::value)); +STATIC_ASSERT((!is_multiplicable<Y>::value)); +STATIC_ASSERT((!is_multiplicable<int X::*>::value)); + +// is_divisible +DEFINE_INFIX_BINARY_TRAIT(is_divisible, /); +X operator/(X, X); +X operator/(X, Y); +STATIC_ASSERT((is_divisible<int>::value)); +STATIC_ASSERT((is_divisible<int, long>::value)); +STATIC_ASSERT((is_divisible<X>::value)); +STATIC_ASSERT((!is_divisible<int*, int>::value)); +STATIC_ASSERT((!is_divisible<int*>::value)); +STATIC_ASSERT((is_divisible<X, Y>::value)); +STATIC_ASSERT((!is_divisible<Y>::value)); +STATIC_ASSERT((!is_divisible<int X::*>::value)); + +// has_remainder +DEFINE_INFIX_BINARY_TRAIT(has_remainder, %); +X operator%(X, X); +X operator%(X, Y); +STATIC_ASSERT((has_remainder<int>::value)); +STATIC_ASSERT((has_remainder<int, long>::value)); +STATIC_ASSERT((!has_remainder<float>::value)); +STATIC_ASSERT((has_remainder<X>::value)); +STATIC_ASSERT((!has_remainder<int*, int>::value)); +STATIC_ASSERT((!has_remainder<int*>::value)); +STATIC_ASSERT((has_remainder<X, Y>::value)); +STATIC_ASSERT((!has_remainder<Y>::value)); +STATIC_ASSERT((!has_remainder<int X::*>::value)); + +// has_xor +DEFINE_INFIX_BINARY_TRAIT(has_xor, ^); +X operator^(X, X); +X operator^(X, Y); +STATIC_ASSERT((has_xor<int>::value)); +STATIC_ASSERT((has_xor<int, long>::value)); +STATIC_ASSERT((!has_xor<float>::value)); +STATIC_ASSERT((has_xor<X>::value)); +STATIC_ASSERT((!has_xor<int*, int>::value)); +STATIC_ASSERT((!has_xor<int*>::value)); +STATIC_ASSERT((has_xor<X, Y>::value)); +STATIC_ASSERT((!has_xor<Y>::value)); +STATIC_ASSERT((!has_xor<int X::*>::value)); + +// has_bitand +DEFINE_INFIX_BINARY_TRAIT(has_bitand, &); +X operator&(X, X); +X operator&(X, Y); +STATIC_ASSERT((has_bitand<int>::value)); +STATIC_ASSERT((has_bitand<int, long>::value)); +STATIC_ASSERT((!has_bitand<float>::value)); +STATIC_ASSERT((has_bitand<X>::value)); +STATIC_ASSERT((!has_bitand<int*, int>::value)); +STATIC_ASSERT((!has_bitand<int*>::value)); +STATIC_ASSERT((has_bitand<X, Y>::value)); +STATIC_ASSERT((!has_bitand<Y>::value)); +STATIC_ASSERT((!has_bitand<int X::*>::value)); + +// has_bitor +DEFINE_INFIX_BINARY_TRAIT(has_bitor, |); +X operator|(X, X); +X operator|(X, Y); +STATIC_ASSERT((has_bitor<int>::value)); +STATIC_ASSERT((has_bitor<int, long>::value)); +STATIC_ASSERT((!has_bitor<float>::value)); +STATIC_ASSERT((has_bitor<X>::value)); +STATIC_ASSERT((!has_bitor<int*, int>::value)); +STATIC_ASSERT((!has_bitor<int*>::value)); +STATIC_ASSERT((has_bitor<X, Y>::value)); +STATIC_ASSERT((!has_bitor<Y>::value)); +STATIC_ASSERT((!has_bitor<int X::*>::value)); + +// has_left_shift +DEFINE_INFIX_BINARY_TRAIT(has_left_shift, <<); +X operator<<(X, X); +X operator<<(X, Y); +STATIC_ASSERT((has_left_shift<int>::value)); +STATIC_ASSERT((has_left_shift<int, long>::value)); +STATIC_ASSERT((!has_left_shift<float>::value)); +STATIC_ASSERT((has_left_shift<X>::value)); +STATIC_ASSERT((!has_left_shift<int*, int>::value)); +STATIC_ASSERT((!has_left_shift<int*>::value)); +STATIC_ASSERT((has_left_shift<X, Y>::value)); +STATIC_ASSERT((!has_left_shift<Y>::value)); +STATIC_ASSERT((!has_left_shift<int X::*>::value)); + +// has_right_shift +DEFINE_INFIX_BINARY_TRAIT(has_right_shift, >>); +X operator>>(X, X); +X operator>>(X, Y); +STATIC_ASSERT((has_right_shift<int>::value)); +STATIC_ASSERT((has_right_shift<int, long>::value)); +STATIC_ASSERT((!has_right_shift<float>::value)); +STATIC_ASSERT((has_right_shift<X>::value)); +STATIC_ASSERT((!has_right_shift<int*, int>::value)); +STATIC_ASSERT((!has_right_shift<int*>::value)); +STATIC_ASSERT((has_right_shift<X, Y>::value)); +STATIC_ASSERT((!has_right_shift<Y>::value)); +STATIC_ASSERT((!has_right_shift<int X::*>::value)); + +// can_subscript +STATIC_ASSERT((can_subscript<int*, int>::value)); +STATIC_ASSERT((can_subscript<int, int*>::value)); +STATIC_ASSERT((can_subscript<int(&)[7], int>::value)); +STATIC_ASSERT((can_subscript<int, int(&)[7]>::value)); +STATIC_ASSERT((!can_subscript<X, Y>::value)); +STATIC_ASSERT((can_subscript<Y, X>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae8.C b/gcc/testsuite/g++.dg/template/sfinae8.C new file mode 100644 index 0000000..2ad68dc --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae8.C @@ -0,0 +1,182 @@ +// DR 339 +// +// Test of the use of various boolean binary operators with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +bool accepts_bool(bool); + +#define DEFINE_BINARY_PREDICATE_TRAIT(Name,Op) \ +template<typename T, typename U> \ + typename enable_if<sizeof(accepts_bool(create_a<T>() Op create_a<U>())), \ + yes_type>::type \ + JOIN(check_,Name)(type<T>, type<U>); \ + \ +no_type JOIN(check_,Name)(...); \ + \ +template<typename T, typename U = T> \ +struct Name \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,Name)(type<T>(), type<U>())) == sizeof(yes_type)); \ +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct X { }; +struct Y { }; + +struct convertible_to_bool { + operator int convertible_to_bool::* (); +}; + +struct not_convertible_to_bool { }; + +// is_less_than_comparable +DEFINE_BINARY_PREDICATE_TRAIT(is_less_than_comparable,<); +bool operator<(X, X); +convertible_to_bool operator<(X, Y); +not_convertible_to_bool operator<(Y, X); + +STATIC_ASSERT((is_less_than_comparable<int>::value)); +STATIC_ASSERT((is_less_than_comparable<int, long>::value)); +STATIC_ASSERT((is_less_than_comparable<int*>::value)); +STATIC_ASSERT((is_less_than_comparable<X>::value)); +STATIC_ASSERT((is_less_than_comparable<X, Y>::value)); +STATIC_ASSERT((!is_less_than_comparable<Y, X>::value)); +STATIC_ASSERT((!is_less_than_comparable<Y>::value)); + +// is_less_equal_comparable +DEFINE_BINARY_PREDICATE_TRAIT(is_less_equal_comparable,<=); +bool operator<=(X, X); +convertible_to_bool operator<=(X, Y); +not_convertible_to_bool operator<=(Y, X); + +STATIC_ASSERT((is_less_equal_comparable<int>::value)); +STATIC_ASSERT((is_less_equal_comparable<int, long>::value)); +STATIC_ASSERT((is_less_equal_comparable<int*>::value)); +STATIC_ASSERT((is_less_equal_comparable<X>::value)); +STATIC_ASSERT((is_less_equal_comparable<X, Y>::value)); +STATIC_ASSERT((!is_less_equal_comparable<Y, X>::value)); +STATIC_ASSERT((!is_less_equal_comparable<Y>::value)); + +// is_greater_than_comparable +DEFINE_BINARY_PREDICATE_TRAIT(is_greater_than_comparable,>); +bool operator>(X, X); +convertible_to_bool operator>(X, Y); +not_convertible_to_bool operator>(Y, X); + +STATIC_ASSERT((is_greater_than_comparable<int>::value)); +STATIC_ASSERT((is_greater_than_comparable<int, long>::value)); +STATIC_ASSERT((is_greater_than_comparable<int*>::value)); +STATIC_ASSERT((is_greater_than_comparable<X>::value)); +STATIC_ASSERT((is_greater_than_comparable<X, Y>::value)); +STATIC_ASSERT((!is_greater_than_comparable<Y, X>::value)); +STATIC_ASSERT((!is_greater_than_comparable<Y>::value)); + +// is_greater_equal_comparable +DEFINE_BINARY_PREDICATE_TRAIT(is_greater_equal_comparable,>=); +bool operator>=(X, X); +convertible_to_bool operator>=(X, Y); +not_convertible_to_bool operator>=(Y, X); + +STATIC_ASSERT((is_greater_equal_comparable<int>::value)); +STATIC_ASSERT((is_greater_equal_comparable<int, long>::value)); +STATIC_ASSERT((is_greater_equal_comparable<int*>::value)); +STATIC_ASSERT((is_greater_equal_comparable<X>::value)); +STATIC_ASSERT((is_greater_equal_comparable<X, Y>::value)); +STATIC_ASSERT((!is_greater_equal_comparable<Y, X>::value)); +STATIC_ASSERT((!is_greater_equal_comparable<Y>::value)); + +// is_equality_comparable +struct Z : X { }; +DEFINE_BINARY_PREDICATE_TRAIT(is_equality_comparable,==); +bool operator==(X, X); +convertible_to_bool operator==(X, Y); +not_convertible_to_bool operator==(Y, X); + +STATIC_ASSERT((is_equality_comparable<int>::value)); +STATIC_ASSERT((is_equality_comparable<int, long>::value)); +STATIC_ASSERT((is_equality_comparable<int*>::value)); +STATIC_ASSERT((is_equality_comparable<X>::value)); +STATIC_ASSERT((is_equality_comparable<X, Y>::value)); +STATIC_ASSERT((!is_equality_comparable<Y, X>::value)); +STATIC_ASSERT((!is_equality_comparable<Y>::value)); +STATIC_ASSERT((is_equality_comparable<int X::*>::value)); +STATIC_ASSERT((!is_equality_comparable<int X::*, int Y::*>::value)); +STATIC_ASSERT((is_equality_comparable<int*, float*>::value)); +STATIC_ASSERT((is_equality_comparable<X*, Z*>::value)); +STATIC_ASSERT((!is_equality_comparable<X*, Y*>::value)); + +// is_not_equal_comparable +DEFINE_BINARY_PREDICATE_TRAIT(is_not_equal_comparable,!=); +bool operator!=(X, X); +convertible_to_bool operator!=(X, Y); +not_convertible_to_bool operator!=(Y, X); + +STATIC_ASSERT((is_not_equal_comparable<int>::value)); +STATIC_ASSERT((is_not_equal_comparable<int, long>::value)); +STATIC_ASSERT((is_not_equal_comparable<int*>::value)); +STATIC_ASSERT((is_not_equal_comparable<X>::value)); +STATIC_ASSERT((is_not_equal_comparable<X, Y>::value)); +STATIC_ASSERT((!is_not_equal_comparable<Y, X>::value)); +STATIC_ASSERT((!is_not_equal_comparable<Y>::value)); +STATIC_ASSERT((is_not_equal_comparable<int X::*>::value)); +STATIC_ASSERT((!is_not_equal_comparable<int X::*, int Y::*>::value)); +STATIC_ASSERT((is_not_equal_comparable<int*, float*>::value)); +STATIC_ASSERT((is_not_equal_comparable<X*, Z*>::value)); +STATIC_ASSERT((!is_not_equal_comparable<X*, Y*>::value)); + +// has_logical_and +DEFINE_BINARY_PREDICATE_TRAIT(has_logical_and,&&); +bool operator&&(X, X); +convertible_to_bool operator&&(X, Y); +not_convertible_to_bool operator&&(Y, X); + +STATIC_ASSERT((has_logical_and<int>::value)); +STATIC_ASSERT((has_logical_and<int, long>::value)); +STATIC_ASSERT((has_logical_and<int*>::value)); +STATIC_ASSERT((has_logical_and<X>::value)); +STATIC_ASSERT((has_logical_and<X, Y>::value)); +STATIC_ASSERT((!has_logical_and<Y, X>::value)); +STATIC_ASSERT((!has_logical_and<Y>::value)); +STATIC_ASSERT((has_logical_and<int X::*>::value)); +STATIC_ASSERT((has_logical_and<int X::*, int Y::*>::value)); +STATIC_ASSERT((has_logical_and<int*, float*>::value)); +STATIC_ASSERT((has_logical_and<X*, Z*>::value)); +STATIC_ASSERT((has_logical_and<X*, Y*>::value)); + +// has_logical_or +DEFINE_BINARY_PREDICATE_TRAIT(has_logical_or,||); +bool operator||(X, X); +convertible_to_bool operator||(X, Y); +not_convertible_to_bool operator||(Y, X); + +STATIC_ASSERT((has_logical_or<int>::value)); +STATIC_ASSERT((has_logical_or<int, long>::value)); +STATIC_ASSERT((has_logical_or<int*>::value)); +STATIC_ASSERT((has_logical_or<X>::value)); +STATIC_ASSERT((has_logical_or<X, Y>::value)); +STATIC_ASSERT((!has_logical_or<Y, X>::value)); +STATIC_ASSERT((!has_logical_or<Y>::value)); +STATIC_ASSERT((has_logical_or<int X::*>::value)); +STATIC_ASSERT((has_logical_or<int X::*, int Y::*>::value)); +STATIC_ASSERT((has_logical_or<int*, float*>::value)); +STATIC_ASSERT((has_logical_or<X*, Z*>::value)); +STATIC_ASSERT((has_logical_or<X*, Y*>::value)); diff --git a/gcc/testsuite/g++.dg/template/sfinae9.C b/gcc/testsuite/g++.dg/template/sfinae9.C new file mode 100644 index 0000000..4e27ff6 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/sfinae9.C @@ -0,0 +1,207 @@ +// DR 339 +// +// Test of the use of various assignment operators with SFINAE + +// Boilerplate helpers +typedef char yes_type; +struct no_type { char data[2]; }; + +template<typename T> T create_a(); +template<typename T> struct type { }; + +template<bool, typename T = void> struct enable_if { typedef T type; }; +template<typename T> struct enable_if<false, T> { }; + +#define JOIN( X, Y ) DO_JOIN( X, Y ) +#define DO_JOIN( X, Y ) DO_JOIN2(X,Y) +#define DO_JOIN2( X, Y ) X##Y + +#define DEFINE_INFIX_BINARY_TRAIT(Name,Op) \ +template<typename T, typename U> \ + typename enable_if<(sizeof(create_a<T>() Op create_a<U>(), 1) > 0), \ + yes_type>::type \ + JOIN(check_,Name)(type<T>, type<U>); \ + \ +no_type JOIN(check_,Name)(...); \ + \ +template<typename T, typename U = T> \ +struct Name \ +{ \ + static const bool value = \ + (sizeof(JOIN(check_,Name)(type<T&>(), type<U>())) == sizeof(yes_type)); \ +} + +#ifdef __GXX_EXPERIMENTAL_CXX0X__ +# define STATIC_ASSERT(Expr) static_assert(Expr, #Expr) +#else +# define STATIC_ASSERT(Expr) int JOIN(a,__LINE__)[Expr? 1 : -1] +#endif + +struct Y { + Y& operator=(Y&); +}; + +struct X { + X& operator=(Y); + X& operator+=(X); + X& operator-=(X); + X& operator*=(X); + X& operator/=(X); + X& operator%=(X); + X& operator^=(X); + X& operator&=(X); + X& operator|=(X); + X& operator<<=(X); + X& operator>>=(X); +}; +struct Z { }; + +// is_assignable +DEFINE_INFIX_BINARY_TRAIT(is_assignable, =); +STATIC_ASSERT((is_assignable<int>::value)); +STATIC_ASSERT((is_assignable<int, long>::value)); +STATIC_ASSERT((is_assignable<X>::value)); +STATIC_ASSERT((!is_assignable<int*, int>::value)); +STATIC_ASSERT((is_assignable<int*>::value)); +STATIC_ASSERT((is_assignable<X, Y>::value)); +STATIC_ASSERT((!is_assignable<X, Z>::value)); +STATIC_ASSERT((!is_assignable<Y>::value)); +STATIC_ASSERT((!is_assignable<const int, long>::value)); + +// has_plus_assign +DEFINE_INFIX_BINARY_TRAIT(has_plus_assign, +=); +X& operator+=(X&, Y); +STATIC_ASSERT((has_plus_assign<int>::value)); +STATIC_ASSERT((has_plus_assign<int, long>::value)); +STATIC_ASSERT((has_plus_assign<X>::value)); +STATIC_ASSERT((has_plus_assign<int*, int>::value)); +STATIC_ASSERT((!has_plus_assign<int*>::value)); +STATIC_ASSERT((has_plus_assign<X, Y>::value)); +STATIC_ASSERT((!has_plus_assign<X, Z>::value)); +STATIC_ASSERT((!has_plus_assign<Y>::value)); +STATIC_ASSERT((!has_plus_assign<const int, long>::value)); + +// has_minus_assign +DEFINE_INFIX_BINARY_TRAIT(has_minus_assign, -=); +X& operator-=(X&, Y); +STATIC_ASSERT((has_minus_assign<int>::value)); +STATIC_ASSERT((has_minus_assign<int, long>::value)); +STATIC_ASSERT((has_minus_assign<X>::value)); +STATIC_ASSERT((has_minus_assign<int*, int>::value)); +STATIC_ASSERT((!has_minus_assign<int*>::value)); +STATIC_ASSERT((has_minus_assign<X, Y>::value)); +STATIC_ASSERT((!has_minus_assign<X, Z>::value)); +STATIC_ASSERT((!has_minus_assign<Y>::value)); +STATIC_ASSERT((!has_minus_assign<int X::*>::value)); +STATIC_ASSERT((!has_minus_assign<const int, long>::value)); + +// has_multiply_assign +DEFINE_INFIX_BINARY_TRAIT(has_multiply_assign, *=); +X& operator*=(X&, Y); +STATIC_ASSERT((has_multiply_assign<int>::value)); +STATIC_ASSERT((has_multiply_assign<int, long>::value)); +STATIC_ASSERT((has_multiply_assign<X>::value)); +STATIC_ASSERT((!has_multiply_assign<int*, int>::value)); +STATIC_ASSERT((!has_multiply_assign<int*>::value)); +STATIC_ASSERT((has_multiply_assign<X, Y>::value)); +STATIC_ASSERT((!has_multiply_assign<X, Z>::value)); +STATIC_ASSERT((!has_multiply_assign<Y>::value)); +STATIC_ASSERT((!has_multiply_assign<int X::*>::value)); +STATIC_ASSERT((!has_multiply_assign<const int, long>::value)); + +// has_divide_assign +DEFINE_INFIX_BINARY_TRAIT(has_divide_assign, /=); +X& operator/=(X&, Y); +STATIC_ASSERT((has_divide_assign<int>::value)); +STATIC_ASSERT((has_divide_assign<int, long>::value)); +STATIC_ASSERT((has_divide_assign<X>::value)); +STATIC_ASSERT((!has_divide_assign<int*, int>::value)); +STATIC_ASSERT((!has_divide_assign<int*>::value)); +STATIC_ASSERT((has_divide_assign<X, Y>::value)); +STATIC_ASSERT((!has_divide_assign<X, Z>::value)); +STATIC_ASSERT((!has_divide_assign<Y>::value)); +STATIC_ASSERT((!has_divide_assign<int X::*>::value)); + +// has_remainder_assign +DEFINE_INFIX_BINARY_TRAIT(has_remainder_assign, %=); +X& operator%=(X&, Y); +STATIC_ASSERT((has_remainder_assign<int>::value)); +STATIC_ASSERT((has_remainder_assign<int, long>::value)); +STATIC_ASSERT((!has_remainder_assign<float>::value)); +STATIC_ASSERT((has_remainder_assign<X>::value)); +STATIC_ASSERT((!has_remainder_assign<int*, int>::value)); +STATIC_ASSERT((!has_remainder_assign<int*>::value)); +STATIC_ASSERT((has_remainder_assign<X, Y>::value)); +STATIC_ASSERT((!has_remainder_assign<X, Z>::value)); +STATIC_ASSERT((!has_remainder_assign<Y>::value)); +STATIC_ASSERT((!has_remainder_assign<int X::*>::value)); + +// has_xor_assign +DEFINE_INFIX_BINARY_TRAIT(has_xor_assign, ^=); +X& operator^=(X&, Y); +STATIC_ASSERT((has_xor_assign<int>::value)); +STATIC_ASSERT((has_xor_assign<int, long>::value)); +STATIC_ASSERT((!has_xor_assign<float>::value)); +STATIC_ASSERT((has_xor_assign<X>::value)); +STATIC_ASSERT((!has_xor_assign<int*, int>::value)); +STATIC_ASSERT((!has_xor_assign<int*>::value)); +STATIC_ASSERT((has_xor_assign<X, Y>::value)); +STATIC_ASSERT((!has_xor_assign<X, Z>::value)); +STATIC_ASSERT((!has_xor_assign<Y>::value)); +STATIC_ASSERT((!has_xor_assign<int X::*>::value)); + +// has_bitand_assign +DEFINE_INFIX_BINARY_TRAIT(has_bitand_assign, &=); +X& operator&=(X&, Y); +STATIC_ASSERT((has_bitand_assign<int>::value)); +STATIC_ASSERT((has_bitand_assign<int, long>::value)); +STATIC_ASSERT((!has_bitand_assign<float>::value)); +STATIC_ASSERT((has_bitand_assign<X>::value)); +STATIC_ASSERT((!has_bitand_assign<int*, int>::value)); +STATIC_ASSERT((!has_bitand_assign<int*>::value)); +STATIC_ASSERT((has_bitand_assign<X, Y>::value)); +STATIC_ASSERT((!has_bitand_assign<X, Z>::value)); +STATIC_ASSERT((!has_bitand_assign<Y>::value)); +STATIC_ASSERT((!has_bitand_assign<int X::*>::value)); + +// has_bitor_assign +DEFINE_INFIX_BINARY_TRAIT(has_bitor_assign, |=); +X& operator|=(X&, Y); +STATIC_ASSERT((has_bitor_assign<int>::value)); +STATIC_ASSERT((has_bitor_assign<int, long>::value)); +STATIC_ASSERT((!has_bitor_assign<float>::value)); +STATIC_ASSERT((has_bitor_assign<X>::value)); +STATIC_ASSERT((!has_bitor_assign<int*, int>::value)); +STATIC_ASSERT((!has_bitor_assign<int*>::value)); +STATIC_ASSERT((has_bitor_assign<X, Y>::value)); +STATIC_ASSERT((!has_bitor_assign<X, Z>::value)); +STATIC_ASSERT((!has_bitor_assign<Y>::value)); +STATIC_ASSERT((!has_bitor_assign<int X::*>::value)); + +// has_left_shift_assign +DEFINE_INFIX_BINARY_TRAIT(has_left_shift_assign, <<=); +X& operator<<=(X&, Y); +STATIC_ASSERT((has_left_shift_assign<int>::value)); +STATIC_ASSERT((has_left_shift_assign<int, long>::value)); +STATIC_ASSERT((!has_left_shift_assign<float>::value)); +STATIC_ASSERT((has_left_shift_assign<X>::value)); +STATIC_ASSERT((!has_left_shift_assign<int*, int>::value)); +STATIC_ASSERT((!has_left_shift_assign<int*>::value)); +STATIC_ASSERT((has_left_shift_assign<X, Y>::value)); +STATIC_ASSERT((!has_left_shift_assign<X, Z>::value)); +STATIC_ASSERT((!has_left_shift_assign<Y>::value)); +STATIC_ASSERT((!has_left_shift_assign<int X::*>::value)); + +// has_right_shift_assign +DEFINE_INFIX_BINARY_TRAIT(has_right_shift_assign, >>=); +X& operator>>=(X&, Y); +STATIC_ASSERT((has_right_shift_assign<int>::value)); +STATIC_ASSERT((has_right_shift_assign<int, long>::value)); +STATIC_ASSERT((!has_right_shift_assign<float>::value)); +STATIC_ASSERT((has_right_shift_assign<X>::value)); +STATIC_ASSERT((!has_right_shift_assign<int*, int>::value)); +STATIC_ASSERT((!has_right_shift_assign<int*>::value)); +STATIC_ASSERT((has_right_shift_assign<X, Y>::value)); +STATIC_ASSERT((!has_right_shift_assign<X, Z>::value)); +STATIC_ASSERT((!has_right_shift_assign<Y>::value)); +STATIC_ASSERT((!has_right_shift_assign<int X::*>::value)); |