OSDN Git Service

Fix PR c++/40239
[pf3gnuchains/gcc-fork.git] / gcc / cp / typeck2.c
index c1fea0c..444ba73 100644 (file)
@@ -1,7 +1,7 @@
 /* Report error messages, build initializers, and perform
    some front-end optimizations for C++ compiler.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
@@ -32,11 +32,13 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "intl.h"
 #include "cp-tree.h"
 #include "flags.h"
 #include "toplev.h"
 #include "output.h"
 #include "diagnostic.h"
+#include "real.h"
 
 static tree
 process_init_constructor (tree type, tree init);
@@ -70,49 +72,143 @@ binfo_or_else (tree base, tree type)
    value may not be changed thereafter.  */
 
 void
-readonly_error (tree arg, const char* string)
+readonly_error (tree arg, readonly_error_kind errstring)
 {
-  const char *fmt;
+/* This macro is used to emit diagnostics to ensure that all format
+   strings are complete sentences, visible to gettext and checked at
+   compile time.  */
+#define ERROR_FOR_ASSIGNMENT(AS, ASM, IN, DE, ARG)                      \
+  do {                                                                  \
+    switch (errstring)                                                  \
+      {                                                                 \
+      case REK_ASSIGNMENT:                                              \
+        error(AS, ARG);                                                 \
+        break;                                                          \
+      case REK_ASSIGNMENT_ASM:                                          \
+        error(ASM, ARG);                                                \
+        break;                                                          \
+      case REK_INCREMENT:                                               \
+        error (IN, ARG);                                                \
+        break;                                                          \
+      case REK_DECREMENT:                                               \
+        error (DE, ARG);                                                \
+        break;                                                          \
+      default:                                                          \
+        gcc_unreachable ();                                             \
+      }                                                                 \
+  } while (0)
 
   if (TREE_CODE (arg) == COMPONENT_REF)
     {
       if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
-       fmt = "%s of data-member %qD in read-only structure";
+        ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                                 "data-member %qD in read-only structure"),
+                              G_("assignment (via 'asm' output) of "
+                                 "data-member %qD in read-only structure"),
+                              G_("increment of "
+                                 "data-member %qD in read-only structure"),
+                              G_("decrement of "
+                                 "data-member %qD in read-only structure"),
+                              TREE_OPERAND (arg, 1));
       else
-       fmt = "%s of read-only data-member %qD";
-      error (fmt, string, TREE_OPERAND (arg, 1));
+        ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                                 "read-only data-member %qD"),
+                              G_("assignment (via 'asm' output) of "
+                                 "read-only data-member %qD"),
+                              G_("increment of "
+                                 "read-only data-member %qD"),
+                              G_("decrement of "
+                                 "read-only data-member %qD"),
+                              TREE_OPERAND (arg, 1));
     }
   else if (TREE_CODE (arg) == VAR_DECL)
     {
       if (DECL_LANG_SPECIFIC (arg)
          && DECL_IN_AGGR_P (arg)
          && !TREE_STATIC (arg))
-       fmt = "%s of constant field %qD";
+        ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                              "constant field %qD"),
+                              G_("assignment (via 'asm' output) of "
+                              "constant field %qD"),
+                              G_("increment of "
+                              "constant field %qD"),
+                              G_("decrement of "
+                              "constant field %qD"),
+                              arg);
       else
-       fmt = "%s of read-only variable %qD";
-      error (fmt, string, arg);
+        ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                              "read-only variable %qD"),
+                              G_("assignment (via 'asm' output) of "
+                              "read-only variable %qD"),
+                              G_("increment of "
+                              "read-only variable %qD"),
+                              G_("decrement of "
+                              "read-only variable %qD"),
+                              arg);
+
     }
   else if (TREE_CODE (arg) == PARM_DECL)
