PATCH: ice108, g++.bugs/900428_01.C
Nathan Sidwell
nathan@acm.org
Tue Feb 16 02:03:00 GMT 1999
Hi,
attached is a patch (against the 19990208 snapshot) which started as a bug hunt
for ICE108. In fixing that and the resulting cascade of later ICE's, I
discovered that egcs is rather schizoprhenic about what it considers an
incomplete type. require_complete_type would return OK, even if the type is not
known (and possibly incomplete).
This patch fixes ice108, caused by passing an ambiguous overloaded function
address to a varadic function, and fixes the XFAILS on g++.bugs/900428_01.C.
Those are failures to diagnose dereferencing an incomplete type in a void
context. In addition, it adds diagnostics to all cases where an expression of
incomplete or unknown type is used in a void context.
convert_for_initialization, convert_arguments were both being over eager on
checking for an incomplete type. Those checks have been removed.
convert_for_assignment does the right thing, checking for a complete type after
overload disambiguation has occured. convert_for_ellipsis was not checking for
a complete type, and hence passing an ambiguous overloaded function address
caused the RTL converter to die horribly.
I have added an extra argument to complete_type_or_else, this does not change
the behaviour, but allows a more informative diagnostic in the case of an
incomplete type.
I have modified incomplete_type_error to show the location of any forwardly
declared type, which is not yet defined. It also now deals with UNKNOWN_TYPE
nodes, and can therefore deal with ambiguous overloaded function addresses.
I have changed require_complete_type to consider any type with a TYPE_SIZE of
size_zero_node to be incomplete. Without this, it would consider certain
incomplete types to be complete.
I have added a new function, require_complete_type_in_void to check that we are
correctly dealing with a complete type in a void context. This was currently
not being thoroughly checked. (the 900428_01 XFAILS). The only complication
here is that it is legitimate to return an incomplete reference from a function
call, but not dereference a pointer to an incomplete type returned from a
function call.
I have corrected the places where egcs was not dealing with qualified void
returns from function calls. These should be treated in the same way as plain
void.
The patches cause a number of changes in the testsuite, the 90042801 XFAILS
become PASSES. A number of other testcases fail with excess errors solely due
to the changes in incomplete_type_error. The patch includes amendments to all
those tests, to mark were new ERRORs are expected.
Here are the old and new check.g++ highlights for this sparc-sun-solaris-2.6
box
-- unpatched
FAIL: g++.brendan/asm-extn1.C caused compiler crash
FAIL: g++.pt/expr3.C (test for excess errors)
=== g++ Summary ===
# of expected passes 4845
# of unexpected failures 2
# of expected failures 88
# of untested testcases 6
--patched
FAIL: g++.brendan/asm-extn1.C caused compiler crash
FAIL: g++.pt/expr3.C (test for excess errors)
=== g++ Summary ===
# of expected passes 4872
# of unexpected failures 2
# of expected failures 70
# of untested testcases 6
I also include two additional test cases. the first, ice108.C, causes that ICE
without the patch (hidden in a `confused by previous errors' message, but you
get a naked ice108 if you remove the previous lines). The second, return.C,
contains undiagnosed errors. The testsuite output does not include these two
additional testcases.
Enjoy
nathan
--
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
You can up the bandwidth, but you can't up the speed of light
nathan@acm.org http://www.cs.bris.ac.uk/~nathan/ nathan@cs.bris.ac.uk
egcs/gcc/cp/ChangeLog:
Mon Feb 15 14:40:43 GMT 1999 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.
* pt.c (tsubst): 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.
* 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.
Index: egcs/gcc/cp/call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.130
diff -c -3 -p -r1.130 call.c
*** call.c 1999/01/25 20:43:13 1.130
--- call.c 1999/02/12 19:59:17
*************** convert_arg_to_ellipsis (arg)
*** 3175,3180 ****
--- 3175,3182 ----
/* Convert `short' and `char' to full-size `int'. */
arg = default_conversion (arg);
+ arg = require_complete_type (arg);
+
return arg;
}
*************** build_over_call (cand, args, flags)
*** 3515,3521 ****
}
fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
! if (TREE_TYPE (fn) == void_type_node)
return fn;
fn = require_complete_type (fn);
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
--- 3517,3523 ----
}
fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
! if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
return fn;
fn = require_complete_type (fn);
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
Index: egcs/gcc/cp/decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.306
diff -c -3 -p -r1.306 decl.c
*** decl.c 1999/02/05 02:42:48 1.306
--- decl.c 1999/02/12 19:59:25
*************** cplus_expand_expr_stmt (exp)
*** 14359,14396 ****
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
! if (TREE_TYPE (exp) == unknown_type_node)
{
! 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");
}
- 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);
#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);
! /* 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. */
--- 14359,14388 ----
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
! exp = require_complete_type_in_void (exp);
!
! 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);
#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);
! /* 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: egcs/gcc/cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.180
diff -c -3 -p -r1.180 decl2.c
*** decl2.c 1999/02/07 15:44:08 1.180
--- decl2.c 1999/02/12 19:59:26
*************** reparse_absdcl_as_expr (type, decl)
*** 3513,3519 ****
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
! if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
decl = require_complete_type (decl);
return decl;
--- 3513,3521 ----
decl = build_x_function_call (decl, NULL_TREE, current_class_ref);
! if (TREE_CODE (decl) == CALL_EXPR
! && (! TREE_TYPE (decl)
! || TREE_CODE (TREE_TYPE (decl)) != VOID_TYPE))
decl = require_complete_type (decl);
return decl;
Index: egcs/gcc/cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.87
diff -c -3 -p -r1.87 init.c
*** init.c 1999/01/26 20:23:34 1.87
--- init.c 1999/02/12 19:59:28
*************** build_new_1 (exp)
*** 2163,2169 ****
true_type = TREE_TYPE (true_type);
}
! if (!complete_type_or_else (true_type))
return error_mark_node;
if (has_array)
--- 2163,2169 ----
true_type = TREE_TYPE (true_type);
}
! if (!complete_type_or_else (true_type, exp))
return error_mark_node;
if (has_array)
*************** build_delete (type, addr, auto_delete, f
*** 3014,3020 ****
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (type));
! if (!complete_type_or_else (type))
return error_mark_node;
if (TREE_CODE (type) == ARRAY_TYPE)
goto handle_array;
--- 3014,3020 ----
if (TREE_CODE (type) == POINTER_TYPE)
{
type = TYPE_MAIN_VARIANT (TREE_TYPE (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: egcs/gcc/cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.258
diff -c -3 -p -r1.258 pt.c
*** pt.c 1999/02/07 15:44:10 1.258
--- pt.c 1999/02/12 19:59:33
*************** tsubst (t, args, in_decl)
*** 6099,6105 ****
it's a partial instantiation. */
if (!uses_template_parms (ctx)
&& !TYPE_BEING_DEFINED (ctx)
! && !complete_type_or_else (ctx))
return error_mark_node;
f = make_typename_type (ctx, f);
--- 6099,6105 ----
it's a partial instantiation. */
if (!uses_template_parms (ctx)
&& !TYPE_BEING_DEFINED (ctx)
! && !complete_type_or_else (ctx, NULL_TREE))
return error_mark_node;
f = make_typename_type (ctx, f);
Index: egcs/gcc/cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.40
diff -c -3 -p -r1.40 semantics.c
*** semantics.c 1999/01/20 13:11:59 1.40
--- semantics.c 1999/02/12 19:59:34
*************** finish_call_expr (fn, args, koenig)
*** 855,861 ****
result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
! && TREE_TYPE (result) != void_type_node)
result = require_complete_type (result);
return result;
--- 855,862 ----
result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
! && (! TREE_TYPE (result)
! || TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
result = require_complete_type (result);
return result;
Index: egcs/gcc/cp/typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.138
diff -c -3 -p -r1.138 typeck.c
*** typeck.c 1999/01/26 00:50:29 1.138
--- typeck.c 1999/02/12 19:59:39
*************** require_complete_type (value)
*** 100,106 ****
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
! && type != void_type_node
&& ! (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))
&& TYPE_SIZE (SIGNATURE_TYPE (type)) == 0))
--- 100,106 ----
/* First, detect a valid value with a complete type. */
if (TYPE_SIZE (type) != 0
! && TYPE_SIZE (type) != size_zero_node
&& ! (TYPE_LANG_SPECIFIC (type)
&& (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))
&& TYPE_SIZE (SIGNATURE_TYPE (type)) == 0))
*************** require_complete_type (value)
*** 122,133 ****
return require_complete_type (value);
}
! if (complete_type_or_else (type))
return value;
else
return error_mark_node;
}
/* 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
--- 122,226 ----
return require_complete_type (value);
}
! 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
*************** complete_type (type)
*** 161,180 ****
}
/* Like complete_type, but issue an error if the TYPE cannot be
! completed. Returns NULL_TREE if the type cannot be made
! complete. */
tree
! complete_type_or_else (type)
tree type;
{
type = complete_type (type);
if (type == error_mark_node)
/* We already issued an error. */
return NULL_TREE;
! else if (!TYPE_SIZE (type))
{
! incomplete_type_error (NULL_TREE, type);
return NULL_TREE;
}
else
--- 254,274 ----
}
/* Like complete_type, but issue an error if the TYPE cannot be
! completed. VALUE is used for informative diagnostics.
! Returns NULL_TREE if the type cannot be made complete. */
tree
! 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) || TYPE_SIZE (type) == size_zero_node)
{
! incomplete_type_error (value, type);
return NULL_TREE;
}
else
*************** build_component_ref (datum, component, b
*** 1996,2002 ****
return error_mark_node;
}
! if (!complete_type_or_else (basetype))
return error_mark_node;
if (TREE_CODE (component) == BIT_NOT_EXPR)
--- 2090,2096 ----
return error_mark_node;
}
! if (!complete_type_or_else (basetype, datum))
return error_mark_node;
if (TREE_CODE (component) == BIT_NOT_EXPR)
*************** build_function_call_real (function, para
*** 2927,2933 ****
if (require_complete)
{
! if (value_type == void_type_node)
return result;
result = require_complete_type (result);
}
--- 3021,3027 ----
if (require_complete)
{
! if (TREE_CODE (value_type) == VOID_TYPE)
return result;
result = require_complete_type (result);
}
*************** convert_arguments (typelist, values, fnd
*** 3002,3008 ****
{
if (fndecl)
{
! cp_error_at ("too many arguments to %s `%+D'", called_thing,
fndecl);
error ("at this point in file");
}
--- 3096,3102 ----
{
if (fndecl)
{
! cp_error_at ("too many arguments to %s `%+#D'", called_thing,
fndecl);
error ("at this point in file");
}
*************** convert_arguments (typelist, values, fnd
*** 3031,3038 ****
|| 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)
--- 3125,3130 ----
*************** convert_arguments (typelist, values, fnd
*** 3107,3115 ****
{
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);
error ("at this point in file");
}
else
--- 3199,3206 ----
{
if (fndecl)
{
! cp_error_at ("too few arguments to %s `%+#D'",
! called_thing, fndecl);
error ("at this point in file");
}
else
*************** pointer_int_sum (resultcode, ptrop, into
*** 3989,3995 ****
register tree result_type = TREE_TYPE (ptrop);
! if (!complete_type_or_else (result_type))
return error_mark_node;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
--- 4080,4086 ----
register tree result_type = TREE_TYPE (ptrop);
! if (!complete_type_or_else (result_type, ptrop))
return error_mark_node;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
*************** pointer_diff (op0, op1, ptrtype)
*** 4081,4087 ****
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
! if (!complete_type_or_else (target_type))
return error_mark_node;
if (pedantic || warn_pointer_arith)
--- 4172,4178 ----
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
! if (!complete_type_or_else (target_type, NULL_TREE))
return error_mark_node;
if (pedantic || warn_pointer_arith)
*************** build_compound_expr (list)
*** 5294,5299 ****
--- 5385,5391 ----
tree list;
{
register tree rest;
+ tree first;
if (TREE_READONLY_DECL_P (TREE_VALUE (list)))
TREE_VALUE (list) = decl_constant_value (TREE_VALUE (list));
*************** build_compound_expr (list)
*** 5313,5326 ****
return TREE_VALUE (list);
}
rest = build_compound_expr (TREE_CHAIN (list));
/* When pedantic, a compound expression cannot be a constant expression. */
! if (! TREE_SIDE_EFFECTS (TREE_VALUE (list)) && ! pedantic)
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest),
! break_out_cleanups (TREE_VALUE (list)), rest);
}
tree
--- 5405,5425 ----
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 (first) && ! pedantic)
return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest),
! break_out_cleanups (first), rest);
}
tree
*************** build_c_cast (type, expr)
*** 5692,5698 ****
warning ("cast to pointer from integer of different size");
#endif
! if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
(convert_to_reference (type, value, CONV_C_CAST,
LOOKUP_COMPLAIN, NULL_TREE)));
--- 5791,5799 ----
warning ("cast to pointer from integer of different size");
#endif
! if (TREE_CODE (type) == VOID_TYPE)
! value = require_complete_type_in_void (value);
! else if (TREE_CODE (type) == REFERENCE_TYPE)
value = (convert_from_reference
(convert_to_reference (type, value, CONV_C_CAST,
LOOKUP_COMPLAIN, NULL_TREE)));
*************** convert_for_initialization (exp, type, r
*** 6973,6984 ****
}
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 == error_mark_node)
return error_mark_node;
--- 7074,7082 ----
}
return rhs;
}
! if (exp != 0)
! exp = require_complete_type (exp);
if (exp == error_mark_node)
return error_mark_node;
*************** c_expand_return (retval)
*** 7178,7184 ****
if (retval == result
|| DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
! else if (TREE_TYPE (retval) == void_type_node)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
--- 7276,7282 ----
if (retval == result
|| DECL_CONSTRUCTOR_P (current_function_decl))
/* It's already done for us. */;
! else if (TREE_CODE (TREE_TYPE (retval)) == VOID_TYPE)
{
pedwarn ("return of void value in function returning non-void");
expand_expr_stmt (retval);
Index: egcs/gcc/cp/typeck2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck2.c,v
retrieving revision 1.49
diff -c -3 -p -r1.49 typeck2.c
*** typeck2.c 1999/02/06 17:12:29 1.49
--- typeck2.c 1999/02/12 19:59:40
***************
*** 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.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
--- 1,6 ----
/* Report error messages, build initializers, and perform
some front-end optimizations for C++ compiler.
! 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.
*************** incomplete_type_error (value, type)
*** 213,267 ****
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;
!
! 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);
}
}
/* Like error(), but don't call report_error_function(). */
--- 213,274 ----
tree value;
tree type;
{
/* 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_at ("incomplete `%D' defined here", value);
}
/* Like error(), but don't call report_error_function(). */
Index: egcs/gcc/cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.195
diff -c -3 -p -r1.195 cp-tree.h
*** cp-tree.h 1999/02/07 15:44:05 1.195
--- cp-tree.h 1999/02/12 19:59:43
*************** extern int string_conv_p PROTO((tree,
*** 3322,3329 ****
extern tree condition_conversion PROTO((tree));
extern tree target_type PROTO((tree));
extern tree require_complete_type PROTO((tree));
extern tree complete_type PROTO((tree));
! extern tree complete_type_or_else PROTO((tree));
extern int type_unknown_p PROTO((tree));
extern int fntype_p PROTO((tree));
extern tree commonparms PROTO((tree, tree));
--- 3322,3330 ----
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, tree));
extern int type_unknown_p PROTO((tree));
extern int fntype_p PROTO((tree));
extern tree commonparms PROTO((tree, tree));
Index: egcs/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.bugs/900121_01.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 900121_01.C
*** 900121_01.C 1998/12/16 21:28:20 1.2
--- 900121_01.C 1999/02/12 19:59:43
***************
*** 6,12 ****
// keywords: abort, incomplete types, reference types, formal parameters
! struct s0;
void function (struct s0 &arg1, struct s0 &arg2)
{
--- 6,12 ----
// keywords: abort, incomplete types, reference types, formal parameters
! struct s0; // ERROR - forward declaration
void function (struct s0 &arg1, struct s0 &arg2)
{
Index: egcs/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.bugs/900214_01.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 900214_01.C
*** 900214_01.C 1998/12/16 21:28:53 1.2
--- 900214_01.C 1999/02/12 19:59:43
***************
*** 7,13 ****
// keywords: friends, incomplete types, function members
! struct A;
struct B {
friend void A::foo(); // ERROR - type A is incomplete
--- 7,13 ----
// keywords: friends, incomplete types, function members
! struct A; // ERROR - forward declaration
struct B {
friend void A::foo(); // ERROR - type A is incomplete
Index: egcs/gcc/testsuite/g++.old-deja/g++.bugs/900428_01.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.bugs/900428_01.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 900428_01.C
*** 900428_01.C 1998/12/16 21:29:34 1.2
--- 900428_01.C 1999/02/12 19:59:43
*************** int i;
*** 17,51 ****
void *pv;
volatile void *pvv;
! struct s;
! extern struct s es, *ps;
! extern volatile struct s evs, *pvs;
void pv_test ()
{
! *pv; // ERROR - , XFAIL *-*-*
! (i ? *pv : *pv); // ERROR - , XFAIL *-*-*
! *pv, *pv; // ERROR - , XFAIL *-*-*
!
! *pvv; // ERROR - , XFAIL *-*-*
! (i ? *pvv : *pvv); // ERROR - , XFAIL *-*-*
! *pvv, *pvv; // ERROR - , XFAIL *-*-*
!
! es; // ERROR - , XFAIL *-*-*
! (i ? es : es); // ERROR - , XFAIL *-*-*
! es, es; // ERROR - , XFAIL *-*-*
!
! evs; // ERROR - , XFAIL *-*-*
! (i ? evs : evs); // ERROR - , XFAIL *-*-*
! evs, evs; // ERROR - , XFAIL *-*-*
!
! *ps; // ERROR - , XFAIL *-*-*
! (i ? *ps : *ps); // ERROR - , XFAIL *-*-*
! *ps, *ps; // ERROR - , XFAIL *-*-*
!
! *pvs; // ERROR - , XFAIL *-*-*
! (i ? *pvs : *pvs); // ERROR - , XFAIL *-*-*
! *pvs, *pvs; // ERROR - , XFAIL *-*-*
}
int main () { return 0; }
--- 17,51 ----
void *pv;
volatile void *pvv;
! struct s; // ERROR - forward declaration
! extern struct s es, *ps; // ERROR - defined here
! extern volatile struct s evs, *pvs; // ERROR - defined here
void pv_test ()
{
! *pv; // ERROR - invalid void
! (i ? *pv : *pv); // ERROR - invalid void
! *pv, *pv; // ERROR - invalid void
!
! *pvv; // ERROR - invalid void
! (i ? *pvv : *pvv); // ERROR - invalid void
! *pvv, *pvv; // ERROR - invalid void
!
! es; // ERROR - incomplete
! (i ? es : es); // ERROR - undefined type
! es, es; // ERROR - incomplete
!
! evs; // ERROR - incomplete
! (i ? evs : evs); // ERROR - undefined type
! evs, evs; // ERROR - incomplete
!
! *ps; // ERROR - undefined type
! (i ? *ps : *ps); // ERROR - undefined type
! *ps, *ps; // ERROR - undefined type
!
! *pvs; // ERROR - undefined type
! (i ? *pvs : *pvs); // ERROR - undefined type
! *pvs, *pvs; // ERROR - undefined type
}
int main () { return 0; }
Index: egcs/gcc/testsuite/g++.old-deja/g++.mike/p7868.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.mike/p7868.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 p7868.C
*** p7868.C 1998/12/16 21:48:24 1.2
--- p7868.C 1999/02/12 19:59:43
***************
*** 4,16 ****
struct DIAGTYP {
};
struct DIAGTYP1 {
! struct DIAGTYP;
void bar() { new struct DIAGTYP; } // ERROR - undefined
void foo() { new struct DIAGTYP1; }
};
int main () {
! struct DIAGTYP;
struct DIAGTYP *lerror_desc;
lerror_desc= new struct DIAGTYP; // ERROR - undefined
}
--- 4,16 ----
struct DIAGTYP {
};
struct DIAGTYP1 {
! struct DIAGTYP; // ERROR - forward declaration
void bar() { new struct DIAGTYP; } // ERROR - undefined
void foo() { new struct DIAGTYP1; }
};
int main () {
! struct DIAGTYP; // ERROR - forward declaration
struct DIAGTYP *lerror_desc;
lerror_desc= new struct DIAGTYP; // ERROR - undefined
}
Index: egcs/gcc/testsuite/g++.old-deja/g++.pt/crash5.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/crash5.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 crash5.C
*** crash5.C 1998/12/16 21:54:26 1.2
--- crash5.C 1999/02/12 19:59:43
***************
*** 3,9 ****
template <class T, int i>
struct K {
void f();
! };
template <class T>
void
--- 3,9 ----
template <class T, int i>
struct K {
void f();
! }; // ERROR - forward declaration
template <class T>
void
Index: egcs/gcc/testsuite/g++.old-deja/g++.pt/typename8.C
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/testsuite/g++.old-deja/g++.pt/typename8.C,v
retrieving revision 1.2
diff -c -3 -p -r1.2 typename8.C
*** typename8.C 1998/12/16 22:02:32 1.2
--- typename8.C 1999/02/12 19:59:43
*************** public:
*** 16,22 ****
}
};
! class B : public A< B >
{
public:
typedef int myT;
--- 16,22 ----
}
};
! class B : public A< B > // ERROR - forward declaration
{
public:
typedef int myT;
More information about the Gcc-patches
mailing list