OSDN Git Service

When a class template is explicitly instantiated, its member should be too.
[pf3gnuchains/gcc-fork.git] / gcc / cp / init.c
index 2c89996..5f0872e 100644 (file)
@@ -248,7 +248,10 @@ build_zero_init (tree type, tree nelts, bool static_storage_p)
 
   /* In all cases, the initializer is a constant.  */
   if (init)
-    TREE_CONSTANT (init) = 1;
+    {
+      TREE_CONSTANT (init) = 1;
+      TREE_INVARIANT (init) = 1;
+    }
 
   return init;
 }
@@ -340,8 +343,7 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
-  else if (TYPE_NEEDS_CONSTRUCTING (type)
-          || (init && TYPE_HAS_CONSTRUCTOR (type)))
+  else if (TYPE_NEEDS_CONSTRUCTING (type))
     {
       if (explicit
          && TREE_CODE (type) == ARRAY_TYPE
@@ -371,6 +373,9 @@ perform_member_init (tree member, tree init)
          /* member traversal: note it leaves init NULL */
          else if (TREE_CODE (type) == REFERENCE_TYPE)
            pedwarn ("uninitialized reference member `%D'", member);
+         else if (CP_TYPE_CONST_P (type))
+           pedwarn ("uninitialized member `%D' with `const' type `%T'",
+                    member, type);
        }
       else if (TREE_CODE (init) == TREE_LIST)
        /* There was an explicit member initialization.  Do some work
@@ -726,12 +731,9 @@ build_vtbl_address (tree binfo)
   TREE_USED (vtbl) = 1;
 
   /* Now compute the address to use when initializing the vptr.  */
-  vtbl = BINFO_VTABLE (binfo_for);
+  vtbl = unshare_expr (BINFO_VTABLE (binfo_for));
   if (TREE_CODE (vtbl) == VAR_DECL)
-    {
-      vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
-      TREE_CONSTANT (vtbl) = 1;
-    }
+    vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);
 
   return vtbl;
 }
@@ -765,7 +767,8 @@ expand_virtual_init (tree binfo, tree decl)
                     TREE_TYPE (vtt_parm), 
                     vtt_parm,
                     vtt_index);
-      vtbl2 = build1 (INDIRECT_REF, TREE_TYPE (vtbl), vtbl2);
+      vtbl2 = build_indirect_ref (vtbl2, NULL);
+      vtbl2 = convert (TREE_TYPE (vtbl), vtbl2);
 
       /* The actual initializer is the VTT value only in the subobject
         constructor.  In maybe_clone_body we'll substitute NULL for
@@ -1088,34 +1091,25 @@ build_aggr_init (tree exp, tree init, int flags)
 
   if (TREE_CODE (type) == ARRAY_TYPE)
     {
-      /* Must arrange to initialize each element of EXP
-        from elements of INIT.  */
-      tree itype = init ? TREE_TYPE (init) : NULL_TREE;
-      
-      if (init && !itype)
+      tree itype;
+
+      /* An array may not be initialized use the parenthesized
+        initialization form -- unless the initializer is "()".  */
+      if (init && TREE_CODE (init) == TREE_LIST)
        {
-         /* Handle bad initializers like:
-            class COMPLEX {
-            public:
-              double re, im;
-              COMPLEX(double r = 0.0, double i = 0.0) {re = r; im = i;};
-              ~COMPLEX() {};
-            };
-
-            int main(int argc, char **argv) {
-              COMPLEX zees(1.0, 0.0)[10];
-            }
-         */
          error ("bad array initializer");
          return error_mark_node;
        }
+      /* Must arrange to initialize each element of EXP
+        from elements of INIT.  */
+      itype = init ? TREE_TYPE (init) : NULL_TREE;
       if (cp_type_quals (type) != TYPE_UNQUALIFIED)
        TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);
       if (itype && cp_type_quals (itype) != TYPE_UNQUALIFIED)
