OSDN Git Service

2010-08-17 Kai Tietz <kai.tietz@onevision.com>
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 30808b2..8555fad 100644 (file)
@@ -184,7 +184,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
       VEC(constructor_elt,gc) *v = NULL;
 
       /* Iterate over the fields, building initializations.  */
-      for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
        {
          if (TREE_CODE (field) != FIELD_DECL)
            continue;
@@ -269,7 +269,7 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
    TYPE, as described in [dcl.init].  */
 
 tree
-build_value_init (tree type)
+build_value_init (tree type, tsubst_flags_t complain)
 {
   /* [dcl.init]
 
@@ -302,7 +302,7 @@ build_value_init (tree type)
          (type,
           build_special_member_call (NULL_TREE, complete_ctor_identifier,
                                      NULL, type, LOOKUP_NORMAL,
-                                     tf_warning_or_error));
+                                     complain));
       else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
        {
          /* This is a class that needs constructing, but doesn't have
@@ -311,21 +311,21 @@ build_value_init (tree type)
             This will be handled in simplify_aggr_init_expr.  */
          tree ctor = build_special_member_call
            (NULL_TREE, complete_ctor_identifier,
-            NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
+            NULL, type, LOOKUP_NORMAL, complain);
 
          ctor = build_aggr_init_expr (type, ctor);
          AGGR_INIT_ZERO_FIRST (ctor) = 1;
          return ctor;
        }
     }
-  return build_value_init_noctor (type);
+  return build_value_init_noctor (type, complain);
 }
 
 /* Like build_value_init, but don't call the constructor for TYPE.  Used
    for base initializers.  */
 
 tree