-    error ("%s of read-only parameter %qD", string, arg);
+    ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                             "read-only parameter %qD"),
+                          G_("assignment (via 'asm' output) of "
+                             "read-only parameter %qD"),
+                          G_("increment of "
+                             "read-only parameter %qD"),
+                          G_("decrement of "
+                             "read-only parameter %qD"),
+                          arg);  
   else if (TREE_CODE (arg) == INDIRECT_REF
           && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE
           && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL
               || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL))
-    error ("%s of read-only reference %qD", string, TREE_OPERAND (arg, 0));
+    ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                             "read-only reference %qD"),
+                          G_("assignment (via 'asm' output) of "
+                             "read-only reference %qD"), 
+                          G_("increment of "
+                             "read-only reference %qD"),
+                          G_("decrement of "
+                             "read-only reference %qD"),
+                          TREE_OPERAND (arg, 0));
   else if (TREE_CODE (arg) == RESULT_DECL)
-    error ("%s of read-only named return value %qD", string, arg);
+    ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                             "read-only named return value %qD"),
+                          G_("assignment (via 'asm' output) of "
+                             "read-only named return value %qD"),
+                          G_("increment of "
+                             "read-only named return value %qD"),
+                          G_("decrement of "
+                             "read-only named return value %qD"),
+                          arg);
   else if (TREE_CODE (arg) == FUNCTION_DECL)
-    error ("%s of function %qD", string, arg);
+    ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                             "function %qD"),
+                          G_("assignment (via 'asm' output) of "
+                             "function %qD"),
+                          G_("increment of "
+                             "function %qD"),
+                          G_("decrement of "
+                             "function %qD"),
+                          arg);
   else
-    error ("%s of read-only location %qE", string, arg);
+    ERROR_FOR_ASSIGNMENT (G_("assignment of "
+                             "read-only location %qE"),
+                          G_("assignment (via 'asm' output) of "
+                             "read-only location %qE"),
+                          G_("increment of "
+                             "read-only location %qE"),
+                          G_("decrement of "
+                             "read-only location %qE"),
+                          arg);
 }
 
 \f
 /* Structure that holds information about declarations whose type was
    incomplete and we could not check whether it was abstract or not.  */
 
-struct pending_abstract_type GTY((chain_next ("%h.next")))
-{
+struct GTY((chain_next ("%h.next"))) pending_abstract_type {
   /* Declaration which we are checking for abstractness. It is either
      a DECL node, or an IDENTIFIER_NODE if we do not have a full
      declaration available.  */
@@ -236,6 +332,7 @@ abstract_virtuals_error (tree decl, tree type)
      be abstract.  */
   if (!CLASS_TYPE_P (type))
     return 0;
+  type = TYPE_MAIN_VARIANT (type);
 
   /* If the type is incomplete, we register it within a hash table,
      so that we can check again once it is completed. This makes sense
@@ -312,41 +409,39 @@ abstract_virtuals_error (tree decl, tree type)
       unsigned ix;
       tree fn;
 
-      inform ("%J  because the following virtual functions are pure "
-             "within %qT:", TYPE_MAIN_DECL (type), type);
+      inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+             "  because the following virtual functions are pure within %qT:",
+             type);
 
       for (ix = 0; VEC_iterate (tree, pure, ix, fn); ix++)
-       inform ("\t%+#D", fn);
+       inform (input_location, "\t%+#D", fn);
       /* Now truncate the vector.  This leaves it non-null, so we know
         there are pure virtuals, but empty so we don't list them out
         again.  */
       VEC_truncate (tree, pure, 0);
     }
   else
-    inform ("%J  since type %qT has pure virtual functions",
-           TYPE_MAIN_DECL (type), type);
+    inform (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+           "  since type %qT has pure virtual functions",
+           type);
 
   return 1;
 }
 
 /* Print an error message for invalid use of an incomplete type.
    VALUE is the expression that was used (or 0 if that isn't known)
-   and TYPE is the type that was invalid.  DIAG_TYPE indicates the
-   type of diagnostic:  0 for an error, 1 for a warning, 2 for a
-   pedwarn.  */
+   and TYPE is the type that was invalid.  DIAG_KIND indicates the
+   type of diagnostic (see diagnostic.def).  */
 
 void
-cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type)
+cxx_incomplete_type_diagnostic (const_tree value, const_tree type, 
+                               diagnostic_t diag_kind)
 {
   int decl = 0;
-  void (*p_msg) (const char *, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
 
-  if (diag_type == 1)
-    p_msg = warning0;
-  else if (diag_type == 2)
-    p_msg = pedwarn;
-  else
-    p_msg = error;
+  gcc_assert (diag_kind == DK_WARNING 
+             || diag_kind == DK_PEDWARN 
+             || diag_kind == DK_ERROR);
 
   /* Avoid duplicate error message.  */
   if (TREE_CODE (type) == ERROR_MARK)
@@ -356,7 +451,8 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type
                     || TREE_CODE (value) == PARM_DECL
                     || TREE_CODE (value) == FIELD_DECL))
     {
-      p_msg ("%q+D has incomplete type", value);
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "%q+D has incomplete type", value);
       decl = 1;
     }
  retry:
@@ -368,15 +464,19 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type
     case UNION_TYPE:
     case ENUMERAL_TYPE:
       if (!decl)
-       p_msg ("invalid use of incomplete type %q#T", type);
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "invalid use of incomplete type %q#T", type);
       if (!TYPE_TEMPLATE_INFO (type))
-       p_msg ("forward declaration of %q+#T", type);
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "forward declaration of %q+#T", type);
       else
-       p_msg ("declaration of %q+#T", type);
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "declaration of %q+#T", type);
       break;
 
     case VOID_TYPE:
-      p_msg ("invalid use of %qT", type);
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "invalid use of %qT", type);
       break;
 
     case ARRAY_TYPE:
@@ -385,37 +485,49 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type
          type = TREE_TYPE (type);
          goto retry;
        }
-      p_msg ("invalid use of array with unspecified bounds");
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "invalid use of array with unspecified bounds");
       break;
 
     case OFFSET_TYPE:
     bad_member:
-      p_msg ("invalid use of member (did you forget the %<&%> ?)");
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "invalid use of member (did you forget the %<&%> ?)");
       break;
 
     case TEMPLATE_TYPE_PARM:
-      p_msg ("invalid use of template type parameter %qT", type);
+      if (is_auto (type))
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "invalid use of %<auto%>");
+      else
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "invalid use of template type parameter %qT", type);
       break;
 
     case BOUND_TEMPLATE_TEMPLATE_PARM:
-      p_msg ("invalid use of template template parameter %qT",
-            TYPE_NAME (type));
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "invalid use of template template parameter %qT",
+                      TYPE_NAME (type));
       break;
 
     case TYPENAME_TYPE:
-      p_msg ("invalid use of dependent type %qT", type);
+      emit_diagnostic (diag_kind, input_location, 0,
+                      "invalid use of dependent type %qT", type);
       break;
 
     case UNKNOWN_TYPE:
       if (value && TREE_CODE (value) == COMPONENT_REF)
        goto bad_member;
       else if (value && TREE_CODE (value) == ADDR_EXPR)
-       p_msg ("address of overloaded function with no contextual "
-              "type information");
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "address of overloaded function with no contextual "
+                        "type information");
       else if (value && TREE_CODE (value) == OVERLOAD)
-       p_msg ("overloaded function with no contextual type information");
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "overloaded function with no contextual type information");
       else
-       p_msg ("insufficient contextual information to determine type");
+       emit_diagnostic (diag_kind, input_location, 0,
+                        "insufficient contextual information to determine type");
       break;
 
     default:
@@ -429,7 +541,7 @@ cxx_incomplete_type_diagnostic (const_tree value, const_tree type, int diag_type
 void
 cxx_incomplete_type_error (const_tree value, const_tree type)
 {
-  cxx_incomplete_type_diagnostic (value, type, 0);
+  cxx_incomplete_type_diagnostic (value, type, DK_ERROR);
 }
 
 \f
@@ -437,13 +549,15 @@ cxx_incomplete_type_error (const_tree value, const_tree type)
    expression to which INIT should be assigned.  INIT is a CONSTRUCTOR.  */
 
 static void
-split_nonconstant_init_1 (tree dest, tree init)
+split_nonconstant_init_1 (tree dest, tree *initp)
 {
   unsigned HOST_WIDE_INT idx;
+  tree init = *initp;
   tree field_index, value;
   tree type = TREE_TYPE (dest);
   tree inner_type = NULL;
   bool array_type_p = false;
+  HOST_WIDE_INT num_type_elements, num_initialized_elements;
 
   switch (TREE_CODE (type))
     {
@@ -455,6 +569,7 @@ split_nonconstant_init_1 (tree dest, tree init)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
+      num_initialized_elements = 0;
       FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx,
                                field_index, value)
        {
@@ -477,12 +592,13 @@ split_nonconstant_init_1 (tree dest, tree init)
                sub = build3 (COMPONENT_REF, inner_type, dest, field_index,
                              NULL_TREE);
 
-             split_nonconstant_init_1 (sub, value);
+             split_nonconstant_init_1 (sub, &value);
            }
          else if (!initializer_constant_valid_p (value, inner_type))
            {
              tree code;
              tree sub;
+             HOST_WIDE_INT inner_elements;
 
              /* FIXME: Ordered removal is O(1) so the whole function is
                 worst-case quadratic. This could be fixed using an aside
@@ -503,11 +619,24 @@ split_nonconstant_init_1 (tree dest, tree init)
                              NULL_TREE);
 
              code = build2 (INIT_EXPR, inner_type, sub, value);
-             code = build_stmt (EXPR_STMT, code);
+             code = build_stmt (input_location, EXPR_STMT, code);
              add_stmt (code);
+
+             inner_elements = count_type_elements (inner_type, true);
+             if (inner_elements < 0)
+               num_initialized_elements = -1;
+             else if (num_initialized_elements >= 0)
+               num_initialized_elements += inner_elements;
              continue;
            }
        }
+
+      num_type_elements = count_type_elements (type, true);
+      /* If all elements of the initializer are non-constant and
+        have been split out, we don't need the empty CONSTRUCTOR.  */
+      if (num_type_elements > 0
+         && num_type_elements == num_initialized_elements)
+       *initp = NULL;
       break;
 
     case VECTOR_TYPE:
@@ -517,7 +646,7 @@ split_nonconstant_init_1 (tree dest, tree init)
          tree cons = copy_node (init);
          CONSTRUCTOR_ELTS (init) = NULL;
          code = build2 (MODIFY_EXPR, type, dest, cons);
-         code = build_stmt (EXPR_STMT, code);
+         code = build_stmt (input_location, EXPR_STMT, code);
          add_stmt (code);
        }
       break;
@@ -543,7 +672,7 @@ split_nonconstant_init (tree dest, tree init)
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
       code = push_stmt_list ();
-      split_nonconstant_init_1 (dest, init);
+      split_nonconstant_init_1 (dest, &init);
       code = pop_stmt_list (code);
       DECL_INITIAL (dest) = init;
       TREE_READONLY (dest) = 0;
@@ -573,7 +702,7 @@ split_nonconstant_init (tree dest, tree init)
    for static variable.  In that case, caller must emit the code.  */
 
 tree
-store_init_value (tree decl, tree init)
+store_init_value (tree decl, tree init, int flags)
 {
   tree value, type;
 
@@ -592,7 +721,7 @@ store_init_value (tree decl, tree init)
        {
          error ("constructor syntax used, but no constructor declared "
                 "for type %qT", type);
-         init = build_constructor_from_list (NULL_TREE, nreverse (init));
+         init = build_constructor_from_list (init_list_type_node, nreverse (init));
        }
     }
   else if (TREE_CODE (init) == TREE_LIST
@@ -615,7 +744,7 @@ store_init_value (tree decl, tree init)
   /* End of special C++ code.  */
 
   /* Digest the specified initializer into an expression.  */
-  value = digest_init (type, init);
+  value = digest_init_flags (type, init, flags);
   /* If the initializer is not a constant, fill in DECL_INITIAL with
      the bits that are constant, and then return an expression that
      will perform the dynamic initialization.  */
@@ -631,19 +760,80 @@ store_init_value (tree decl, tree init)
 }
 
 \f
+/* Give errors about narrowing conversions within { }.  */
+
+void
+check_narrowing (tree type, tree init)
+{
+  tree ftype = unlowered_expr_type (init);
+  bool ok = true;
+  REAL_VALUE_TYPE d;
+
+  if (DECL_P (init))
+    init = decl_constant_value (init);
+
+  if (TREE_CODE (type) == INTEGER_TYPE
+      && TREE_CODE (ftype) == REAL_TYPE)
+    ok = false;
+  else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
+          && CP_INTEGRAL_TYPE_P (type))
+    {
+      if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)
+         && (TREE_CODE (init) != INTEGER_CST
+             || !int_fits_type_p (init, type)))
+       ok = false;
+    }
+  else if (TREE_CODE (ftype) == REAL_TYPE
+          && TREE_CODE (type) == REAL_TYPE)
+    {
+      if (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))
+       {
+         if (TREE_CODE (init) == REAL_CST)
+           {
+             /* Issue 703: Loss of precision is OK as long as the value is
+                within the representable range of the new type.  */
+             REAL_VALUE_TYPE r;
+             d = TREE_REAL_CST (init);
+             real_convert (&r, TYPE_MODE (type), &d);
+             if (real_isinf (&r))
+               ok = false;
+           }
+         else
+           ok = false;
+       }
+    }
+  else if (INTEGRAL_OR_ENUMERATION_TYPE_P (ftype)
+          && TREE_CODE (type) == REAL_TYPE)
+    {
+      ok = false;
+      if (TREE_CODE (init) == INTEGER_CST)
+       {
+         d = real_value_from_int_cst (0, init);
+         if (exact_real_truncate (TYPE_MODE (type), &d))
+           ok = true;
+       }
+    }
+
+  if (!ok)
+    permerror (input_location, "narrowing conversion of %qE from %qT to %qT inside { }",
+              init, ftype, type);
+}
+
 /* Process the initializer INIT for a variable of type TYPE, emitting
    diagnostics for invalid initializers and converting the initializer as
    appropriate.
 
    For aggregate types, it assumes that reshape_init has already run, thus the
-   initializer will have the right shape (brace elision has been undone).  */
+   initializer will have the right shape (brace elision has been undone).
 
