+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
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 = " ";
}
/* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg);
+ arg = require_complete_type (arg);
+
return arg;
}
}
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)))
{
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
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));
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
/* 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. */
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;
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)
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;
{
error ("request for member `%s' is ambiguous in multiple inheritance lattice",
IDENTIFIER_POINTER (name));
+ print_candidates (value);
return error_mark_node;
}
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
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++)
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))
{
}
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);
}
}
}
if (errstr && protect)
{
cp_error (errstr, name, type);
+ if (ambiguous)
+ print_candidates (ambiguous);
rval = error_mark_node;
}
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;
{
tree type;
- if (processing_template_decl)
+ if (processing_template_decl || value == error_mark_node)
return value;
if (TREE_CODE (value) == OVERLOAD)
/* 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))
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
}
/* 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
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)
if (require_complete)
{
- if (value_type == void_type_node)
+ if (TREE_CODE (value_type) == VOID_TYPE)
return result;
result = require_complete_type (result);
}
{
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");
}
|| 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)
{
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
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)
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)
tree list;
{
register tree rest;
+ tree first;
if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
TREE_VALUE (list) = decl_constant_value (TREE_VALUE (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
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)));
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;
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);
/* 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.
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(). */