call.c (convert_default_arg): Make global, not static.
authorMark Mitchell <mark@markmitchell.com>
Thu, 11 Jun 1998 00:07:24 +0000 (00:07 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 11 Jun 1998 00:07:24 +0000 (00:07 +0000)
* call.c (convert_default_arg): Make global, not static.
(convert_arg_for_ellipsis): Split out from ...
(build_over_call): Here.
* cp-tree.h (convert_default_arg); Declare.
(convert_arg_to_ellipsis): Likewise.
(do_member_init): Remove.
* init.c (do_member_init): Remove; this code is dead.
(expand_member_init): Remove much of this code; it is dead.
* typeck.c (convert_arguments): Use convert_default_arg and
convert_arg_for_ellipsis, rather than duplicating here.
* call.c (convert_like): Don't fail silently if
build_user_type_conversion fails.  Always return error_mark_node
for failure.

From-SVN: r20424

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/init.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.pt/crash9.C [new file with mode: 0644]

index 0b67eb5db38c1900f18ba34ff105614dfe143ddc..f37a3e481895d70f3a6b637fc6c5a816914a8745 100644 (file)
@@ -1,3 +1,20 @@
+1998-06-10  Mark Mitchell  <mark@markmitchell.com>
+
+       * call.c (convert_default_arg): Make global, not static.
+       (convert_arg_for_ellipsis): Split out from ...
+       (build_over_call): Here.
+       * cp-tree.h (convert_default_arg); Declare.
+       (convert_arg_to_ellipsis): Likewise.
+       (do_member_init): Remove.
+       * init.c (do_member_init): Remove; this code is dead.
+       (expand_member_init): Remove much of this code; it is dead.
+       * typeck.c (convert_arguments): Use convert_default_arg and
+       convert_arg_for_ellipsis, rather than duplicating here.
+       
+       * call.c (convert_like): Don't fail silently if 
+       build_user_type_conversion fails.  Always return error_mark_node 
+       for failure.
+
 1998-06-10  Jason Merrill  <jason@yorick.cygnus.com>
 
        * search.c (covariant_return_p): Complain about ambiguous base.
index 173bdde4d9f99738d06efea9af766d330d0b6e59..429b4cf4758e91d468d5dd816706de19449025c5 100644 (file)
@@ -47,7 +47,6 @@ static struct z_candidate * tourney PROTO((struct z_candidate *));
 static int joust PROTO((struct z_candidate *, struct z_candidate *, int));
 static int compare_ics PROTO((tree, tree));
 static tree build_over_call PROTO((struct z_candidate *, tree, int));
-static tree convert_default_arg PROTO((tree, tree));
 static tree convert_like PROTO((tree, tree));
 static void op_error PROTO((enum tree_code, enum tree_code, tree, tree,
                            tree, char *));
@@ -3155,8 +3154,32 @@ convert_like (convs, expr)
        return expr;
       /* else fall through */
     case BASE_CONV:
-      return build_user_type_conversion
-       (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+      {
+       tree cvt_expr = build_user_type_conversion
+         (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
+       if (!cvt_expr) 
+         {
+           /* This can occur if, for example, the EXPR has incomplete
+              type.  We can't check for that before attempting the
+              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 (comptypes (TREE_TYPE (expr), TREE_TYPE (convs), 1))
+                 incomplete_type_error (expr, TREE_TYPE (expr));
+               else
+                 cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
+                           expr, TREE_TYPE (expr), TREE_TYPE (convs));
+             }
+           else
+             cp_error ("could not convert `%E' to `%T'",
+                       expr, TREE_TYPE (convs));
+           return error_mark_node;
+         }
+       return cvt_expr;
+      }
+
     case REF_BIND:
       return convert_to_reference
        (TREE_TYPE (convs), expr,
@@ -3172,7 +3195,34 @@ convert_like (convs, expr)
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
 }
 
-static tree
+/* ARG is being passed to a varargs function.  Perform any conversions
+   required.  Return the converted value.  */
+
+tree
+convert_arg_to_ellipsis (arg)
+     tree arg;
+{
+  if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
+      && (TYPE_PRECISION (TREE_TYPE (arg))
+         < TYPE_PRECISION (double_type_node)))
+    /* Convert `float' to `double'.  */
+    arg = cp_convert (double_type_node, arg);
+  else if (IS_AGGR_TYPE (TREE_TYPE (arg))
+          && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (arg)))
+    cp_warning ("cannot pass objects of type `%T' through `...'",
+               TREE_TYPE (arg));
+  else
+    /* Convert `short' and `char' to full-size `int'.  */
+    arg = default_conversion (arg);
+
+  return arg;
+}
+
+/* ARG is a default argument expression being passed to a parameter of
+   the indicated TYPE.  Do any required conversions.  Return the
+   converted value.  */
+
+tree
 convert_default_arg (type, arg)
      tree type, arg;
 {
@@ -3341,24 +3391,10 @@ build_over_call (cand, args, flags)
 
   /* Ellipsis */
   for (; arg; arg = TREE_CHAIN (arg))
-    {
-      val = TREE_VALUE (arg);
-
-      if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
-         && (TYPE_PRECISION (TREE_TYPE (val))
-             < TYPE_PRECISION (double_type_node)))
-       /* Convert `float' to `double'.  */
-       val = cp_convert (double_type_node, val);
-      else if (IS_AGGR_TYPE (TREE_TYPE (val))
-              && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
-       cp_warning ("cannot pass objects of type `%T' through `...'",
-                   TREE_TYPE (val));
-      else
-       /* Convert `short' and `char' to full-size `int'.  */
-       val = default_conversion (val);
-
-      converted_args = expr_tree_cons (NULL_TREE, val, converted_args);
-    }
+    converted_args 
+      = expr_tree_cons (NULL_TREE,
+                       convert_arg_to_ellipsis (TREE_VALUE (arg)),
+                       converted_args);
 
   converted_args = nreverse (converted_args);
 
index 3e118d91a5a5e33a4cb99a9e341e824860162259..f0e59fd4322a153dd8cc271f48c0067fbb536ddc 100644 (file)
@@ -2254,6 +2254,8 @@ extern tree build_op_delete_call          PROTO((enum tree_code, tree, tree, int));
 extern int can_convert                         PROTO((tree, tree));
 extern int can_convert_arg                     PROTO((tree, tree, tree));
 extern void enforce_access                      PROTO((tree, tree));
+extern tree convert_default_arg                 PROTO((tree, tree));
+extern tree convert_arg_to_ellipsis             PROTO((tree));
 
 /* in class.c */
 extern tree build_vbase_path                   PROTO((enum tree_code, tree, tree, tree, int));
@@ -2532,7 +2534,6 @@ extern void init_init_processing          PROTO((void));
 extern void expand_direct_vtbls_init           PROTO((tree, tree, int, int, tree));
 extern void emit_base_init                     PROTO((tree, int));
 extern void check_base_init                    PROTO((tree));
-extern void do_member_init                     PROTO((tree, tree, tree));
 extern void expand_member_init                 PROTO((tree, tree, tree));
 extern void expand_aggr_init                   PROTO((tree, tree, int, int));
 extern int is_aggr_typedef                     PROTO((tree, int));
index 828729c3c6c27ca6195a3ef40b88f96cc96cdc55..59491a718b47b201fe5d712e307176b1cf1b9b99 100644 (file)
@@ -832,34 +832,6 @@ expand_aggr_vbase_init (binfo, exp, addr, init_list)
     }
 }
 
-/* Subroutine to perform parser actions for member initialization.
-   S_ID is the scoped identifier.
-   NAME is the name of the member.
-   INIT is the initializer, or `void_type_node' if none.  */
-
-void
-do_member_init (s_id, name, init)
-     tree s_id, name, init;
-{
-  tree binfo, base;
-
-  if (current_class_type == NULL_TREE
-      || ! is_aggr_typedef (s_id, 1))
-    return;
-  binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),
-                         current_class_type, 1);
-  if (binfo == error_mark_node)
-    return;
-  if (binfo == 0)
-    {
-      error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);
-      return;
-    }
-
-  base = convert_pointer_to (binfo, current_class_ptr);
-  expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);
-}
-
 /* Find the context in which this FIELD can be initialized.  */
 
 static tree