-tree
-digest_init (tree type, tree init)
+   NESTED is true iff we are being called for an element of a CONSTRUCTOR.  */
+
+static tree
+digest_init_r (tree type, tree init, bool nested, int flags)
 {
   enum tree_code code = TREE_CODE (type);
 
-  if (init == error_mark_node)
+  if (error_operand_p (init))
     return error_mark_node;
 
   gcc_assert (init);
@@ -671,17 +861,26 @@ digest_init (tree type, tree init)
        {
          tree char_type = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (init)));
 
-         if (char_type != char_type_node
-             && TYPE_PRECISION (typ1) == BITS_PER_UNIT)
+         if (TYPE_PRECISION (typ1) == BITS_PER_UNIT)
            {
-             error ("char-array initialized from wide string");
-             return error_mark_node;
+             if (char_type != char_type_node)
+               {
+                 error ("char-array initialized from wide string");
+                 return error_mark_node;
+               }
            }
-         if (char_type == char_type_node
-             && TYPE_PRECISION (typ1) != BITS_PER_UNIT)
+         else
            {
-             error ("int-array initialized from non-wide string");
-             return error_mark_node;
+             if (char_type == char_type_node)
+               {
+                 error ("int-array initialized from non-wide string");
+                 return error_mark_node;
+               }
+             else if (char_type != typ1)
+               {
+                 error ("int-array initialized from incompatible wide string");
+                 return error_mark_node;
+               }
            }
 
          TREE_TYPE (init) = type;
