aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorDouglas Gregor <doug.gregor@gmail.com>2008-03-25 13:53:58 +0000
committerDoug Gregor <dgregor@gcc.gnu.org>2008-03-25 13:53:58 +0000
commit5ade1ed2c08bf2f327ee24afc57bc263fd90e6e1 (patch)
tree3ef47d27df52cfcaa5644727ec9e934a79cad636 /gcc
parentde6adfa2f4dfd7afd05eecab3b6cb6b2321d6ef2 (diff)
downloadgcc-5ade1ed2c08bf2f327ee24afc57bc263fd90e6e1.zip
gcc-5ade1ed2c08bf2f327ee24afc57bc263fd90e6e1.tar.gz
gcc-5ade1ed2c08bf2f327ee24afc57bc263fd90e6e1.tar.bz2
typeck.c (composite_pointer_type_r): Add SFINAE support.
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-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 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. From-SVN: r133519
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/c-common.c4
-rw-r--r--gcc/cp/ChangeLog205
-rw-r--r--gcc/cp/call.c431
-rw-r--r--gcc/cp/class.c30
-rw-r--r--gcc/cp/cp-tree.h99
-rw-r--r--gcc/cp/cvt.c64
-rw-r--r--gcc/cp/decl.c25
-rw-r--r--gcc/cp/decl2.c47
-rw-r--r--gcc/cp/except.c36
-rw-r--r--gcc/cp/init.c260
-rw-r--r--gcc/cp/method.c6
-rw-r--r--gcc/cp/parser.c60
-rw-r--r--gcc/cp/pt.c60
-rw-r--r--gcc/cp/rtti.c44
-rw-r--r--gcc/cp/semantics.c58
-rw-r--r--gcc/cp/tree.c6
-rw-r--r--gcc/cp/typeck.c947
-rw-r--r--gcc/cp/typeck2.c27
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae10.C181
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae11.C53
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae12.C47
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae13.C86
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae14.C79
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae4.C35
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae5.C47
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae6.C83
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae6_neg.C58
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae7.C199
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae8.C182
-rw-r--r--gcc/testsuite/g++.dg/template/sfinae9.C207
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));