-build_value_init_noctor (tree type)
+build_value_init_noctor (tree type, tsubst_flags_t complain)
 {
   if (CLASS_TYPE_P (type))
     {
@@ -337,7 +337,7 @@ build_value_init_noctor (tree type)
          VEC(constructor_elt,gc) *v = NULL;
 
          /* Iterate over the fields, building initializations.  */
-         for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+         for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
            {
              tree ftype, value;
 
@@ -347,7 +347,12 @@ build_value_init_noctor (tree type)
              ftype = TREE_TYPE (field);
 
              if (TREE_CODE (ftype) == REFERENCE_TYPE)
-               error ("value-initialization of reference");
+               {
+                 if (complain & tf_error)
+                   error ("value-initialization of reference");
+                 else
+                   return error_mark_node;
+               }
 
              /* We could skip vfields and fields of types with
                 user-defined constructors, but I think that won't improve
@@ -359,7 +364,7 @@ build_value_init_noctor (tree type)
                 corresponding to base classes as well.  Thus, iterating
                 over TYPE_FIELDs will result in correct initialization of
                 all of the subobjects.  */
-             value = build_value_init (ftype);
+             value = build_value_init (ftype, complain);
 
              if (value)
                CONSTRUCTOR_APPEND_ELT(v, field, value);
@@ -379,7 +384,10 @@ build_value_init_noctor (tree 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;
+       {
+         error ("cannot value-initialize array of unknown bound %qT", type);
+         return error_mark_node;
+       }
       gcc_assert (TREE_CODE (max_index) == INTEGER_CST);
 
       /* A zero-sized array, which is accepted as an extension, will
@@ -398,7 +406,7 @@ build_value_init_noctor (tree type)
            ce->index = build2 (RANGE_EXPR, sizetype, size_zero_node,
                                max_index);
 
-         ce->value = build_value_init (TREE_TYPE (type));
+         ce->value = build_value_init (TREE_TYPE (type), complain);
 
          /* The gimplifier can't deal with a RANGE_EXPR of TARGET_EXPRs.  */
          gcc_assert (TREE_CODE (ce->value) != TARGET_EXPR
@@ -456,7 +464,8 @@ perform_member_init (tree member, tree init)
                       member);
          else
            {
-             init = build2 (INIT_EXPR, type, decl, build_value_init (type));
+             init = build2 (INIT_EXPR, type, decl,
+                            build_value_init (type, tf_warning_or_error));
              finish_expr_stmt (init);
            }
        }
@@ -525,7 +534,8 @@ perform_member_init (tree member, tree init)
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
           in that case.  */
-       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT);
+       init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
+                                               tf_warning_or_error);
 
       if (init)
        finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
@@ -562,27 +572,29 @@ build_field_list (tree t, tree list, int *uses_unions_p)
   if (TREE_CODE (t) == UNION_TYPE)
     *uses_unions_p = 1;
 
-  for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
+  for (fields = TYPE_FIELDS (t); fields; fields = DECL_CHAIN (fields))
     {
+      tree fieldtype;
+
       /* Skip CONST_DECLs for enumeration constants and so forth.  */
       if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
        continue;
 
+      fieldtype = TREE_TYPE (fields);
       /* Keep track of whether or not any fields are unions.  */
-      if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
+      if (TREE_CODE (fieldtype) == UNION_TYPE)
        *uses_unions_p = 1;
 
       /* For an anonymous struct or union, we must recursively
         consider the fields of the anonymous type.  They can be
         directly initialized from the constructor.  */
-      if (ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
+      if (ANON_AGGR_TYPE_P (fieldtype))
        {
          /* Add this field itself.  Synthesized copy constructors
             initialize the entire aggregate.  */
          list = tree_cons (fields, NULL_TREE, list);
          /* And now add the fields in the anonymous aggregate.  */
-         list = build_field_list (TREE_TYPE (fields), list,
-                                  uses_unions_p);
+         list = build_field_list (fieldtype, list, uses_unions_p);
        }
       /* Add this field.  */
       else if (DECL_NAME (fields))
@@ -708,38 +720,54 @@ sort_mem_initializers (tree t, tree mem_inits)
 
      If a ctor-initializer specifies more than one mem-initializer for
      multiple members of the same union (including members of
-     anonymous unions), the ctor-initializer is ill-formed.  */
+     anonymous unions), the ctor-initializer is ill-formed.
+
+     Here we also splice out uninitialized union members.  */
   if (uses_unions_p)
     {
       tree last_field = NULL_TREE;
-      for (init = sorted_inits; init; init = TREE_CHAIN (init))
+      tree *p;
+      for (p = &sorted_inits; *p; )
        {
          tree field;
-         tree field_type;
+         tree ctx;
          int done;
 
-         /* Skip uninitialized members and base classes.  */
-         if (!TREE_VALUE (init)
-             || TREE_CODE (TREE_PURPOSE (init)) != FIELD_DECL)
-           continue;
+         init = *p;
+
+         field = TREE_PURPOSE (init);
+
+         /* Skip base classes.  */
+         if (TREE_CODE (field) != FIELD_DECL)
+           goto next;
+
+         /* If this is an anonymous union with no explicit initializer,
+            splice it out.  */
+         if (!TREE_VALUE (init) && ANON_UNION_TYPE_P (TREE_TYPE (field)))
+           goto splice;
+
          /* See if this field is a member of a union, or a member of a
             structure contained in a union, etc.  */
-         field = TREE_PURPOSE (init);
-         for (field_type = DECL_CONTEXT (field);
-              !same_type_p (field_type, t);
-              field_type = TYPE_CONTEXT (field_type))
-           if (TREE_CODE (field_type) == UNION_TYPE)
+         for (ctx = DECL_CONTEXT (field);
+              !same_type_p (ctx, t);
+              ctx = TYPE_CONTEXT (ctx))
+           if (TREE_CODE (ctx) == UNION_TYPE)
              break;
          /* If this field is not a member of a union, skip it.  */
-         if (TREE_CODE (field_type) != UNION_TYPE)
-           continue;
+         if (TREE_CODE (ctx) != UNION_TYPE)
+           goto next;
+
+         /* If this union member has no explicit initializer, splice
+            it out.  */
+         if (!TREE_VALUE (init))
+           goto splice;
 
          /* It's only an error if we have two initializers for the same
             union type.  */
          if (!last_field)
            {
              last_field = field;
-             continue;
+             goto next;
            }
 
          /* See if LAST_FIELD and the field initialized by INIT are
@@ -750,41 +778,48 @@ sort_mem_initializers (tree t, tree mem_inits)
               union { struct { int i; int j; }; };
 
             initializing both `i' and `j' makes sense.  */
-         field_type = DECL_CONTEXT (field);
+         ctx = DECL_CONTEXT (field);
          done = 0;
          do
            {
-             tree last_field_type;
+             tree last_ctx;
 
-             last_field_type = DECL_CONTEXT (last_field);
+             last_ctx = DECL_CONTEXT (last_field);
              while (1)
                {
-                 if (same_type_p (last_field_type, field_type))
+                 if (same_type_p (last_ctx, ctx))
                    {
-                     if (TREE_CODE (field_type) == UNION_TYPE)
+                     if (TREE_CODE (ctx) == UNION_TYPE)
                        error_at (DECL_SOURCE_LOCATION (current_function_decl),
                                  "initializations for multiple members of %qT",
-                                 last_field_type);
+                                 last_ctx);
                      done = 1;
                      break;
                    }
 
-                 if (same_type_p (last_field_type, t))
+                 if (same_type_p (last_ctx, t))
                    break;
 
-                 last_field_type = TYPE_CONTEXT (last_field_type);
+                 last_ctx = TYPE_CONTEXT (last_ctx);
                }
 
              /* If we've reached the outermost class, then we're
                 done.  */
-             if (same_type_p (field_type, t))
+             if (same_type_p (ctx, t))
                break;
 
-             field_type = TYPE_CONTEXT (field_type);
+             ctx = TYPE_CONTEXT (ctx);
            }
          while (!done);
 
          last_field = field;
+
+       next:
+         p = &TREE_CHAIN (*p);
+         continue;
+       splice:
+         *p = TREE_CHAIN (*p);
+         continue;
        }
     }
 
@@ -1005,7 +1040,7 @@ construct_virtual_base (tree vbase, tree arguments)
      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));