@@ -694,21 +893,24 @@ digest_init (tree type, tree init)
                 counted in the length of the constant, but in C++ this would
                 be invalid.  */
              if (size < TREE_STRING_LENGTH (init))
-               pedwarn ("initializer-string for array of chars is too long");
+               permerror (input_location, "initializer-string for array of chars is too long");
            }
          return init;
        }
     }
 
   /* Handle scalar types (including conversions) and references.  */
-  if (TREE_CODE (type) != COMPLEX_TYPE
+  if ((TREE_CODE (type) != COMPLEX_TYPE
+       || BRACE_ENCLOSED_INITIALIZER_P (init))
       && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE))
     {
       tree *exp;
 
-      init = convert_for_initialization (0, type, init, LOOKUP_NORMAL,
+      if (cxx_dialect != cxx98 && nested)
+       check_narrowing (type, init);
+      init = convert_for_initialization (0, type, init, flags,
                                         "initialization", NULL_TREE, 0,
-                                         tf_warning_or_error);
+                                        tf_warning_or_error);
       exp = &init;
 
       /* Skip any conversions since we'll be outputting the underlying
@@ -730,8 +932,9 @@ digest_init (tree type, tree init)
              || TREE_CODE (type) == UNION_TYPE
              || TREE_CODE (type) == COMPLEX_TYPE);
 
-  if (BRACE_ENCLOSED_INITIALIZER_P (init))
-      return process_init_constructor (type, init);
+  if (BRACE_ENCLOSED_INITIALIZER_P (init)
+      && !TYPE_NON_AGGREGATE_CLASS (type))
+    return process_init_constructor (type, init);
   else
     {
       if (COMPOUND_LITERAL_P (init) && TREE_CODE (type) == ARRAY_TYPE)
@@ -743,20 +946,39 @@ digest_init (tree type, tree init)
        }
 
       if (TREE_CODE (type) == ARRAY_TYPE
-         && TREE_CODE (init) != CONSTRUCTOR)
+         && !BRACE_ENCLOSED_INITIALIZER_P (init))
        {
+         /* Allow the result of build_array_copy and of
+            build_value_init_noctor.  */
+         if ((TREE_CODE (init) == TARGET_EXPR
+              || TREE_CODE (init) == CONSTRUCTOR)
+             && (same_type_ignoring_top_level_qualifiers_p
+                 (type, TREE_TYPE (init))))
+           return init;
+
          error ("array must be initialized with a brace-enclosed"
                 " initializer");
          return error_mark_node;
        }
 
       return convert_for_initialization (NULL_TREE, type, init,
-                                        LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
+                                        flags,
                                         "initialization", NULL_TREE, 0,
                                          tf_warning_or_error);
     }
 }
 
+tree
+digest_init (tree type, tree init)
+{
+  return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
+}
+
+tree
+digest_init_flags (tree type, tree init, int flags)
+{
+  return digest_init_r (type, init, false, flags);
+}
 \f
 /* Set of flags used within process_init_constructor to describe the
    initializers.  */
@@ -809,10 +1031,9 @@ process_init_constructor_array (tree type, tree init)
     /* Vectors are like simple fixed-size arrays.  */
     len = TYPE_VECTOR_SUBPARTS (type);
 
