typeck.c (complete_type_or_else): Add VALUE arg, for helpful diagnostics.

* 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
This commit is contained in:
Nathan Sidwell 1999-02-26 23:37:04 +00:00 committed by Jason Merrill
parent 99f25d8ea8
commit 6654316990
13 changed files with 277 additions and 113 deletions

View 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

View 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)))

View 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

View 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));

View 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

View 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. */

View 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;

View 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;

View 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;
}

View 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;
}

View 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;

View 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);

View 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;
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:
cp_error ("invalid use of undefined type `%#T'", type);
cp_error_at ("forward declaration of `%#T'", type);
break;
case VOID_TYPE:
cp_error ("invalid use of void expression");
break;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
type = TREE_TYPE (type);
goto retry;
}
cp_error ("invalid use of array with unspecified bounds");
break;
case OFFSET_TYPE:
bad_member:
cp_error ("invalid use of member (did you forget the `&' ?)");
break;
case TEMPLATE_TYPE_PARM:
cp_error ("invalid use of template type parameter");
break;
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 ("`%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;
case VOID_TYPE:
error ("invalid use of void expression");
return;
case ARRAY_TYPE:
if (TYPE_DOMAIN (type))
{
type = TREE_TYPE (type);
goto retry;
}
error ("invalid use of array with unspecified bounds");
return;
case OFFSET_TYPE:
error ("invalid use of member type (did you forget the `&' ?)");
return;
case TEMPLATE_TYPE_PARM:
error ("invalid use of template type parameter");
return;
default:
my_friendly_abort (108);
}
cp_error (errmsg, type);
}
cp_error_at ("incomplete `%D' defined here", value);
}
/* Like error(), but don't call report_error_function(). */