OSDN Git Service

2007-02-15 Sandra Loosemore <sandra@codesourcery.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index bc6df20..1ca0798 100644 (file)
@@ -178,7 +178,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
        items with static storage duration that are not otherwise
        initialized are initialized to zero.  */
     ;
-  else if (SCALAR_TYPE_P (type))
+  else if (SCALAR_TYPE_P (type)
+          || TREE_CODE (type) == COMPLEX_TYPE)
     init = convert (type, integer_zero_node);
   else if (CLASS_TYPE_P (type))
     {
@@ -222,6 +223,11 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
                                 nelts, integer_one_node);
       else
        max_index = array_type_nelts (type);
+
+      /* If we have an error_mark here, we should just return error mark
+        as we don't know the size of the array yet.  */
+      if (max_index == error_mark_node)
+       return error_mark_node;
       gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
 
       /* A zero-sized array, which is accepted as an extension, will
@@ -248,6 +254,8 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
       /* Build a constructor to contain the initializations.  */
       init = build_constructor (type, v);
     }
+  else if (TREE_CODE (type) == VECTOR_TYPE)
+    init = fold_convert (type, integer_zero_node);
   else
     gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
 
@@ -855,7 +863,7 @@ construct_virtual_base (tree vbase, tree arguments)
      confuses the sjlj exception-handling code.  Therefore, we do not
      create a single conditional block, but one for each
      initialization.  (That way the cleanup regions always begin
-     in the outer block.)  We trust the back-end to figure out
+     in the outer block.)  We trust the back end to figure out
      that the FLAG will not change across initializations, and
      avoid doing multiple tests.  */
   flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
@@ -1142,26 +1150,6 @@ build_aggr_init (tree exp, tree init, int flags)
   return stmt_expr;
 }
 