-  /* There cannot be more initializers than needed as otherwise
-     reshape_init would have already rejected the initializer.  */
-  if (!unbounded)
-    gcc_assert (VEC_length (constructor_elt, v) <= len);
+  /* There must not be more initializers than needed.  */
+  if (!unbounded && VEC_length (constructor_elt, v)  > len)
+    error ("too many initializers for %qT", type);
 
   for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
     {
@@ -828,7 +1049,7 @@ process_init_constructor_array (tree type, tree init)
       else
        ce->index = size_int (i);
       gcc_assert (ce->value);
-      ce->value = digest_init (TREE_TYPE (type), ce->value);
+      ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
 
       if (ce->value != error_mark_node)
        gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -854,7 +1075,7 @@ process_init_constructor_array (tree type, tree init)
               next = build_functional_cast (TREE_TYPE (type), NULL_TREE,
                                             tf_warning_or_error);
            else
-               next = build_constructor (NULL_TREE, NULL);
+             next = build_constructor (init_list_type_node, NULL);
            next = digest_init (TREE_TYPE (type), next);
          }
        else if (!zero_init_p (TREE_TYPE (type)))
@@ -898,6 +1119,7 @@ process_init_constructor_record (tree type, tree init)
   for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
     {
       tree next;
+      tree type;
 
       if (!DECL_NAME (field) && DECL_C_BIT_FIELD (field))
        {
@@ -909,6 +1131,11 @@ process_init_constructor_record (tree type, tree init)
       if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
        continue;
 
+      /* If this is a bitfield, first convert to the declared type.  */
+      type = TREE_TYPE (field);
+      if (DECL_BIT_FIELD_TYPE (field))
+       type = DECL_BIT_FIELD_TYPE (field);
+
       if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
        {
          constructor_elt *ce = VEC_index (constructor_elt,
@@ -929,7 +1156,7 @@ process_init_constructor_record (tree type, tree init)
            }
 
          gcc_assert (ce->value);
-         next = digest_init (TREE_TYPE (field), ce->value);
+         next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
          ++idx;
        }
       else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
@@ -939,12 +1166,18 @@ 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,
-                                          tf_warning_or_error);
+           {
+             next = build_functional_cast (TREE_TYPE (field), NULL_TREE,
+                                           tf_warning_or_error);
+             /* direct-initialize the target. No temporary is going
+                 to be involved.  */
+             if (TREE_CODE (next) == TARGET_EXPR)
+               TARGET_EXPR_DIRECT_INIT_P (next) = true;
+           }
          else
-           next = build_constructor (NULL_TREE, NULL);
+           next = build_constructor (init_list_type_node, NULL);
 
-         next = digest_init (TREE_TYPE (field), next);
+         next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
 
          /* Warn when some struct elements are implicitly initialized.  */
          warning (OPT_Wmissing_field_initializers,
@@ -973,10 +1206,16 @@ process_init_constructor_record (tree type, tree init)
            continue;
        }
 
+      /* If this is a bitfield, now convert to the lowered type.  */
+      if (type != TREE_TYPE (field))
+       next = cp_convert_and_check (TREE_TYPE (field), next);
       flags |= picflag_from_initializer (next);
       CONSTRUCTOR_APPEND_ELT (v, field, next);
     }
 
+  if (idx < VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)))
+    error ("too many initializers for %qT", type);
+    
   CONSTRUCTOR_ELTS (init) = v;
   return flags;
 }
@@ -989,12 +1228,19 @@ static int
 process_init_constructor_union (tree type, tree init)
 {
   constructor_elt *ce;
+  int len;
 
   /* If the initializer was empty, use default zero initialization.  */
   if (VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (init)))
     return 0;
 
-  gcc_assert (VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init)) == 1);
+  len = VEC_length (constructor_elt, CONSTRUCTOR_ELTS (init));
+  if (len > 1)
+    {
+      error ("too many initializers for %qT", type);
+      VEC_block_remove (constructor_elt, CONSTRUCTOR_ELTS (init), 1, len-1);
+    }
+
   ce = VEC_index (constructor_elt, CONSTRUCTOR_ELTS (init), 0);
 
   /* If this element specifies a field, initialize via that field.  */