-       TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
+       itype = TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);
       stmt_expr = build_vec_init (exp, NULL_TREE, init,
-                                 init && same_type_p (TREE_TYPE (init),
-                                                      TREE_TYPE (exp)));
+                                 itype && same_type_p (itype,
+                                                       TREE_TYPE (exp)));
       TREE_READONLY (exp) = was_const;
       TREE_THIS_VOLATILE (exp) = was_volatile;
       TREE_TYPE (exp) = type;
@@ -1150,9 +1144,13 @@ build_init (tree decl, tree init, int flags)
 {
   tree expr;
 
-  if (IS_AGGR_TYPE (TREE_TYPE (decl))
-      || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+  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),
+                                     TYPE_BINFO (TREE_TYPE (decl)),
+                                     LOOKUP_NORMAL|flags);
   else
     expr = build (INIT_EXPR, TREE_TYPE (decl), decl, init);
 
@@ -1187,8 +1185,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
           to run a new constructor; and catching an exception, where we
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
-      else if (TREE_CODE (init) == CONSTRUCTOR 
-              && TREE_HAS_CONSTRUCTOR (init))
+      else if (BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          /* A brace-enclosed initializer for an aggregate.  */
          my_friendly_assert (CP_AGGREGATE_TYPE_P (type), 20021016);
@@ -1371,7 +1368,7 @@ build_offset_ref (tree type, tree name, bool address_p)
   if (TREE_CODE (name) == TEMPLATE_DECL)
     return name;
 
-  if (processing_template_decl || uses_template_parms (type))
+  if (dependent_type_p (type) || type_dependent_expression_p (name))
     return build_min_nt (SCOPE_REF, type, name);
 
   if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
@@ -1453,6 +1450,14 @@ build_offset_ref (tree type, tree name, bool address_p)
       return error_mark_node;
     }
 
+  if (processing_template_decl)
+    {
+      if (TREE_CODE (orig_name) == TEMPLATE_ID_EXPR)
+       return build_min (SCOPE_REF, TREE_TYPE (member), type, orig_name);
+      else
+       return build_min (SCOPE_REF, TREE_TYPE (member), type, name);
+    }
+
   if (TREE_CODE (member) == TYPE_DECL)
     {
       TREE_USED (member) = 1;
@@ -1620,6 +1625,7 @@ decl_constant_value (tree decl)
          /* And so are variables with a 'const' type -- unless they
             are also 'volatile'.  */
          || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))
+      && TREE_CODE (decl) != PARM_DECL
       && DECL_INITIAL (decl)
       && DECL_INITIAL (decl) != error_mark_node
       /* This is invalid if initial value is not constant.
@@ -1790,6 +1796,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
       rval = build_min (NEW_EXPR, build_pointer_type (type), 
                        placement, t, init);
       NEW_EXPR_USE_GLOBAL (rval) = use_global_new;
+      TREE_SIDE_EFFECTS (rval) = 1;
       return rval;
     }
 
@@ -1832,7 +1839,7 @@ build_new (tree placement, tree decl, tree init, int use_global_new)
 
   /* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain.  */
   rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
-  TREE_NO_UNUSED_WARNING (rval) = 1;
+  TREE_NO_WARNING (rval) = 1;
 
   return rval;
 }