@@ -958,151 +930,84 @@ expand_member_init (exp, name, init)
        return;
       }
 
-  if (init)
-    {
-      /* The grammar should not allow fields which have names
-        that are TYPENAMEs.  Therefore, if the field has
-        a non-NULL TREE_TYPE, we may assume that this is an
-        attempt to initialize a base class member of the current
-        type.  Otherwise, it is an attempt to initialize a
-        member field.  */
+  my_friendly_assert (init != NULL_TREE, 0);
 
-      if (init == void_type_node)
-       init = NULL_TREE;
+  /* The grammar should not allow fields which have names that are
+     TYPENAMEs.  Therefore, if the field has a non-NULL TREE_TYPE, we
+     may assume that this is an attempt to initialize a base class
+     member of the current type.  Otherwise, it is an attempt to
+     initialize a member field.  */
 
-      if (name == NULL_TREE || basetype)
-       {
-         tree base_init;
+  if (init == void_type_node)
+    init = NULL_TREE;
 
-         if (name == NULL_TREE)
-           {
-#if 0
-             if (basetype)
-               name = TYPE_IDENTIFIER (basetype);
-             else
-               {
-                 error ("no base class to initialize");
-                 return;
-               }
-#endif
-           }
-         else if (basetype != type
-                  && ! current_template_parms
-                  && ! vec_binfo_member (basetype,
-                                         TYPE_BINFO_BASETYPES (type))
-                  && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
-           {
-             if (IDENTIFIER_CLASS_VALUE (name))
-               goto try_member;
-             if (TYPE_USES_VIRTUAL_BASECLASSES (type))
-               cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
-                         basetype, type);
-             else
-               cp_error ("type `%T' is not an immediate basetype for `%T'",
-                         basetype, type);
-             return;
-           }
+  if (name == NULL_TREE || basetype)
+    {
+      tree base_init;
 
-         if (purpose_member (basetype, current_base_init_list))
+      if (name == NULL_TREE)
+       {
+#if 0
+         if (basetype)
+           name = TYPE_IDENTIFIER (basetype);
+         else
            {
-             cp_error ("base class `%T' already initialized", basetype);
+             error ("no base class to initialize");
              return;
            }
-
-         if (warn_reorder && current_member_init_list)
-           {
-             cp_warning ("base initializer for `%T'", basetype);
-             warning ("   will be re-ordered to precede member initializations");
-           }
-
-         base_init = build_tree_list (basetype, init);
-         current_base_init_list = chainon (current_base_init_list, base_init);
+#endif
        }
-      else
+      else if (basetype != type
+              && ! current_template_parms
+              && ! vec_binfo_member (basetype,
+                                     TYPE_BINFO_BASETYPES (type))
+              && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))
        {
-         tree member_init;
-
-       try_member:
-         field = lookup_field (type, name, 1, 0);
-
-         if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
-           return;
-
-         if (purpose_member (name, current_member_init_list))
-           {
-             cp_error ("field `%D' already initialized", field);
-             return;
-           }
-
-         member_init = build_tree_list (name, init);
-         current_member_init_list = chainon (current_member_init_list, member_init);
+         if (IDENTIFIER_CLASS_VALUE (name))
+           goto try_member;
+         if (TYPE_USES_VIRTUAL_BASECLASSES (type))
+           cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",
+                     basetype, type);
+         else
+           cp_error ("type `%T' is not an immediate basetype for `%T'",
+                     basetype, type);
+         return;
        }
-      return;
-    }
-  else if (name == NULL_TREE)
-    {
-      compiler_error ("expand_member_init: name == NULL_TREE");
-      return;
-    }
 
