typeck.c (complete_type_or_else): Add VALUE arg, for helpful diagnostics.
authorNathan Sidwell <nathan@acm.org>
Fri, 26 Feb 1999 23:37:04 +0000 (23:37 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 26 Feb 1999 23:37:04 +0000 (18:37 -0500)
* typeck.c (complete_type_or_else): Add VALUE arg, for helpful
diagnostics.
cp-tree.h (complete_type_or_else): Added VALUE parameter.
* init.c (build_new_1): Extra arg to complete_type_or_else.
(build_delete): Likewise.
* typeck.c (require_complete_type): Likewise.
(pointer_int_sum): Likewise.
(pointer_diff): Likewise.
(build_component_ref): Likewise.
* typeck2.c (incomplete_type_error): Always use cp_error.
Show declaration of undefined type, if appropriate.
Deal with UNKNOWN_TYPE nodes.
* typeck.c (require_complete_type): Use TYPE_SIZE as
size_zero_node to mean incomplete type.
(require_complete_type_in_void): New function.
(build_compound_expr): Call complete_type_in_void for LHS.
(build_c_cast): Call complete_type_in_void for void cast.
* cvt.c (ocp_convert): Call complete_type_in_void for void cast.
* decl.c (cplus_expand_expr_stmt): Void expression checks moved to
require_complete_type_in_void. Call it.
* cp-tree.h (require_complete_type_in_void): Prototype new function.
* typeck.c (convert_arguments): Use alternative format for function
decls. Don't require_complete_type here. Simplify diagnostic printing.
(convert_for_initialization): Don't require_complete_type on RHS yet.
* call.c (convert_arg_to_ellipsis): Call require_complete_type.
* call.c (build_over_call): Cope with qualified void return type.
* semantics.c (finish_call_expr): Likewise
* typeck.c (build_function_call_real): Likewise
(c_expand_return): Likewise
* decl2.c (reparse_absdcl_as_expr): Cope with qualified void type.
* call.c (print_z_candidates): Use alternate print format, to be
consistant with (pt.c) print_candidates.
method.c (hack_identifier): List candidate members.
search.c (lookup_field): Build ambiguous list, and show it, if
ambiguous.

From-SVN: r25474

13 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/search.c
gcc/cp/semantics.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index 34e8ef8..8e82f27 100644 (file)
@@ -1,3 +1,46 @@
+1999-02-26  Nathan Sidwell  <nathan@acm.org>
+
+       * typeck.c (complete_type_or_else): Add VALUE arg, for helpful
+       diagnostics.
+       cp-tree.h (complete_type_or_else): Added VALUE parameter.
+       * init.c (build_new_1): Extra arg to complete_type_or_else.
+       (build_delete): Likewise.
+       * typeck.c (require_complete_type): Likewise.
+       (pointer_int_sum): Likewise.
+       (pointer_diff): Likewise.
+       (build_component_ref): Likewise.
+       
+       * typeck2.c (incomplete_type_error): Always use cp_error.
+       Show declaration of undefined type, if appropriate.
+       Deal with UNKNOWN_TYPE nodes.
+       
+       * typeck.c (require_complete_type): Use TYPE_SIZE as
+       size_zero_node to mean incomplete type.
+       (require_complete_type_in_void): New function.
+       (build_compound_expr): Call complete_type_in_void for LHS.
+       (build_c_cast): Call complete_type_in_void for void cast.
+       * cvt.c (ocp_convert): Call complete_type_in_void for void cast.
+       * decl.c (cplus_expand_expr_stmt): Void expression checks moved to
+       require_complete_type_in_void. Call it.
+       * cp-tree.h (require_complete_type_in_void): Prototype new function.
+
+       * typeck.c (convert_arguments): Use alternative format for function 
+       decls. Don't require_complete_type here. Simplify diagnostic printing.
+       (convert_for_initialization): Don't require_complete_type on RHS yet.
+       * call.c (convert_arg_to_ellipsis): Call require_complete_type.
+       
+       * call.c (build_over_call): Cope with qualified void return type.
+       * semantics.c (finish_call_expr): Likewise
+       * typeck.c (build_function_call_real): Likewise
+       (c_expand_return): Likewise
+       * decl2.c (reparse_absdcl_as_expr): Cope with qualified void type.
+       
+       * call.c (print_z_candidates): Use alternate print format, to be
+       consistant with (pt.c) print_candidates.
+       method.c (hack_identifier): List candidate members.
+       search.c (lookup_field): Build ambiguous list, and show it, if
+       ambiguous.
+
 1999-02-26  Mark Mitchell  <mark@markmitchell.com>
 
        * typeck.c (decay_conversion): Don't confuse constant array
index 1e43233..9bf5035 100644 (file)
@@ -2078,7 +2078,7 @@ print_z_candidates (candidates)
       else if (TYPE_P (candidates->fn))
        cp_error ("%s %T <conversion>", str, candidates->fn);
       else
-       cp_error_at ("%s %+D%s", str, candidates->fn,
+       cp_error_at ("%s %+#D%s", str, candidates->fn,
                     candidates->viable == -1 ? " <near match>" : "");
       str = "               "; 
     }
@@ -3175,6 +3175,8 @@ convert_arg_to_ellipsis (arg)
     /* Convert `short' and `char' to full-size `int'.  */
     arg = default_conversion (arg);
 
+  arg = require_complete_type (arg);
+  
   return arg;
 }
 