@@ -1915,7 +1922,7 @@ static tree
 build_new_1 (tree exp)
 {
   tree placement, init;
-  tree true_type, size, rval, t;
+  tree true_type, size, rval;
   /* The type of the new-expression.  (This type is always a pointer
      type.)  */
   tree pointer_type;
@@ -1956,6 +1963,7 @@ build_new_1 (tree exp)
      address of the first array element.  This node is a VAR_DECL, and
      is therefore reusable.  */
   tree data_addr;
+  tree init_preeval_expr = NULL_TREE;
 
   placement = TREE_OPERAND (exp, 0);
   type = TREE_OPERAND (exp, 1);
@@ -2015,17 +2023,18 @@ build_new_1 (tree exp)
     {
       tree class_addr, alloc_decl;
       tree class_decl = build_java_class_ref (true_type);
-      tree class_size = size_in_bytes (true_type);
       static const char alloc_name[] = "_Jv_AllocObject";
+
       use_java_new = 1;
+      alloc_decl = NULL;
       if (!get_global_value_if_present (get_identifier (alloc_name), 
                                        &alloc_decl))
-       {\r
+       {
          error ("call to Java constructor with `%s' undefined", alloc_name);
          return error_mark_node;
        }
       else if (really_overloaded_fn (alloc_decl))
-       {\r
+       {
          error ("`%D' should never be overloaded", alloc_decl);
          return error_mark_node;
        }
@@ -2033,8 +2042,7 @@ build_new_1 (tree exp)
       class_addr = build1 (ADDR_EXPR, jclass_node, class_decl);
       alloc_call = (build_function_call
                    (alloc_decl,
-                    tree_cons (NULL_TREE, class_addr,
-                               build_tree_list (NULL_TREE, class_size))));
+                    build_tree_list (NULL_TREE, class_addr)));
     }
   else
     {
@@ -2124,18 +2132,8 @@ build_new_1 (tree exp)
      placement delete.  */
   if (placement_allocation_fn_p)
     {
-      tree inits = NULL_TREE;
-      t = TREE_CHAIN (TREE_OPERAND (alloc_call, 1));
-      for (; t; t = TREE_CHAIN (t))
-       if (TREE_SIDE_EFFECTS (TREE_VALUE (t)))
-         {
-           tree init;
-           TREE_VALUE (t) = stabilize_expr (TREE_VALUE (t), &init);
-           if (inits)
-             inits = build (COMPOUND_EXPR, void_type_node, inits, init);
-           else
-             inits = init;
-         }
+      tree inits;
+      stabilize_call (alloc_call, &inits);
       if (inits)
        alloc_expr = build (COMPOUND_EXPR, TREE_TYPE (alloc_expr), inits,
                            alloc_expr);
@@ -2178,27 +2176,43 @@ build_new_1 (tree exp)
       data_addr = alloc_node;
     }
 
-  /* Now initialize the allocated object.  */
+  /* Now initialize the allocated object.  Note that we preevaluate the
+     initialization expression, apart from the actual constructor call or
+     assignment--we do this because we want to delay the allocation as long
+     as possible in order to minimize the size of the exception region for
+     placement delete.  */
   if (is_initialized)
     {
+      bool stable;
+
       init_expr = build_indirect_ref (data_addr, NULL);
 
       if (init == void_zero_node)
        init = build_default_init (full_type, nelts);
-      else if (init && pedantic && has_array)
+      else if (init && has_array)
        pedwarn ("ISO C++ forbids initialization in array new");
 
       if (has_array)
-       init_expr
-         = build_vec_init (init_expr,
-                           cp_build_binary_op (MINUS_EXPR, outer_nelts,
-                                               integer_one_node),
-                           init, /*from_array=*/0);
+       {
+         init_expr
+           = build_vec_init (init_expr,
+                             cp_build_binary_op (MINUS_EXPR, outer_nelts,
+                                                 integer_one_node),
+                             init, /*from_array=*/0);
+
+         /* An array initialization is stable because the initialization
+            of each element is a full-expression, so the temporaries don't
+            leak out.  */
+         stable = true;
+       }
       else if (TYPE_NEEDS_CONSTRUCTING (type))
-       init_expr = build_special_member_call (init_expr, 
-                                              complete_ctor_identifier,
-                                              init, TYPE_BINFO (true_type),
-                                              LOOKUP_NORMAL);
+       {
+         init_expr = build_special_member_call (init_expr, 
+                                                complete_ctor_identifier,
+                                                init, TYPE_BINFO (true_type),
+                                                LOOKUP_NORMAL);
+         stable = stabilize_init (init_expr, &init_preeval_expr);
+       }
       else
        {
          /* We are processing something like `new int (10)', which
@@ -2206,15 +2220,13 @@ build_new_1 (tree exp)
 
          if (TREE_CODE (init) == TREE_LIST)
            init = build_x_compound_expr_from_list (init, "new initializer");
-         
+
          else if (TREE_CODE (init) == CONSTRUCTOR
                   && TREE_TYPE (init) == NULL_TREE)
-           {
-             pedwarn ("ISO C++ forbids aggregate initializer to new");
-             init = digest_init (type, init, 0);
-           }
+           abort ();
 
          init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
+         stable = stabilize_init (init_expr, &init_preeval_expr);
        }
 
       if (init_expr == error_mark_node)
@@ -2232,43 +2244,33 @@ build_new_1 (tree exp)
        {
          enum tree_code dcode = has_array ? VEC_DELETE_EXPR : DELETE_EXPR;
          tree cleanup;
-         int flags = (LOOKUP_NORMAL 
-                      | (globally_qualified_p * LOOKUP_GLOBAL));
 
          /* The Standard is unclear here, but the right thing to do
             is to use the same method for finding deallocation
             functions that we use for finding allocation functions.  */
-         flags |= LOOKUP_SPECULATIVELY;
-
-         cleanup = build_op_delete_call (dcode, alloc_node, size, flags,
+         cleanup = build_op_delete_call (dcode, alloc_node, size, 
+                                         globally_qualified_p,
                                          (placement_allocation_fn_p 
                                           ? alloc_call : NULL_TREE));
 
-         /* Ack!  First we allocate the memory.  Then we set our sentry
-            variable to true, and expand a cleanup that deletes the memory
-            if sentry is true.  Then we run the constructor, and finally
-            clear the sentry.
-
-            It would be nice to be able to handle this without the sentry
-            variable, perhaps with a TRY_CATCH_EXPR, but this doesn't
-            work.  We allocate the space first, so if there are any
-            temporaries with cleanups in the constructor args we need this
-            EH region to extend until end of full-expression to preserve
-            nesting.
-
-            If the backend had some mechanism so that we could force the
-            allocation to be expanded after all the other args to the
-            constructor, that would fix the nesting problem and we could
-            do away with this complexity.  But that would complicate other
-            things; in particular, it would make it difficult to bail out
-            if the allocation function returns null.  Er, no, it wouldn't;
-            we just don't run the constructor.  The standard says it's
-            unspecified whether or not the args are evaluated.
-
-            FIXME FIXME FIXME inline invisible refs as refs.  That way we
-            can preevaluate value parameters.  */
-
-         if (cleanup)
+         if (!cleanup)
+           /* We're done.  */;
+         else if (stable)
+           /* This is much simpler if we were able to preevaluate all of
+              the arguments to the constructor call.  */
+           init_expr = build (TRY_CATCH_EXPR, void_type_node,
+                              init_expr, cleanup);
+         else
+           /* Ack!  First we allocate the memory.  Then we set our sentry
+              variable to true, and expand a cleanup that deletes the
+              memory if sentry is true.  Then we run the constructor, and
+              finally clear the sentry.
+
+              We need to do this because we allocate the space first, so
+              if there are any temporaries with cleanups in the
+              constructor args and we weren't able to preevaluate them, we
+              need this EH region to extend until end of full-expression
+              to preserve nesting.  */
            {
              tree end, sentry, begin;
 
@@ -2289,6 +2291,7 @@ build_new_1 (tree exp)
                         build (COMPOUND_EXPR, void_type_node, init_expr,
                                end));
            }
+           
        }
     }
   else
@@ -2321,6 +2324,9 @@ build_new_1 (tree exp)
       rval = build (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
     }
 
+  if (init_preeval_expr)
+    rval = build (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
+
   /* Convert to the final type.  */
   rval = build_nop (pointer_type, rval);
 
@@ -2439,7 +2445,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   /* Outermost wrapper: If pointer is null, punt.  */
   body = fold (build (COND_EXPR, void_type_node,
                      fold (build (NE_EXPR, boolean_type_node, base,
-                                  integer_zero_node)),
+                                  convert (TREE_TYPE (base),
+                                           integer_zero_node))),
                      body, integer_zero_node));
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -2790,9 +2797,9 @@ build_x_delete (tree addr, int which_delete, tree virtual_size)
   int use_global_delete = which_delete & 1;
   int use_vec_delete = !!(which_delete & 2);
   enum tree_code code = use_vec_delete ? VEC_DELETE_EXPR : DELETE_EXPR;
-  int flags = LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL);
 