-  basetype = type;
-  field = lookup_field (basetype, name, 0, 0);
-
-  if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))
-    return;
-
-  /* now see if there is a constructor for this type
-     which will take these args.  */
-
-  if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))
-    {
-      tree parmtypes, fndecl;
-
-      if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)
+      if (purpose_member (basetype, current_base_init_list))
        {
-         /* just know that we've seen something for this node */
-         DECL_INITIAL (exp) = error_mark_node;
-         TREE_USED (exp) = 1;
+         cp_error ("base class `%T' already initialized", basetype);
+         return;
        }
-      type = TYPE_MAIN_VARIANT (TREE_TYPE (field));
-      parm = build_component_ref (exp, name, NULL_TREE, 0);
 
-      /* Now get to the constructors.  */
-      fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);
+      if (warn_reorder && current_member_init_list)
+       {
+         cp_warning ("base initializer for `%T'", basetype);
+         warning ("   will be re-ordered to precede member initializations");
+       }
 
-      if (fndecl)
-       my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);
+      base_init = build_tree_list (basetype, init);
+      current_base_init_list = chainon (current_base_init_list, base_init);
+    }
+  else
+    {
+      tree member_init;
 
-      parmtypes = NULL_TREE;
-      fndecl = NULL_TREE;
+    try_member:
+      field = lookup_field (type, name, 1, 0);
 
-      init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);
-      if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)
-       rval = build_method_call (NULL_TREE, ctor_identifier, init,
-                                 TYPE_BINFO (type), LOOKUP_NORMAL);
-      else
+      if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
        return;
 
