typeck.c (composite_pointer_type_r): Add SFINAE support.
authorDouglas Gregor <doug.gregor@gmail.com>
Tue, 25 Mar 2008 13:53:58 +0000 (13:53 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Tue, 25 Mar 2008 13:53:58 +0000 (13:53 +0000)
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

32 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/except.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/rtti.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/sfinae10.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae6.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae6_neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae7.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae8.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/sfinae9.C [new file with mode: 0644]

index 03f6332e777273aeaae5f2965d011763a7abed0c..05ece07463890b3e8e450d8c8732398072ff8da5 100644 (file)
@@ -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.
index 2bc74348e6a9f734eee7fd4997a54d83f61884df..1b6297452394ec2e5af47f7f00c59a033727020c 100644 (file)
@@ -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))
index ce147f76da19d5b6825d4c70b0e28cf1e229fe27..c90f58396bd2c109b4288ebf14fa5fa619afa256 100644 (file)
@@ -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.
index 41e6933f68633f3fd2f529e1b1f6589991050a0d..29dda07426fb80f604433d6417da8885a1385ed8 100644 (file)
@@ -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);
index 154c3b3fc37cadcd8d88c9e9a7274e2e887ca98a..69acf11cdfc80630296e5f0822893c5044d00546 100644 (file)
@@ -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);
index 9afeed71fbe728cedc0e0cf3f330ac0ca737815b..8387fd790e08c906119f11ee046a751233afc21d 100644 (file)
@@ -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);
 
index 64a871650e1594aa3a3ae90241f9eb64116e310d..fe1ed29ec65a2c5fb2efbac3fce6ef10dd35349c 100644 (file)
@@ -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");
            }
        }
index 8353b9b64c3f44fb87118655d1a7e9f208f3ef4d..df0b78c19715adabd98b0450e87a41dd12c9dca9 100644 (file)
@@ -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;
     }
index 367d9eba26b31131dda78e37e96fc7ea90d6f7f0..078ca99e6f89ef791d821b61590fe4dc78726819 100644 (file)
@@ -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;
index 38111b16338407e3015a2a61cae7b9a32f96b9e9..5304381a4994169664e8734b16db21582229cff8 100644 (file)
@@ -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);
index e0700eacb4f056411e945ba0f6c5f7aed4999507..dc4e988a3eec4a8868fe77d1fef969a76b43c17f 100644 (file)
@@ -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);
index c8061bbc6b82ff07f54fa85e6470e041f97d3191..5d50f8542f92af2b206a26e55f16f87e8bca3dcc 100644 (file)
@@ -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);
index 8156822f62688ebe1d072a9b27f7e48449f0bbfb..8a9c3e2956373d80d6a15ee6ad34c14594803737 100644 (file)
@@ -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)
index 628a445a58eff2923fa0002159b4004b197b3b7a..bc33efc7fbdc30e742a5786fe976e94f0e734090 100644 (file)
@@ -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:
index 8bd51c80a207148089e65517b3fe4261273de2a3..d17ef6433e1ae8e74c5c773e2cab9e54b0c08572 100644 (file)
@@ -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));
 }
 \f
 /* 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
index 74d9ae55af268f0aab276b3d566b2982baf512d7..8966bf5d9216288594db84a4afb61ebe44a0be82 100644 (file)
@@ -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);
 }
 
index 927b3de0dea4abcb3f66aee55cb397cd047b28eb..027f1c9b1f2fdd850a7d0fff33b904ab94d4391e 100644 (file)
@@ -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;
 
index 036f93efecb4c5b47098b7a72842a6da0b910bea..2e8151b1ff3298604c4bbd6fa261faa62f3be59a 100644 (file)
@@ -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);
 }
 \f
 /* 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,8 +2412,16 @@ 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;
 
@@ -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);
   }
 }
 \f
@@ -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,8 +2787,15 @@ 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;
@@ -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;
 }
 \f
+/* 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);
 }
 \f
 /* 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;
index c48a7852609ee57899e48854f6c8712b9d97e9a8..4fdb07ff0b9854d06bf3ecc0786699d0a8b8a183 100644 (file)
@@ -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;
index 05e9c267e869203e3639d94aa636fe8422befeaf..4adfe1d69473b90942d7f0dc9b3af7136a9bb235 100644 (file)
@@ -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 (file)
index 0000000..e0680db
--- /dev/null
@@ -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 (file)
index 0000000..a813055
--- /dev/null
@@ -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 (file)
index 0000000..c51211b
--- /dev/null
@@ -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 (file)
index 0000000..b659685
--- /dev/null
@@ -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 (file)
index 0000000..93eba43
--- /dev/null
@@ -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 (file)
index 0000000..a965051
--- /dev/null
@@ -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 (file)
index 0000000..516e5cc
--- /dev/null
@@ -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 (file)
index 0000000..64567aa
--- /dev/null
@@ -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 (file)
index 0000000..2df4ade
--- /dev/null
@@ -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 (file)
index 0000000..8551eb2
--- /dev/null
@@ -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 (file)
index 0000000..2ad68dc
--- /dev/null
@@ -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 (file)
index 0000000..4e27ff6
--- /dev/null
@@ -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));