-  return build_op_delete_call (code, addr, virtual_size, flags, NULL_TREE);
+  return build_op_delete_call (code, addr, virtual_size, use_global_delete, 
+                              NULL_TREE);
 }
 
 /* Call the DTOR_KIND destructor for EXP.  FLAGS are as for
@@ -2856,23 +2863,35 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
 
   if (TREE_CODE (type) == POINTER_TYPE)
     {
+      bool complete_p = true;
+
       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
       if (TREE_CODE (type) == ARRAY_TYPE)
        goto handle_array;
 
-      if (VOID_TYPE_P (type)
-         /* We don't want to warn about delete of void*, only other
-            incomplete types.  Deleting other incomplete types
-            invokes undefined behavior, but it is not ill-formed, so
-            compile to something that would even do The Right Thing
-            (TM) should the type have a trivial dtor and no delete
-            operator.  */
-         || !complete_type_or_diagnostic (type, addr, 1)
-         || !IS_AGGR_TYPE (type))
+      /* We don't want to warn about delete of void*, only other
+         incomplete types.  Deleting other incomplete types
+         invokes undefined behavior, but it is not ill-formed, so
+         compile to something that would even do The Right Thing
+         (TM) should the type have a trivial dtor and no delete
+         operator.  */
+      if (!VOID_TYPE_P (type))
        {
-         /* Call the builtin operator delete.  */
-         return build_builtin_delete_call (addr);
+         complete_type (type);
+         if (!COMPLETE_TYPE_P (type))
+           {
+             warning ("possible problem detected in invocation of "
+                      "delete operator:");
+             cxx_incomplete_type_diagnostic (addr, type, 1);
+             inform ("neither the destructor nor the class-specific "\r
+                     "operator delete will be called, even if they are "\r
+                     "declared when the class is defined.");
+             complete_p = false;
+           }
        }
