OSDN Git Service

* cp-tree.h (IDENTIFIER_CTOR_OR_DTOR_P): New macro.
[pf3gnuchains/gcc-fork.git] / gcc / cp / call.c
index 40cd43d..1ffbf60 100644 (file)
@@ -34,10 +34,7 @@ Boston, MA 02111-1307, USA.  */
 #include "toplev.h"
 #include "defaults.h"
 #include "expr.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
+#include "ggc.h"
 
 extern int inhibit_warnings;
 
@@ -133,7 +130,7 @@ build_field_call (basetype_path, instance_ptr, name, parms)
 {
   tree field, instance;
 
-  if (name == ctor_identifier || name == dtor_identifier)
+  if (IDENTIFIER_CTOR_OR_DTOR_P (name))
     return NULL_TREE;
 
   /* Speed up the common case.  */
@@ -189,7 +186,7 @@ check_dtor_name (basetype, name)
 
   if (TREE_CODE (name) == TYPE_DECL)
     name = TREE_TYPE (name);
-  else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+  else if (TYPE_P (name))
     /* OK */;
   else if (TREE_CODE (name) == IDENTIFIER_NODE)
     {
@@ -1232,18 +1229,12 @@ add_candidate (candidates, fn, convs, viable)
      tree fn, convs;
      int viable;
 {
-  /* FIXME: This is a memory leak.  Presumably, we should use
-     ggc_alloc instead.  */
   struct z_candidate *cand
-    = (struct z_candidate *) expralloc (sizeof (struct z_candidate));
+    = (struct z_candidate *) ggc_alloc_obj (sizeof (struct z_candidate), 1);
 
   cand->fn = fn;
   cand->convs = convs;
-  cand->second_conv = NULL_TREE;
   cand->viable = viable;
-  cand->basetype_path = NULL_TREE;
-  cand->template = NULL_TREE;
-  cand->warnings = NULL_TREE;
   cand->next = candidates;
 
   return cand;
@@ -1274,7 +1265,7 @@ add_function_candidate (candidates, fn, ctype, arglist, flags)
     {
       parmlist = TREE_CHAIN (parmlist);
       arglist = TREE_CHAIN (arglist);
-      if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
        {
          parmlist = TREE_CHAIN (parmlist);
          arglist = TREE_CHAIN (arglist);
@@ -1514,7 +1505,7 @@ static int
 is_complete (t)
      tree t;
 {
-  return TYPE_SIZE (complete_type (t)) != NULL_TREE;
+  return COMPLETE_TYPE_P (complete_type (t));
 }
 
 /* Returns non-zero if TYPE is a promoted arithmetic type.  */
@@ -2286,7 +2277,12 @@ build_user_type_conversion_1 (totype, expr, flags)
   tree templates = NULL_TREE;
 
   if (IS_AGGR_TYPE (totype))
-    ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
+    ctors = lookup_fnfields (TYPE_BINFO (totype),
+                            (flag_new_abi 
+                             ? complete_ctor_identifier
+                             : ctor_identifier),
+                            0);
+
   if (IS_AGGR_TYPE (fromtype)
       && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
     convs = lookup_conversions (fromtype);
@@ -2296,14 +2292,16 @@ build_user_type_conversion_1 (totype, expr, flags)
 
   if (ctors)
     {
-      tree t = build_int_2 (0, 0);
+      tree t;
+
+      ctors = TREE_VALUE (ctors);
+
+      t = build_int_2 (0, 0);
       TREE_TYPE (t) = build_pointer_type (totype);
       args = build_tree_list (NULL_TREE, expr);
-      if (TYPE_USES_VIRTUAL_BASECLASSES (totype))
+      if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)))
        args = tree_cons (NULL_TREE, integer_one_node, args);
       args = tree_cons (NULL_TREE, t, args);
-
-      ctors = TREE_VALUE (ctors);
     }
   for (; ctors; ctors = OVL_NEXT (ctors))
     {
@@ -3667,7 +3665,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
            TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
 
            args = build_tree_list (NULL_TREE, expr);
-           if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+           if (DECL_HAS_IN_CHARGE_PARM_P (fn))
              args = tree_cons (NULL_TREE, integer_one_node, args);
            args = tree_cons (NULL_TREE, t, args);
          }
@@ -3736,7 +3734,7 @@ convert_like_real (convs, expr, fn, argnum, inner)
               conversion because the type might be an incomplete
               array type, which is OK if some constructor for the
               destination type takes a pointer argument.  */
-           if (TYPE_SIZE (TREE_TYPE (expr)) == 0)
+           if (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
              {
                if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
                  incomplete_type_error (expr, TREE_TYPE (expr));
@@ -3939,7 +3937,7 @@ build_over_call (cand, args, flags)
       converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
       arg = TREE_CHAIN (arg);
       parm = TREE_CHAIN (parm);
-      if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
        {
          converted_args = tree_cons
            (NULL_TREE, TREE_VALUE (arg), converted_args);
@@ -4040,13 +4038,12 @@ build_over_call (cand, args, flags)
 
   if (! flag_elide_constructors)
     /* Do things the hard way.  */;
-  else if (DECL_CONSTRUCTOR_P (fn)
-          && TREE_VEC_LENGTH (convs) == 1
-          && copy_args_p (fn))
+  else if (TREE_VEC_LENGTH (convs) == 1
+          && DECL_COPY_CONSTRUCTOR_P (fn))
     {
       tree targ;
       arg = TREE_CHAIN (converted_args);
-      if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+      if (DECL_HAS_IN_CHARGE_PARM_P (fn))
        arg = TREE_CHAIN (arg);
       arg = TREE_VALUE (arg);
 
@@ -4175,6 +4172,29 @@ build_over_call (cand, args, flags)
   return convert_from_reference (fn);
 }
 
+/* Returns the value to use for the in-charge parameter when making a
+   call to a function with the indicated NAME.  */
+
+tree
+in_charge_arg_for_name (name)
+     tree name;
+{
+  if (name == base_ctor_identifier
+      || name == base_dtor_identifier)
+    return integer_zero_node;
+  else if (name == complete_ctor_identifier)
+    return integer_one_node;
+  else if (name == complete_dtor_identifier)
+    return integer_two_node;
+  else if (name == deleting_dtor_identifier)
+    return integer_three_node;
+
+  /* This function should only be called with one of the names listed
+     above.  */
+  my_friendly_abort (20000411);
+  return NULL_TREE;
+}
+
 static tree
 build_new_method_call (instance, name, args, basetype_path, flags)
      tree instance, name, args, basetype_path;
@@ -4192,7 +4212,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
     {
       explicit_targs = TREE_OPERAND (name, 1);
       name = TREE_OPERAND (name, 0);
-      if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
+      if (DECL_P (name))
        name = DECL_NAME (name);
       else
        {
@@ -4205,11 +4225,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       template_only = 1;
     }
 
-  /* If there is an extra argument for controlling virtual bases,
-     remove it for error reporting.  */
-  if (flags & LOOKUP_HAS_IN_CHARGE)
-    user_args = TREE_CHAIN (args);
-
+  user_args = args;
   args = resolve_args (args);
 
   if (args == error_mark_node)
@@ -4257,8 +4273,37 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
     }
 
-  pretty_name
-    = (name == ctor_identifier ? constructor_name (basetype) : name);
+  /* Callers should explicitly indicate whether they want to construct
+     the complete object or just the part without virtual bases.  */
+  my_friendly_assert (name != ctor_identifier, 20000408);
+  /* Similarly for destructors.  */
+  my_friendly_assert (name != dtor_identifier, 20000408);
+
+  if (IDENTIFIER_CTOR_OR_DTOR_P (name))
+    {
+      int constructor_p;
+
+      constructor_p = (name == complete_ctor_identifier
+                      || name == base_ctor_identifier);
+      pretty_name = (constructor_p 
+                    ? constructor_name (basetype) : dtor_identifier);
+
+      if (!flag_new_abi)
+       {
+         /* Add the in-charge parameter as an implicit first argument.  */
+         if (!constructor_p
+             || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+           args = tree_cons (NULL_TREE,
+                             in_charge_arg_for_name (name),
+                             args);
+
+         /* We want to call the normal constructor function under the
+            old ABI.  */
+         name = constructor_p ? ctor_identifier : dtor_identifier;
+       }
+    }
+  else
+    pretty_name = name;
 
   fns = lookup_fnfields (basetype_path, name, 1);
 
@@ -4268,12 +4313,6 @@ build_new_method_call (instance, name, args, basetype_path, flags)
     {
       tree base = BINFO_TYPE (TREE_PURPOSE (fns));
       tree fn = TREE_VALUE (fns);
-      if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
-         && ! (flags & LOOKUP_HAS_IN_CHARGE))
-       {
-         flags |= LOOKUP_HAS_IN_CHARGE;
-         args = tree_cons (NULL_TREE, integer_one_node, args);
-       }
       mem_args = tree_cons (NULL_TREE, instance_ptr, args);
       for (; fn; fn = OVL_NEXT (fn))
        {
@@ -4281,8 +4320,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
          tree this_arglist;
 
          /* We can end up here for copy-init of same or base class.  */
-         if (name == ctor_identifier
-             && (flags & LOOKUP_ONLYCONVERTING)
+         if ((flags & LOOKUP_ONLYCONVERTING)
              && DECL_NONCONVERTING_P (t))
            continue;
          if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
@@ -4313,7 +4351,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
       /* XXX will LOOKUP_SPECULATIVELY be needed when this is done?  */
       if (flags & LOOKUP_SPECULATIVELY)
        return NULL_TREE;
-      if (TYPE_SIZE (basetype) == 0)
+      if (!COMPLETE_TYPE_P (basetype))
        incomplete_type_error (instance_ptr, basetype);
       else
        cp_error ("no matching function for call to `%T::%D (%A)%V'",