+  flag = DECL_CHAIN (DECL_ARGUMENTS (current_function_decl));
   inner_if_stmt = begin_if_stmt ();
   finish_if_stmt_cond (flag, inner_if_stmt);
 
@@ -1374,7 +1409,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
     release_tree_vector (parms);
 
   if (TREE_SIDE_EFFECTS (rval))
-    finish_expr_stmt (convert_to_void (rval, NULL, complain));
+    finish_expr_stmt (convert_to_void (rval, ICV_CAST, complain));
 }
 
 /* This function is responsible for initializing EXP with INIT
@@ -1444,7 +1479,8 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
         then just zero out the object and we're done.  */
       else
        {
-         init = build2 (INIT_EXPR, type, exp, build_value_init_noctor (type));
+         init = build2 (INIT_EXPR, type, exp,
+                        build_value_init_noctor (type, complain));
          finish_expr_stmt (init);
          return;
        }
@@ -1507,9 +1543,9 @@ build_offset_ref (tree type, tree member, bool address_p)
   if (TREE_CODE (member) == TEMPLATE_DECL)
     return member;
 
-  if (dependent_type_p (type) || type_dependent_expression_p (member))
+  if (dependent_scope_p (type) || type_dependent_expression_p (member))
     return build_qualified_name (NULL_TREE, type, member,
-                                /*template_p=*/false);
+                                 /*template_p=*/false);
 
   gcc_assert (TYPE_P (type));
   if (! is_class_type (type, 1))
@@ -1519,6 +1555,7 @@ build_offset_ref (tree type, tree member, bool address_p)
   /* Callers should call mark_used before this point.  */
   gcc_assert (!DECL_P (member) || TREE_USED (member));
 