+      if (VOID_TYPE_P (type) || !complete_p || !IS_AGGR_TYPE (type))
+       /* Call the builtin operator delete.  */
+       return build_builtin_delete_call (addr);
       if (TREE_SIDE_EFFECTS (addr))
        addr = save_expr (addr);
 
@@ -2911,8 +2930,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
        return void_zero_node;
 
       return build_op_delete_call
-       (DELETE_EXPR, addr, cxx_sizeof_nowarn (type),
-        LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
+       (DELETE_EXPR, addr, cxx_sizeof_nowarn (type), use_global_delete,
         NULL_TREE);
     }
   else
@@ -2947,7 +2965,7 @@ build_delete (tree type, tree addr, special_function_kind auto_delete,
          do_delete = build_op_delete_call (DELETE_EXPR,
                                            addr,
                                            cxx_sizeof_nowarn (type),
-                                           LOOKUP_NORMAL,
+                                           /*global_p=*/false,
                                            NULL_TREE);
          /* Call the complete object destructor.  */
          auto_delete = sfk_complete_destructor;
@@ -2958,7 +2976,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),
-                               LOOKUP_NORMAL, NULL_TREE);
+                               /*global_p=*/false, NULL_TREE);
        }
 
       expr = build_dtor_call (build_indirect_ref (addr, NULL),