@@ -3515,7 +3517,7 @@ build_over_call (cand, args, flags)
       }
 
   fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
-  if (TREE_TYPE (fn) == void_type_node)
+  if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
     return fn;
   fn = require_complete_type (fn);
   if (IS_AGGR_TYPE (TREE_TYPE (fn)))
index 3fc9cf4..c533e3e 100644 (file)
@@ -4888,8 +4888,6 @@ push_nested_class (type, modify)
 {
   tree context;
 
-  my_friendly_assert (!type || TREE_CODE (type) != NAMESPACE_DECL, 980711);
-
   /* A namespace might be passed in error cases, like A::B:C.  */
   if (type == NULL_TREE || type == error_mark_node || ! IS_AGGR_TYPE (type)
       || TREE_CODE (type) == NAMESPACE_DECL
index 62ffbf0..59a067e 100644 (file)
@@ -3324,8 +3324,9 @@ extern int string_conv_p                  PROTO((tree, tree, int));
 extern tree condition_conversion               PROTO((tree));
 extern tree target_type                                PROTO((tree));
 extern tree require_complete_type              PROTO((tree));
+extern tree require_complete_type_in_void      PROTO((tree));
 extern tree complete_type                      PROTO((tree));
-extern tree complete_type_or_else               PROTO((tree));
+extern tree complete_type_or_else               PROTO((tree, tree));
 extern int type_unknown_p                      PROTO((tree));
 extern int fntype_p                            PROTO((tree));
 extern tree commonparms                                PROTO((tree, tree));
index b73020f..9f29c65 100644 (file)
@@ -687,10 +687,11 @@ ocp_convert (type, expr, convtype, flags)
 
   if (code == VOID_TYPE && (convtype & CONV_STATIC))
     {
-      if (type_unknown_p (e))
-       error ("address of overloaded function with no contextual type information");
+      e = require_complete_type_in_void (e);
+      if (e != error_mark_node)
+        e = build1 (CONVERT_EXPR, void_type_node, e);
 
-      return build1 (CONVERT_EXPR, type, e);
+      return e;
     }
 
 #if 0
index c18eab7..231a598 100644 (file)
@@ -14380,38 +14380,30 @@ cplus_expand_expr_stmt (exp)
   /* Arrange for all temps to disappear.  */
   expand_start_target_temps ();
 
-  if (TREE_TYPE (exp) == unknown_type_node)
+  exp = require_complete_type_in_void (exp);
+  
+  if (TREE_CODE (exp) == FUNCTION_DECL)
     {
-      if (TREE_CODE (exp) == COMPONENT_REF)
-       error ("invalid reference to a member function name, did you forget the ()?");
-      else
-       error ("address of overloaded function with no contextual type information");
+      cp_warning ("reference, not call, to function `%D'", exp);
+      warning ("at this point in file");
     }
-  else
-    {
-      if (TREE_CODE (exp) == FUNCTION_DECL)
-       {
-         cp_warning ("reference, not call, to function `%D'", exp);
-         warning ("at this point in file");
-       }
 
 #if 0
-      /* We should do this eventually, but right now this causes regex.o from
-        libg++ to miscompile, and tString to core dump.  */
-      exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
+  /* We should do this eventually, but right now this causes regex.o from
+     libg++ to miscompile, and tString to core dump.  */
+  exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
 #endif
 
-      /* Strip unused implicit INDIRECT_REFs of references.  */
-      if (TREE_CODE (exp) == INDIRECT_REF
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
-       exp = TREE_OPERAND (exp, 0);
+  /* Strip unused implicit INDIRECT_REFs of references.  */
+  if (TREE_CODE (exp) == INDIRECT_REF
+      && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
+    exp = TREE_OPERAND (exp, 0);
 
-      /* If we don't do this, we end up down inside expand_expr
-        trying to do TYPE_MODE on the ERROR_MARK, and really
-        go outside the bounds of the type.  */
-      if (exp != error_mark_node)
-       expand_expr_stmt (break_out_cleanups (exp));
-    }
+  /* If we don't do this, we end up down inside expand_expr
+     trying to do TYPE_MODE on the ERROR_MARK, and really
+     go outside the bounds of the type.  */
+  if (exp != error_mark_node)
+    expand_expr_stmt (break_out_cleanups (exp));
 
   /* Clean up any pending cleanups.  This happens when a function call
      returns a cleanup-needing value that nobody uses.  */
index cc38dab..d53dc70 100644 (file)
@@ -3506,7 +3506,9 @@ reparse_absdcl_as_expr (type, decl)
 
   decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
 
-  if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
+  if (TREE_CODE (decl) == CALL_EXPR
+      && (! TREE_TYPE (decl)
+          || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
     decl = require_complete_type (decl);
 
   return decl;
index 847222f..ea424b6 100644 (file)
@@ -2163,7 +2163,7 @@ build_new_1 (exp)
       true_type = TREE_TYPE (true_type);
     }
 
-  if (!complete_type_or_else (true_type))
+  if (!complete_type_or_else (true_type, exp))
     return error_mark_node;
 
   if (has_array)
@@ -3014,7 +3014,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
   if (TREE_CODE (type) == POINTER_TYPE)
     {
       type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
-      if (!complete_type_or_else (type))
+      if (type != void_type_node && !complete_type_or_else (type, addr))
        return error_mark_node;
       if (TREE_CODE (type) == ARRAY_TYPE)
        goto handle_array;
index f3530dd..8546332 100644 (file)
@@ -2023,6 +2023,7 @@ hack_identifier (value, name)
     {
       error ("request for member `%s' is ambiguous in multiple inheritance lattice",
             IDENTIFIER_POINTER (name));
+      print_candidates (value);
       return error_mark_node;
     }
 
index 6c046ed..3b88c40 100644 (file)
@@ -870,6 +870,7 @@ lookup_field (xbasetype, name, protect, want_type)
   tree entry, binfo, binfo_h;
   tree own_access = access_default_node;
   int vbase_name_p = VBASE_NAME_P (name);
+  tree ambiguous = NULL_TREE;
 
   /* rval_binfo is the binfo associated with the found member, note,
      this can be set with useful information, even when rval is not
@@ -986,6 +987,7 @@ lookup_field (xbasetype, name, protect, want_type)
       tree binfos = BINFO_BASETYPES (binfo);
       int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
       tree nval;
+      int idx = -1;
 
       /* Process and/or queue base types.  */
       for (i = 0; i < n_baselinks; i++)
@@ -1040,7 +1042,7 @@ lookup_field (xbasetype, name, protect, want_type)
 
       nval = lookup_field_1 (type, name);
 
-      if (nval || lookup_fnfields_here (type, name)>=0)
+      if (nval || (idx = lookup_fnfields_here (type, name)) >= 0)
        {
          if (nval && nval == rval && SHARED_MEMBER_P (nval))
            {
@@ -1074,10 +1076,20 @@ lookup_field (xbasetype, name, protect, want_type)
            }
          else
            {
-             /* This is ambiguous.  */
-             errstr = "request for member `%D' is ambiguous";
-             protect += 2;
-             break;
+             /* This is ambiguous. Remember it. */
+             if (! ambiguous)
+               {
+                 errstr = "request for member `%D' is ambiguous";
+                 protect += 2;
+                 if (rval)
+                   ambiguous = scratch_tree_cons (NULL_TREE, rval, ambiguous);
+               }
+             if (! nval)
+               {
+                 nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
+                 nval = OVL_CURRENT (nval);
+               }
+              ambiguous = scratch_tree_cons (NULL_TREE, nval, ambiguous);
            }
        }
     }
@@ -1176,6 +1188,8 @@ lookup_field (xbasetype, name, protect, want_type)
   if (errstr && protect)
     {
       cp_error (errstr, name, type);
+      if (ambiguous)
+        print_candidates (ambiguous);
       rval = error_mark_node;
     }
 
index fd6f3d0..076197a 100644 (file)
@@ -855,7 +855,8 @@ finish_call_expr (fn, args, koenig)
   result = build_x_function_call (fn, args, current_class_ref);
 
   if (TREE_CODE (result) == CALL_EXPR
-      && TREE_TYPE (result) != void_type_node)
+      && (! TREE_TYPE (result)
+          || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
     result = require_complete_type (result);
 
   return result;
index 9a99097..463fcd4 100644 (file)
@@ -90,7 +90,7 @@ require_complete_type (value)
 {
   tree type;
 
-  if (processing_template_decl)
+  if (processing_template_decl || value == error_mark_node)
     return value;
 
   if (TREE_CODE (value) == OVERLOAD)
@@ -100,7 +100,7 @@ require_complete_type (value)
 
   /* First, detect a valid value with a complete type.  */
   if (TYPE_SIZE (type) != 0
-      && type != void_type_node
+      && TYPE_SIZE (type) != size_zero_node
       && ! (TYPE_LANG_SPECIFIC (type)
            && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))
            && TYPE_SIZE (SIGNATURE_TYPE (type)) == 0))
@@ -122,12 +122,105 @@ require_complete_type (value)
       return require_complete_type (value);
     }
 
-  if (complete_type_or_else (type))
+  if (complete_type_or_else (type, value))
     return value;
   else
     return error_mark_node;
 }
 
+/* Makes sure EXPR is a complete type when used in a void context, like a
+   whole expression, or lhs of a comma operator. Issue a diagnostic and
+   return error_mark_node on failure. This is a little tricky, because some
+   valid void types look stunningly similar to invalid void types. We err on
+   the side of caution */
+
+tree
+require_complete_type_in_void (expr)
+     tree expr;
+{
+  switch (TREE_CODE (expr))
+    {
+    case COND_EXPR:
+      {
+        tree op;
+        
+        op = TREE_OPERAND (expr,2);
+        op = require_complete_type_in_void (op);
+        TREE_OPERAND (expr,2) = op;
+        if (op == error_mark_node)
+          {
+            expr = op;
+            break;
+          }
+        
+        /* fallthrough */
+      }
+    
+    case COMPOUND_EXPR:
+      {
+        tree op;
+        
+        op = TREE_OPERAND (expr,1);
+        op = require_complete_type_in_void (op);
+        TREE_OPERAND (expr,1) = op;
+        if (op == error_mark_node)
+          {
+            expr = op;
+            break;
+          }
+        
+        break;
+      }
+    
+    case NON_LVALUE_EXPR:
+    case NOP_EXPR:
+      {
+        tree op;
+        
+        op = TREE_OPERAND (expr,0);
+        op = require_complete_type_in_void (op);
+        TREE_OPERAND (expr,0) = op;
+        if (op == error_mark_node)
+          {
+            expr = op;
+            break;
+          }
+        break;
+      }
+    
+    case CALL_EXPR:   /* function call return can be ignored */
+    case RTL_EXPR:    /* RTL nodes have no value */
+    case DELETE_EXPR: /* delete expressions have no type */
+    case VEC_DELETE_EXPR:
+    case INTEGER_CST: /* used for null pointer */
+    case EXIT_EXPR:   /* have no return */
+    case LOOP_EXPR:   /* have no return */
+    case BIND_EXPR:   /* have no return */
+    case THROW_EXPR:  /* have no return */
+    case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
+    case CONVERT_EXPR:  /* sometimes has a void type */
+      break;
+    
+    case INDIRECT_REF:
+      {
+        tree op = TREE_OPERAND (expr,0);
+        
+        /* Calling a function returning a reference has an implicit
+           dereference applied. We don't want to make that an error. */
+        if (TREE_CODE (op) == CALL_EXPR
+            && TREE_CODE (TREE_TYPE (op)) == REFERENCE_TYPE)
+          break;
+        /* else fallthrough */
+      }
+    
+    default:
+      expr = require_complete_type (expr);
+      break;
+    }
+
+  return expr;
+}
+
 /* Try to complete TYPE, if it is incomplete.  For example, if TYPE is
    a template instantiation, do the instantiation.  Returns TYPE,
    whether or not it could be completed, unless something goes
@@ -161,20 +254,21 @@ complete_type (type)
 }
 
 /* Like complete_type, but issue an error if the TYPE cannot be
-   completed.  Returns NULL_TREE if the type cannot be made 
-   complete.  */
+   completed.  VALUE is used for informative diagnostics.
+   Returns NULL_TREE if the type cannot be made complete.  */
 
 tree
-complete_type_or_else (type)
+complete_type_or_else (type, value)
      tree type;
+     tree value;
 {
   type = complete_type (type);
   if (type == error_mark_node)
     /* We already issued an error.  */
     return NULL_TREE;
-  else if (!TYPE_SIZE (type))
+  else if (!TYPE_SIZE (type) || TYPE_SIZE (type) == size_zero_node)
     {
-      incomplete_type_error (NULL_TREE, type);
+      incomplete_type_error (value, type);
       return NULL_TREE;
     }
   else
@@ -1997,7 +2091,7 @@ build_component_ref (datum, component, basetype_path, protect)
       return error_mark_node;
     }
 
-  if (!complete_type_or_else (basetype))
+  if (!complete_type_or_else (basetype, datum))
     return error_mark_node;
 
   if (TREE_CODE (component) == BIT_NOT_EXPR)
@@ -2928,7 +3022,7 @@ build_function_call_real (function, params, require_complete, flags)
 
     if (require_complete)
       {
-       if (value_type == void_type_node)
+       if (TREE_CODE (value_type) == VOID_TYPE)
          return result;
        result = require_complete_type (result);
       }
@@ -3003,7 +3097,7 @@ convert_arguments (typelist, values, fndecl, flags)
        {
          if (fndecl)
            {
-             cp_error_at ("too many arguments to %s `%+D'", called_thing,
+             cp_error_at ("too many arguments to %s `%+#D'", called_thing,
                           fndecl);
              error ("at this point in file");
            }
@@ -3032,8 +3126,6 @@ convert_arguments (typelist, values, fndecl, flags)
              || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
              || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
            val = default_conversion (val);
-
-         val = require_complete_type (val);
        }
 
       if (val == error_mark_node)
@@ -3108,9 +3200,8 @@ convert_arguments (typelist, values, fndecl, flags)
        {
          if (fndecl)
            {
-             char *buf = (char *)alloca (32 + strlen (called_thing));
-             sprintf (buf, "too few arguments to %s `%%#D'", called_thing);
-             cp_error_at (buf, fndecl);
+             cp_error_at ("too few arguments to %s `%+#D'",
+                          called_thing, fndecl);
              error ("at this point in file");
            }
          else
@@ -3990,7 +4081,7 @@ pointer_int_sum (resultcode, ptrop, intop)
 
   register tree result_type = TREE_TYPE (ptrop);
 
-  if (!complete_type_or_else (result_type))
+  if (!complete_type_or_else (result_type, ptrop))
     return error_mark_node;
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
@@ -4082,7 +4173,7 @@ pointer_diff (op0, op1, ptrtype)
   tree restype = ptrdiff_type_node;
   tree target_type = TREE_TYPE (ptrtype);
 
-  if (!complete_type_or_else (target_type))
+  if (!complete_type_or_else (target_type, NULL_TREE))
     return error_mark_node;
 
   if (pedantic || warn_pointer_arith)
@@ -5272,6 +5363,7 @@ build_compound_expr (list)
      tree list;
 {
   register tree rest;
+  tree first;
 
   if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
     TREE_VALUE (list) = decl_constant_value (TREE_VALUE (list));
@@ -5291,14 +5383,21 @@ build_compound_expr (list)
        return TREE_VALUE (list);
     }
 
+  first = TREE_VALUE (list);
+  first = require_complete_type_in_void (first);
+  if (first == error_mark_node)
+    return error_mark_node;
+  
   rest = build_compound_expr (TREE_CHAIN (list));
+  if (rest == error_mark_node)
+    return error_mark_node;
 
   /* When pedantic, a compound expression cannot be a constant expression.  */
-  if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
+  if (! TREE_SIDE_EFFECTS (first) && ! pedantic)
     return rest;
 
   return build (COMPOUND_EXPR, TREE_TYPE (rest),
-               break_out_cleanups (TREE_VALUE (list)), rest);
+               break_out_cleanups (first), rest);
 }
 
 tree
@@ -5670,7 +5769,13 @@ build_c_cast (type, expr)
     warning ("cast to pointer from integer of different size");
 #endif
 
-  if (TREE_CODE (type) == REFERENCE_TYPE)
+  if (TREE_CODE (type) == VOID_TYPE)
+    {
+      value = require_complete_type_in_void (value);
+      if (value != error_mark_node)
+        value = build1 (CONVERT_EXPR, void_type_node, value);
+    }
+  else if (TREE_CODE (type) == REFERENCE_TYPE)
     value = (convert_from_reference
             (convert_to_reference (type, value, CONV_C_CAST,
                                    LOOKUP_COMPLAIN, NULL_TREE)));
@@ -6954,11 +7059,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
       return rhs;
     }      
 
-  rhs = require_complete_type (rhs);
-  if (rhs == error_mark_node)
-    return error_mark_node;
-
-  if (exp != 0) exp = require_complete_type (exp);
+  if (exp != 0)
+    exp = require_complete_type (exp);
   if (exp == error_mark_node)
     return error_mark_node;
 
@@ -7158,7 +7260,7 @@ c_expand_return (retval)
   if (retval == result
       || DECL_CONSTRUCTOR_P (current_function_decl))
     /* It's already done for us.  */;
-  else if (TREE_TYPE (retval) == void_type_node)
+  else if (TREE_CODE (TREE_TYPE (retval)) == VOID_TYPE)
     {
       pedwarn ("return of void value in function returning non-void");
       expand_expr_stmt (retval);
index dc9695e..f002bc0 100644 (file)
@@ -1,6 +1,6 @@
 /* Report error messages, build initializers, and perform
    some front-end optimizations for C++ compiler.
-   Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -213,55 +213,62 @@ incomplete_type_error (value, type)
      tree value;
      tree type;
 {
-  char *errmsg = 0;
-
   /* Avoid duplicate error message.  */
   if (TREE_CODE (type) == ERROR_MARK)
     return;
 
-  if (value != 0 && (TREE_CODE (value) == VAR_DECL
-                    || TREE_CODE (value) == PARM_DECL))
-    cp_error ("`%D' has incomplete type", value);
-  else
-    {
-    retry:
-      /* We must print an error message.  Be clever about what it says.  */
-
-      switch (TREE_CODE (type))
-       {
-       case RECORD_TYPE:
-       case UNION_TYPE:
-       case ENUMERAL_TYPE:
-         errmsg = "invalid use of undefined type `%#T'";
-         break;
+retry:
+  /* We must print an error message.  Be clever about what it says.  */
 
-       case VOID_TYPE:
-         error ("invalid use of void expression");
-         return;
+  switch (TREE_CODE (type))
+    {
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case ENUMERAL_TYPE:
+      cp_error ("invalid use of undefined type `%#T'", type);
+      cp_error_at ("forward declaration of `%#T'", type);
+      break;
 
-       case ARRAY_TYPE:
-         if (TYPE_DOMAIN (type))
-           {
-             type = TREE_TYPE (type);
-             goto retry;
-           }
-         error ("invalid use of array with unspecified bounds");
-         return;
+    case VOID_TYPE:
+      cp_error ("invalid use of void expression");
+      break;
 
-       case OFFSET_TYPE:
-         error ("invalid use of member type (did you forget the `&' ?)");
-         return;
+    case ARRAY_TYPE:
+      if (TYPE_DOMAIN (type))
+        {
+          type = TREE_TYPE (type);
+          goto retry;
+        }
+      cp_error ("invalid use of array with unspecified bounds");
+      break;
 
-       case TEMPLATE_TYPE_PARM:
-         error ("invalid use of template type parameter");
-         return;
+    case OFFSET_TYPE:
+    bad_member:
+      cp_error ("invalid use of member (did you forget the `&' ?)");
+      break;
 
-       default:
-         my_friendly_abort (108);
-       }
+    case TEMPLATE_TYPE_PARM:
+      cp_error ("invalid use of template type parameter");
+      break;
 
-      cp_error (errmsg, type);
+    case UNKNOWN_TYPE:
+      if (value && TREE_CODE (value) == COMPONENT_REF)
+        goto bad_member;
+      else if (value && TREE_CODE (value) == ADDR_EXPR)
+        cp_error ("address of overloaded function with no contextual type information");
+      else if (value && TREE_CODE (value) == OVERLOAD)
+        cp_error ("overloaded function with no contextual type information");
+      else
+        cp_error ("insufficient contextual information to determine type");
+      break;
+    
+    default:
+      my_friendly_abort (108);
     }
+
+  if (value != 0 && (TREE_CODE (value) == VAR_DECL
+                    || TREE_CODE (value) == PARM_DECL))
+    cp_error_at ("incomplete `%D' defined here", value);
 }
 
 /* Like error(), but don't call report_error_function().  */