@@ -1032,12 +1278,16 @@ process_init_constructor_union (tree type, tree init)
       tree field = TYPE_FIELDS (type);
       while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
        field = TREE_CHAIN (field);
-      gcc_assert (field);
+      if (field == NULL_TREE)
+       {
+         error ("too many initializers for %qT", type);
+         ce->value = error_mark_node;
+       }
       ce->index = field;
     }
 
   if (ce->value && ce->value != error_mark_node)
-    ce->value = digest_init (TREE_TYPE (ce->index), ce->value);
+    ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, LOOKUP_IMPLICIT);
 
   return picflag_from_initializer (ce->value);
 }
@@ -1209,7 +1459,7 @@ build_x_arrow (tree expr)
          return expr;
        }
 
-      return cp_build_indirect_ref (last_rval, NULL, tf_warning_or_error);
+      return cp_build_indirect_ref (last_rval, RO_NULL, tf_warning_or_error);
     }
 
   if (types_memoized)
@@ -1301,7 +1551,7 @@ build_m_component_ref (tree datum, tree component)
       datum = build2 (POINTER_PLUS_EXPR, ptype,
                      fold_convert (ptype, datum),
                      build_nop (sizetype, component));
-      return cp_build_indirect_ref (datum, 0, tf_warning_or_error);
+      return cp_build_indirect_ref (datum, RO_NULL, tf_warning_or_error);
     }
   else
     return build2 (OFFSET_REF, type, datum, component);
@@ -1317,6 +1567,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
 
   /* The type to which we are casting.  */
   tree type;
+  VEC(tree,gc) *parmvec;
 
   if (exp == error_mark_node || parms == error_mark_node)
     return error_mark_node;
@@ -1326,6 +1577,12 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
   else
     type = exp;
 
+  if (TREE_CODE (type) == REFERENCE_TYPE && !parms)
+    {
+      error ("invalid value-initialization of reference types");
+      return error_mark_node;
+    }
+
   if (processing_template_decl)
     {
       tree t = build_min (CAST_EXPR, type, parms);
@@ -1381,8 +1638,12 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
     }
 
   /* Call the constructor.  */
-  exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
-                                  type, LOOKUP_NORMAL, complain);
+  parmvec = make_tree_vector ();
+  for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
+    VEC_safe_push (tree, gc, parmvec, TREE_VALUE (parms));
+  exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+                                  &parmvec, type, LOOKUP_NORMAL, complain);
+  release_tree_vector (parmvec);
 
   if (exp == error_mark_node)
     return error_mark_node;
@@ -1402,7 +1663,7 @@ add_exception_specifier (tree list, tree spec, int complain)
   bool ok;
   tree core = spec;
   bool is_ptr;
-  int diag_type = -1; /* none */
+  diagnostic_t diag_type = DK_UNSPECIFIED; /* none */
 
   if (spec == error_mark_node)
     return list;
@@ -1431,7 +1692,7 @@ add_exception_specifier (tree list, tree spec, int complain)
         and calls.  So just give a pedwarn at this point; we will give an
         error later if we hit one of those two cases.  */
       if (!COMPLETE_TYPE_P (complete_type (core)))
-       diag_type = 2; /* pedwarn */
+       diag_type = DK_PEDWARN; /* pedwarn */
     }
 
   if (ok)
@@ -1445,9 +1706,9 @@ add_exception_specifier (tree list, tree spec, int complain)
        list = tree_cons (NULL_TREE, spec, list);
     }
   else
-    diag_type = 0; /* error */
+    diag_type = DK_ERROR; /* error */
 
-  if (diag_type >= 0 && complain)
+  if (diag_type != DK_UNSPECIFIED && complain)
     cxx_incomplete_type_diagnostic (NULL_TREE, core, diag_type);
 
   return list;