]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/init.c
typeck.c (composite_pointer_type_r): Add SFINAE support.
[thirdparty/gcc.git] / gcc / cp / init.c
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);