-      if (rval != error_mark_node)
+      if (purpose_member (name, current_member_init_list))
        {
-         /* Now, fill in the first parm with our guy */
-         TREE_VALUE (TREE_OPERAND (rval, 1))
-           = build_unary_op (ADDR_EXPR, parm, 0);
-         TREE_TYPE (rval) = ptr_type_node;
-         TREE_SIDE_EFFECTS (rval) = 1;
+         cp_error ("field `%D' already initialized", field);
+         return;
        }
-    }
-  else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
-    {
-      parm = build_component_ref (exp, name, NULL_TREE, 0);
-      expand_aggr_init (parm, NULL_TREE, 0, 0);
-      rval = error_mark_node;
-    }
 
-  /* Now initialize the member.  It does not have to
-     be of aggregate type to receive initialization.  */
-  if (rval != error_mark_node)
-    expand_expr_stmt (rval);
+      member_init = build_tree_list (name, init);
+      current_member_init_list = chainon (current_member_init_list, member_init);
+    }
 }
 
 /* This is like `expand_member_init', only it stores one aggregate
index 8c71a2442207e7fbb37028a51ef4ce5cc62ac0cb..d417afbed6d3278ee404ce4d9969694c09d31c0e 100644 (file)
@@ -3037,24 +3037,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
          if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
            val = convert_from_reference (val);
 
-         if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
-             && (TYPE_PRECISION (TREE_TYPE (val))
-                 < TYPE_PRECISION (double_type_node)))
-           /* Convert `float' to `double'.  */
-           result = expr_tree_cons (NULL_TREE,
-                                    cp_convert (double_type_node, val),
-                                    result);
-         else if (IS_AGGR_TYPE (TREE_TYPE (val))
-                  && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val)))
-           {
-             cp_warning ("cannot pass objects of type `%T' through `...'",
-                         TREE_TYPE (val));
-             result = expr_tree_cons (NULL_TREE, val, result);
-           }
-         else
-           /* Convert `short' and `char' to full-size `int'.  */
-           result = expr_tree_cons (NULL_TREE, default_conversion (val),
-                                    result);
+         result = expr_tree_cons (NULL_TREE,
+                                  convert_arg_to_ellipsis (val),
+                                  result);
        }
 
       if (typetail)
@@ -3069,37 +3054,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
          for (; typetail != void_list_node; ++i)
            {
              tree type = TREE_VALUE (typetail);
-             tree val = break_out_target_exprs (TREE_PURPOSE (typetail));
-             tree parmval;
-
-             if (val == NULL_TREE)
-               parmval = error_mark_node;
-             else if (TREE_CODE (val) == CONSTRUCTOR)
-               {
-                 parmval = digest_init (type, val, (tree *)0);
-                 parmval = convert_for_initialization (return_loc, type,
-                                                       parmval, flags,
-                                                       "default constructor",
-                                                       fndecl, i);
-               }
-             else
-               {
-                 /* This could get clobbered by the following call.  */
-                 if (TREE_HAS_CONSTRUCTOR (val))
-                   val = copy_node (val);
-
-                 parmval = convert_for_initialization (return_loc, type,
-                                                       val, flags,
-                                                       "default argument",
-                                                       fndecl, i);
-#ifdef PROMOTE_PROTOTYPES
-                 if ((TREE_CODE (type) == INTEGER_TYPE
-                      || TREE_CODE (type) == ENUMERAL_TYPE)
-                     && (TYPE_PRECISION (type)
-                         < TYPE_PRECISION (integer_type_node)))
-                   parmval = default_conversion (parmval);
-#endif
-               }
+             tree val = TREE_PURPOSE (typetail);
+             tree parmval = convert_default_arg (type, val);
 
              if (parmval == error_mark_node)
                return error_mark_node;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash9.C b/gcc/testsuite/g++.old-deja/g++.pt/crash9.C
new file mode 100644 (file)
index 0000000..297b8ac
--- /dev/null
@@ -0,0 +1,11 @@
+// Build don't link:
+
+template <class T>
+void f(T) {} // ERROR - parameter has incomplete type
+
+class C;
+
+void g(const C& c)
+{
+  f(c); // ERROR - invalid use of undefined type
+}