+  type = TYPE_MAIN_VARIANT (type);
   if (!COMPLETE_OR_OPEN_TYPE_P (complete_type (type)))
     {
       error ("incomplete type %qT does not have member %qD", type, member);
@@ -1789,7 +1826,7 @@ diagnose_uninitialized_cst_or_ref_member_1 (tree type, tree origin,
   if (type_has_user_provided_constructor (type))
     return 0;
 
-  for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+  for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
     {
       tree field_type;
 
@@ -2007,10 +2044,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
        }
       alloc_fn = OVL_CURRENT (alloc_fn);
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
-      alloc_call = (cp_build_function_call
-                   (alloc_fn,
-                    build_tree_list (NULL_TREE, class_addr),
-                    complain));
+      alloc_call = cp_build_function_call_nary (alloc_fn, complain,
+                                               class_addr, NULL_TREE);
     }
   else if (TYPE_FOR_JAVA (elt_type) && MAYBE_CLASS_TYPE_P (elt_type))
     {
@@ -2286,8 +2321,10 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
          else if (explicit_value_init_p)
            {
              /* Something like `new int()'.  */
-             init_expr = build2 (INIT_EXPR, type,
-                                 init_expr, build_value_init (type));
+             tree val = build_value_init (type, complain);
+             if (val == error_mark_node)
+               return error_mark_node;
+             init_expr = build2 (INIT_EXPR, type, init_expr, val);
            }
          else
            {
@@ -2506,7 +2543,7 @@ build_new (VEC(tree,gc) **placement, tree type, tree nelts,
   /* The type allocated must be complete.  If the new-type-id was
      "T[N]" then we are just checking that "T" is complete here, but
      that is equivalent, since the value of "N" doesn't matter.  */
-  if (!complete_type_or_else (type, NULL_TREE))
+  if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
     return error_mark_node;
 
   rval = build_new_1 (placement, type, nelts, init, use_global_new, complain);
@@ -2552,7 +2589,7 @@ build_java_class_ref (tree type)
   /* Mangle the class$ field.  */
   {
     tree field;
-    for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+    for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
       if (DECL_NAME (field) == CL_suffix)
        {
          mangle_decl (field);
@@ -2717,7 +2754,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, tf_warning_or_error);
+  return convert_to_void (body, ICV_CAST, tf_warning_or_error);
 }
 
 /* Create an unnamed variable of the indicated TYPE.  */
@@ -2825,7 +2862,7 @@ build_vec_init (tree base, tree maxindex, tree init,
       && TREE_CODE (atype) == ARRAY_TYPE
       && (from_array == 2
          ? (!CLASS_TYPE_P (inner_elt_type)
-            || !TYPE_HAS_COMPLEX_ASSIGN_REF (inner_elt_type))
+            || !TYPE_HAS_COMPLEX_COPY_ASSIGN (inner_elt_type))
          : !TYPE_NEEDS_CONSTRUCTING (type))
       && ((TREE_CODE (init) == CONSTRUCTOR
           /* Don't do this if the CONSTRUCTOR might contain something
@@ -3013,8 +3050,13 @@ build_vec_init (tree base, tree maxindex, tree init,
                                     0, complain);
        }
       else if (explicit_value_init_p)
-       elt_init = build2 (INIT_EXPR, type, to,
-                          build_value_init (type));
+       {
+         elt_init = build_value_init (type, complain);
+         if (elt_init == error_mark_node)
+           return error_mark_node;
+         else
+           elt_init = build2 (INIT_EXPR, type, to, elt_init);
+       }
       else
        {
          gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
@@ -3352,21 +3394,27 @@ push_base_cleanups (void)
       finish_decl_cleanup (NULL_TREE, expr);
     }
 
+  /* Don't automatically destroy union members.  */
+  if (TREE_CODE (current_class_type) == UNION_TYPE)
+    return;
+
   for (member = TYPE_FIELDS (current_class_type); member;
-       member = TREE_CHAIN (member))
+       member = DECL_CHAIN (member))
     {
-      if (TREE_TYPE (member) == error_mark_node
+      tree this_type = TREE_TYPE (member);
+      if (this_type == error_mark_node
          || TREE_CODE (member) != FIELD_DECL
          || DECL_ARTIFICIAL (member))
        continue;
-      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+      if (ANON_UNION_TYPE_P (this_type))
+       continue;
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (this_type))
        {
          tree this_member = (build_class_member_access_expr
                              (current_class_ref, member,
                               /*access_path=*/NULL_TREE,
                               /*preserve_reference=*/false,
                               tf_warning_or_error));
-         tree this_type = TREE_TYPE (member);
          expr = build_delete (this_type, this_member,
                               sfk_complete_destructor,
                               LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,