-/* Like build_aggr_init, but not just for aggregates.  */
-
-tree
-build_init (tree decl, tree init, int flags)
-{
-  tree expr;
-
-  if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
-    expr = build_aggr_init (decl, init, flags);
-  else if (CLASS_TYPE_P (TREE_TYPE (decl)))
-    expr = build_special_member_call (decl, complete_ctor_identifier,
-                                     build_tree_list (NULL_TREE, init),
-                                     TREE_TYPE (decl),
-                                     LOOKUP_NORMAL|flags);
-  else
-    expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
-
-  return expr;
-}
-
 static void
 expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
 {
@@ -1340,7 +1328,7 @@ build_offset_ref (tree type, tree member, bool address_p)
     return member;
 
   if (dependent_type_p (type) || type_dependent_expression_p (member))
-    return build_qualified_name (NULL_TREE, type, member, 
+    return build_qualified_name (NULL_TREE, type, member,
                                 /*template_p=*/false);
 
   gcc_assert (TYPE_P (type));
@@ -1359,7 +1347,7 @@ build_offset_ref (tree type, tree member, bool address_p)
     }
 
   /* Entities other than non-static members need no further
-     processing.  */ 
+     processing.  */
   if (TREE_CODE (member) == TYPE_DECL)
     return member;
   if (TREE_CODE (member) == VAR_DECL || TREE_CODE (member) == CONST_DECL)
@@ -1395,9 +1383,9 @@ build_offset_ref (tree type, tree member, bool address_p)
               (or any class derived from that class).  */
          if (address_p && DECL_P (t)
              && DECL_NONSTATIC_MEMBER_P (t))
-           perform_or_defer_access_check (TYPE_BINFO (type), t);
+           perform_or_defer_access_check (TYPE_BINFO (type), t, t);
          else
-           perform_or_defer_access_check (basebinfo, t);
+           perform_or_defer_access_check (basebinfo, t, t);
 
          if (DECL_STATIC_FUNCTION_P (t))
            return t;
@@ -1410,7 +1398,7 @@ build_offset_ref (tree type, tree member, bool address_p)
     /* We need additional test besides the one in
        check_accessibility_of_qualified_id in case it is
        a pointer to non-static member.  */
-    perform_or_defer_access_check (TYPE_BINFO (type), member);
+    perform_or_defer_access_check (TYPE_BINFO (type), member, member);
 
   if (!address_p)
     {
@@ -1446,7 +1434,7 @@ build_offset_ref (tree type, tree member, bool address_p)
            }
          error ("invalid use of non-static member function %qD",
                 TREE_OPERAND (member, 1));
-         return member;
+         return error_mark_node;
        }
       else if (TREE_CODE (member) == FIELD_DECL)
        {
@@ -1471,7 +1459,7 @@ static tree
 constant_value_1 (tree decl, bool integral_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
-        || (integral_p 
+        || (integral_p
             ? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
             : (TREE_CODE (decl) == VAR_DECL
                && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
@@ -1486,7 +1474,7 @@ constant_value_1 (tree decl, bool integral_p)
         instantiation time.  */
       if (DECL_CLASS_SCOPE_P (decl)
          && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))
-         && uses_template_parms (CLASSTYPE_TI_ARGS 
+         && uses_template_parms (CLASSTYPE_TI_ARGS
                                  (DECL_CONTEXT (decl))))
        {
          ++processing_template_decl;
@@ -1503,7 +1491,7 @@ constant_value_1 (tree decl, bool integral_p)
          init = DECL_INITIAL (decl);
        }
       if (init == error_mark_node)
-       return error_mark_node;
+       return decl;
       if (!init
          || !TREE_TYPE (init)
          || (integral_p
@@ -1534,13 +1522,13 @@ integral_constant_value (tree decl)
 }
 
 /* A more relaxed version of integral_constant_value, used by the
-   common C/C++ code and by the C++ front-end for optimization
+   common C/C++ code and by the C++ front end for optimization
    purposes.  */
 
 tree
 decl_constant_value (tree decl)
 {
-  return constant_value_1 (decl, 
+  return constant_value_1 (decl,
                           /*integral_p=*/processing_template_decl);
 }
 \f
@@ -1568,9 +1556,9 @@ build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
                    int use_global_new)
 {
   tree new_expr;
-  
-  new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type, 
-                    nelts, init); 
+
+  new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
+                    nelts, init);
   NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
   TREE_SIDE_EFFECTS (new_expr) = 1;
 
@@ -1585,7 +1573,6 @@ build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
 static tree
 build_new_1 (tree placement, tree type, tree nelts, tree init,
             bool globally_qualified_p)
-            
 {
   tree size, rval;
   /* True iff this is a call to "operator new[]" instead of just
@@ -1646,10 +1633,14 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
         function context.  Methinks that's not it's purvey.  So we'll do
         our own VLA layout later.  */
       vla_p = true;
-      full_type = build_cplus_array_type (type, NULL_TREE);
       index = convert (sizetype, nelts);
       index = size_binop (MINUS_EXPR, index, size_one_node);
-      TYPE_DOMAIN (full_type) = build_index_type (index);
+      index = build_index_type (index);
+      full_type = build_cplus_array_type (type, NULL_TREE);
+      /* We need a copy of the type as build_array_type will return a shared copy
+         of the incomplete array type.  */
+      full_type = build_distinct_type_copy (full_type);
+      TYPE_DOMAIN (full_type) = index;
     }
   else
     {
@@ -1717,6 +1708,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
       tree class_decl = build_java_class_ref (elt_type);
       static const char alloc_name[] = "_Jv_AllocObject";
 
+      if (class_decl == error_mark_node)
+       return error_mark_node;
+
       use_java_new = 1;
       if (!get_global_value_if_present (get_identifier (alloc_name),
                                        &alloc_fn))
@@ -1914,8 +1908,8 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
            = build_vec_init (init_expr,
                              cp_build_binary_op (MINUS_EXPR, outer_nelts,
                                                  integer_one_node),
-                             init, 
-                             explicit_default_init_p,
+                             init,
+                             explicit_default_init_p,
                              /*from_array=*/0);
 
          /* An array initialization is stable because the initialization
@@ -1940,14 +1934,14 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
            {
              /* We are processing something like `new int (10)', which
                 means allocate an int, and initialize it with 10.  */
-             
+
              if (TREE_CODE (init) == TREE_LIST)
-               init = build_x_compound_expr_from_list (init, 
+               init = build_x_compound_expr_from_list (init,
                                                        "new initializer");
              else
                gcc_assert (TREE_CODE (init) != CONSTRUCTOR
                            || TREE_TYPE (init) != NULL_TREE);
-             
+
              init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
              stable = stabilize_init (init_expr, &init_preeval_expr);
            }
@@ -2057,7 +2051,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
   rval = build_nop (pointer_type, rval);
 
   /* A new-expression is never an lvalue.  */
-  rval = rvalue (rval);
+  gcc_assert (!lvalue_p (rval));
 
   return rval;
 }
@@ -2081,7 +2075,8 @@ build_new (tree placement, tree type, tree nelts, tree init,
   tree orig_nelts;
   tree orig_init;
 
-  if (type == error_mark_node)
+  if (placement == error_mark_node || type == error_mark_node
+      || init == error_mark_node)
     return error_mark_node;
 
   orig_placement = placement;
@@ -2108,9 +2103,22 @@ build_new (tree placement, tree type, tree nelts, tree init,
     {
       if (!build_expr_type_conversion (WANT_INT | WANT_ENUM, nelts, false))
        pedwarn ("size in array new must have integral type");
-      nelts = save_expr (cp_convert (sizetype, nelts));
-      if (nelts == integer_zero_node)
-       warning (0, "zero size array reserves no space");
+      nelts = cp_save_expr (cp_convert (sizetype, nelts));
+      /* It is valid to allocate a zero-element array:
+
+          [expr.new]
+
+          When the value of the expression in a direct-new-declarator
+          is zero, the allocation function is called to allocate an
+          array with no elements.  The pointer returned by the
+          new-expression is non-null.  [Note: If the library allocation
+          function is called, the pointer returned is distinct from the
+          pointer to any other object.]
+
+        However, that is not generally useful, so we issue a
+        warning.  */
+      if (integer_zerop (nelts))
+       warning (0, "allocating zero-element array");
     }
 
   /* ``A reference cannot be created by the new operator.  A reference
@@ -2156,8 +2164,10 @@ build_java_class_ref (tree type)
     {
       jclass_node = IDENTIFIER_GLOBAL_VALUE (get_identifier ("jclass"));
       if (jclass_node == NULL_TREE)
-       fatal_error ("call to Java constructor, while %<jclass%> undefined");
-
+       {
+         error ("call to Java constructor, while %<jclass%> undefined");
+         return error_mark_node;
+       }
       jclass_node = TREE_TYPE (jclass_node);
     }
 
@@ -2172,8 +2182,11 @@ build_java_class_ref (tree type)
          break;
        }
     if (!field)
-      internal_error ("can't find class$");
-    }
+      {
+       error ("can't find %<class$%> in %qT", type);
+       return error_mark_node;
+      }
+  }
 
   class_decl = IDENTIFIER_GLOBAL_VALUE (name);
   if (class_decl == NULL_TREE)
@@ -2283,7 +2296,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
        deallocate_expr = build_op_delete_call (VEC_DELETE_EXPR,
                                                base_tbd, virtual_size,
                                                use_global_delete & 1,
-                                               /*placement=*/NULL_TREE, 
+                                               /*placement=*/NULL_TREE,
                                                /*alloc_fn=*/NULL_TREE);
     }
 
@@ -2377,7 +2390,7 @@ get_temp_regvar (tree type, tree init)
    but use assignment instead of initialization.  */
 
 tree
-build_vec_init (tree base, tree maxindex, tree init, 
+build_vec_init (tree base, tree maxindex, tree init,
                bool explicit_default_init_p,
                int from_array)
 {
@@ -2465,7 +2478,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      When copying from array to another, when the array elements have
      only trivial copy constructors, we should use __builtin_memcpy
      rather than generating a loop.  That way, we could take advantage
-     of whatever cleverness the back-end has for dealing with copies
+     of whatever cleverness the back end has for dealing with copies
      of blocks of memory.  */
 
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
@@ -2586,12 +2599,12 @@ build_vec_init (tree base, tree maxindex, tree init,
            sorry
              ("cannot initialize multi-dimensional array with initializer");
          elt_init = build_vec_init (build1 (INDIRECT_REF, type, base),
-                                    0, 0, 
+                                    0, 0,
                                     /*explicit_default_init_p=*/false,
                                     0);
        }
       else if (!TYPE_NEEDS_CONSTRUCTING (type))
-       elt_init = (build_modify_expr 
+       elt_init = (build_modify_expr
                    (to, INIT_EXPR,
                     build_zero_init (type, size_one_node,
                                      /*static_storage_p=*/false)));
@@ -2770,8 +2783,8 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
       if (auto_delete != sfk_deleting_destructor)
        return void_zero_node;
 
-      return build_op_delete_call (DELETE_EXPR, addr, 
-                                  cxx_sizeof_nowarn (type), 
+      return build_op_delete_call (DELETE_EXPR, addr,
+                                  cxx_sizeof_nowarn (type),
                                   use_global_delete,
                                   /*placement=*/NULL_TREE,
                                   /*alloc_fn=*/NULL_TREE);
@@ -2821,7 +2834,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          /* Make sure we have access to the member op delete, even though
             we'll actually be calling it from the destructor.  */
          build_op_delete_call (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-                               /*global_p=*/false, 
+                               /*global_p=*/false,
                                /*placement=*/NULL_TREE,
                                /*alloc_fn=*/NULL_TREE);
        }
@@ -2906,7 +2919,9 @@ push_base_cleanups (void)
   for (member = TYPE_FIELDS (current_class_type); member;
        member = TREE_CHAIN (member))
     {
-      if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
+      if (TREE_TYPE (member) == error_mark_node
+         || TREE_CODE (member) != FIELD_DECL
+         || DECL_ARTIFICIAL (member))
        continue;
       if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
        {