aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>1999-02-26 23:37:04 +0000
committerJason Merrill <jason@gcc.gnu.org>1999-02-26 18:37:04 -0500
commit665431699036e1b9bd2317d452579a6fc6af9482 (patch)
tree95146880bbae3e437264ebcc433d39108ea8419e
parent99f25d8ea84021f7c7887a65085342760abd0c5a (diff)
downloadgcc-665431699036e1b9bd2317d452579a6fc6af9482.zip
gcc-665431699036e1b9bd2317d452579a6fc6af9482.tar.gz
gcc-665431699036e1b9bd2317d452579a6fc6af9482.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog43
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/cp-tree.h3
-rw-r--r--gcc/cp/cvt.c7
-rw-r--r--gcc/cp/decl.c42
-rw-r--r--gcc/cp/decl2.c4
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/method.c1
-rw-r--r--gcc/cp/search.c24
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/cp/typeck.c156
-rw-r--r--gcc/cp/typeck2.c85
13 files changed, 272 insertions, 108 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 34e8ef8..8e82f27 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1e43233..9bf5035 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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)))
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3fc9cf4..c533e3e 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 62ffbf0..59a067e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index b73020f..9f29c65 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c18eab7..231a598 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index cc38dab..d53dc70 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 847222f..ea424b6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f3530dd..8546332 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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;
}
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 6c046ed..3b88c40 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fd6f3d0..076197a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 9a99097..463fcd4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index dc9695e..f002bc0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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(). */