This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
(C++) Patch to rework use of instantiate_type
- To: egcs-patches at cygnus dot com
- Subject: (C++) Patch to rework use of instantiate_type
- From: Jason Merrill <jason at cygnus dot com>
- Date: Tue, 27 Oct 1998 22:31:05 -0800
Applied. Previously, we would call instantiate_type whenever we had an
overloaded function that we wanted to resolve. This works fine if the
target type is a pointer to function, but not if the target is a class
which must be constructed. To handle that case properly, we need to let
the overloaded functions persist longer, and only resolve them if the
target is in fact a pointer to function (or such).
Mark, please take a look at the pt.c changes; I couldn't tell why the code
was the way it was, and my changes don't break anything, but maybe you had
a secret plan? :)
Fixes g++.robertl/eb43.C.
1998-10-27 Jason Merrill <jason@yorick.cygnus.com>
* call.c (standard_conversion): instantiate_type here.
(reference_binding): And here.
(implicit_conversion): Not here.
(build_op_delete_call): No need to cons up an OVERLOAD.
* cvt.c (cp_convert_to_pointer): instantiate_type here.
(convert_to_reference): And here.
* decl.c (grok_reference_init): Not here.
(grokparms): Or here.
* typeck2.c (digest_init): Or here.
* typeck.c (decay_conversion): Take the address of overloaded
functions, too.
(require_instantiated_type): Lose.
(convert_arguments): Don't handle unknown types here.
(build_c_cast): Likewise.
(build_binary_op): Gut.
(build_conditional_expr): Don't require_instantiated_type.
(build_modify_expr): Likewise.
(build_static_cast): Don't instantiate_type.
(build_reinterpret_cast): Likewise.
(build_const_cast): Likewise.
(convert_for_initialization): Likewise.
(build_ptrmemfunc): Use type_unknown_p.
(convert_for_assignment): Also do default_conversion on overloaded
functions. Hand them off to ocp_convert.
* pt.c (convert_nontype_argument): Tell instantiate_type to complain.
Do complain about overload resolution producing a non-public fn.
Index: call.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/call.c,v
retrieving revision 1.115
diff -c -p -w -r1.115 call.c
*** call.c 1998/10/23 14:52:53 1.115
--- call.c 1998/10/28 06:14:00
*************** standard_conversion (to, from, expr)
*** 803,808 ****
--- 803,817 ----
to = strip_top_quals (to);
from = strip_top_quals (from);
+ if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
+ && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
fcode = TREE_CODE (from);
tcode = TREE_CODE (to);
*************** reference_binding (rto, rfrom, expr, fla
*** 968,973 ****
--- 977,990 ----
tree from = rfrom;
int related;
+ if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
+ {
+ expr = instantiate_type (to, expr, 0);
+ if (expr == error_mark_node)
+ return NULL_TREE;
+ from = TREE_TYPE (expr);
+ }
+
if (TREE_CODE (from) == REFERENCE_TYPE)
from = TREE_TYPE (from);
else if (! expr || ! real_lvalue_p (expr))
*************** implicit_conversion (to, from, expr, fla
*** 1032,1045 ****
tree conv;
struct z_candidate *cand;
- if (expr && type_unknown_p (expr))
- {
- expr = instantiate_type (to, expr, 0);
- if (expr == error_mark_node)
- return 0;
- from = TREE_TYPE (expr);
- }
-
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
--- 1049,1054 ----
*************** build_op_delete_call (code, addr, size,
*** 2906,2916 ****
/* Strip const and volatile from addr. */
if (type != TYPE_MAIN_VARIANT (type))
addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr);
-
- /* instantiate_type will always return a plain function; pretend it's
- overloaded. */
- if (TREE_CODE (fns) == FUNCTION_DECL)
- fns = scratch_ovl_cons (fns, NULL_TREE);
fn = instantiate_type (fntype, fns, 0);
--- 2915,2920 ----
Index: class.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/class.c,v
retrieving revision 1.99
diff -c -p -w -r1.99 class.c
*** class.c 1998/10/26 23:48:52 1.99
--- class.c 1998/10/28 06:14:01
*************** validate_lhs (lhstype, complain)
*** 4968,4975 ****
try many possible instantiations, in hopes that at least one will
work.
! This function is used in build_modify_expr, convert_arguments,
! build_c_cast, and compute_conversion_costs. */
tree
instantiate_type (lhstype, rhs, complain)
--- 4968,4975 ----
try many possible instantiations, in hopes that at least one will
work.
! For non-recursive calls, LHSTYPE should be a function, pointer to
! function, or a pointer to member function. */
tree
instantiate_type (lhstype, rhs, complain)
*************** instantiate_type (lhstype, rhs, complain
*** 5132,5139 ****
{
if (complain)
cp_error("cannot resolve overloaded function `%D' "
! "based on non-function type",
! DECL_NAME (OVL_FUNCTION (rhs)));
return error_mark_node;
}
--- 5132,5139 ----
{
if (complain)
cp_error("cannot resolve overloaded function `%D' "
! "based on non-function type `%T'",
! DECL_NAME (OVL_FUNCTION (rhs)), lhstype);
return error_mark_node;
}
Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.161
diff -c -p -w -r1.161 cp-tree.h
*** cp-tree.h 1998/10/26 02:07:34 1.161
--- cp-tree.h 1998/10/28 06:14:01
*************** cp-tree.h PROTO((tree)
*** 3136,3142 ****
extern tree complete_type_or_else PROTO((tree));
extern int type_unknown_p PROTO((tree));
extern int fntype_p PROTO((tree));
- extern tree require_instantiated_type PROTO((tree, tree, tree));
extern tree commonparms PROTO((tree, tree));
extern tree original_type PROTO((tree));
extern tree common_type PROTO((tree, tree));
--- 3136,3141 ----
Index: cvt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cvt.c,v
retrieving revision 1.38
diff -c -p -w -r1.38 cvt.c
*** cvt.c 1998/10/23 14:52:57 1.38
--- cvt.c 1998/10/28 06:14:02
*************** cp_convert_to_pointer (type, expr)
*** 249,254 ****
--- 249,257 ----
return convert_to_pointer (type, expr);
}
+ if (type_unknown_p (expr))
+ return instantiate_type (type, expr, 1);
+
cp_error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
*************** convert_to_reference (reftype, expr, con
*** 406,411 ****
--- 409,420 ----
tree rval = NULL_TREE;
tree rval_as_conversion = NULL_TREE;
int i;
+
+ if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node)
+ {
+ expr = instantiate_type (type, expr, 0);
+ intype = TREE_TYPE (expr);
+ }
if (TREE_CODE (intype) == REFERENCE_TYPE)
my_friendly_abort (364);
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.247
diff -c -p -w -r1.247 decl.c
*** decl.c 1998/10/26 23:48:53 1.247
--- decl.c 1998/10/28 06:14:03
*************** grok_reference_init (decl, type, init)
*** 6921,6930 ****
return;
}
- if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
- /* decay_conversion is probably wrong for references to functions. */
- init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
-
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
--- 6921,6926 ----
*************** grokparms (first_parm, funcdef_flag)
*** 11145,11152 ****
else if (TREE_READONLY_DECL_P (init))
init = decl_constant_value (init);
}
! else
! init = require_instantiated_type (type, init, integer_zero_node);
if (! processing_template_decl
&& init != error_mark_node
&& TREE_CODE (init) != DEFAULT_ARG
--- 11141,11152 ----
else if (TREE_READONLY_DECL_P (init))
init = decl_constant_value (init);
}
! else if (TREE_TYPE (init) == NULL_TREE)
! {
! error ("argument list may not have an initializer list");
! init = error_mark_node;
! }
!
if (! processing_template_decl
&& init != error_mark_node
&& TREE_CODE (init) != DEFAULT_ARG
Index: pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.220
diff -c -p -w -r1.220 pt.c
*** pt.c 1998/10/26 02:07:46 1.220
--- pt.c 1998/10/28 06:14:04
*************** convert_nontype_argument (type, expr)
*** 2510,2516 ****
else
fns = expr;
! fn = instantiate_type (type_pointed_to, fns, 0);
if (fn == error_mark_node)
return error_mark_node;
--- 2510,2516 ----
else
fns = expr;
! fn = instantiate_type (type_pointed_to, fns, 1);
if (fn == error_mark_node)
return error_mark_node;
*************** convert_nontype_argument (type, expr)
*** 2567,2588 ****
tree fns = expr;
tree fn;
! fn = instantiate_type (type_referred_to, fns, 0);
if (!TREE_PUBLIC (fn))
{
if (really_overloaded_fn (fns))
/* Don't issue an error here; we might get a different
function if the overloading had worked out
differently. */
return error_mark_node;
else
goto bad_argument;
}
- if (fn == error_mark_node)
- return error_mark_node;
-
my_friendly_assert (comptypes (type_referred_to, TREE_TYPE (fn), 1),
0);
--- 2567,2590 ----
tree fns = expr;
tree fn;
! fn = instantiate_type (type_referred_to, fns, 1);
+ if (fn == error_mark_node)
+ return error_mark_node;
+
if (!TREE_PUBLIC (fn))
{
+ #if 0
if (really_overloaded_fn (fns))
/* Don't issue an error here; we might get a different
function if the overloading had worked out
differently. */
return error_mark_node;
else
+ #endif
goto bad_argument;
}
my_friendly_assert (comptypes (type_referred_to, TREE_TYPE (fn), 1),
0);
*************** convert_nontype_argument (type, expr)
*** 2646,2652 ****
fns = TREE_OPERAND (expr, 0);
fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)),
! fns, 0);
if (fn == error_mark_node)
return error_mark_node;
--- 2648,2654 ----
fns = TREE_OPERAND (expr, 0);
fn = instantiate_type (TREE_TYPE (TREE_TYPE (type)),
! fns, 1);
if (fn == error_mark_node)
return error_mark_node;
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.120
diff -c -p -w -r1.120 typeck.c
*** typeck.c 1998/10/26 00:48:18 1.120
--- typeck.c 1998/10/28 06:14:05
*************** fntype_p (t)
*** 206,237 ****
|| TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)));
}
- /* Do `exp = require_instantiated_type (type, exp);' to make sure EXP
- does not have an uninstantiated type.
- TYPE is type to instantiate with, if uninstantiated. */
-
- tree
- require_instantiated_type (type, exp, errval)
- tree type, exp, errval;
- {
- if (TREE_TYPE (exp) == NULL_TREE)
- {
- error ("argument list may not have an initializer list");
- return errval;
- }
-
- if (TREE_CODE (exp) == OVERLOAD
- || TREE_TYPE (exp) == unknown_type_node
- || (TREE_CODE (TREE_TYPE (exp)) == OFFSET_TYPE
- && TREE_TYPE (TREE_TYPE (exp)) == unknown_type_node))
- {
- exp = instantiate_type (type, exp, 1);
- if (TREE_TYPE (exp) == error_mark_node)
- return errval;
- }
- return exp;
- }
-
/* Return a variant of TYPE which has all the type qualifiers of LIKE
as well as those of TYPE. */
--- 206,211 ----
*************** decay_conversion (exp)
*** 1690,1702 ****
error ("void value not ignored as it ought to be");
return error_mark_node;
}
! if (code == FUNCTION_TYPE)
{
return build_unary_op (ADDR_EXPR, exp, 0);
}
! if (code == METHOD_TYPE)
{
- cp_pedwarn ("assuming & on `%E'", exp);
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
--- 1664,1676 ----
error ("void value not ignored as it ought to be");
return error_mark_node;
}
! if (code == METHOD_TYPE)
{
+ cp_pedwarn ("assuming & on `%E'", exp);
return build_unary_op (ADDR_EXPR, exp, 0);
}
! if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
{
return build_unary_op (ADDR_EXPR, exp, 0);
}
if (code == ARRAY_TYPE)
*************** convert_arguments (typelist, values, fnd
*** 3045,3069 ****
break;
}
! /* The tree type of the parameter being passed may not yet be
! known. In this case, its type is TYPE_UNKNOWN, and will
! be instantiated by the type given by TYPE. If TYPE
! is also NULL, the tree type of VAL is ERROR_MARK_NODE. */
! if (type && type_unknown_p (val))
! val = require_instantiated_type (type, val, integer_zero_node);
! else if (type_unknown_p (val))
! {
! /* Strip the `&' from an overloaded FUNCTION_DECL. */
! if (TREE_CODE (val) == ADDR_EXPR)
! val = TREE_OPERAND (val, 0);
! if (really_overloaded_fn (val))
! cp_error ("insufficient type information to resolve address of overloaded function `%D'",
! DECL_NAME (get_first_fn (val)));
! else
! error ("insufficient type information in parameter list");
! val = integer_zero_node;
! }
! else if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
--- 3019,3025 ----
break;
}
! if (TREE_CODE (val) == OFFSET_REF)
val = resolve_offset_ref (val);
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
*************** build_binary_op (code, arg1, arg2, conve
*** 3187,3228 ****
enum tree_code code;
tree arg1, arg2;
int convert_p;
- {
- tree args[2];
-
- args[0] = arg1;
- args[1] = arg2;
-
- if (convert_p)
- {
- tree type0, type1;
- args[0] = decay_conversion (args[0]);
- args[1] = decay_conversion (args[1]);
-
- if (args[0] == error_mark_node || args[1] == error_mark_node)
- return error_mark_node;
-
- type0 = TREE_TYPE (args[0]);
- type1 = TREE_TYPE (args[1]);
-
- if (type_unknown_p (args[0]))
- {
- args[0] = instantiate_type (type1, args[0], 1);
- args[0] = decay_conversion (args[0]);
- }
- else if (type_unknown_p (args[1]))
{
! args[1] = require_instantiated_type (type0, args[1],
! error_mark_node);
! args[1] = decay_conversion (args[1]);
}
- if (IS_AGGR_TYPE (type0) || IS_AGGR_TYPE (type1))
- my_friendly_abort (754867);
- }
- return build_binary_op_nodefault (code, args[0], args[1], code);
- }
-
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
This function differs from `build' in several ways:
--- 3143,3152 ----
enum tree_code code;
tree arg1, arg2;
int convert_p;
{
! return build_binary_op_nodefault (code, arg1, arg2, code);
}
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
This function differs from `build' in several ways:
*************** build_conditional_expr (ifexp, op1, op2)
*** 5026,5038 ****
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
- op1 = require_instantiated_type (TREE_TYPE (op2), op1, error_mark_node);
- if (op1 == error_mark_node)
- return error_mark_node;
- op2 = require_instantiated_type (TREE_TYPE (op1), op2, error_mark_node);
- if (op2 == error_mark_node)
- return error_mark_node;
-
/* C++: REFERENCE_TYPES must be dereferenced. */
type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
--- 4950,4955 ----
*************** build_conditional_expr (ifexp, op1, op2)
*** 5229,5234 ****
--- 5146,5155 ----
pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
+ if (type2 == unknown_type_node)
+ result_type = type1;
+ else if (type1 == unknown_type_node)
+ result_type = type2;
if (!result_type)
{
*************** build_static_cast (type, expr)
*** 5431,5443 ****
if (TREE_CODE (type) == VOID_TYPE)
return build1 (CONVERT_EXPR, type, expr);
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
if (TREE_CODE (type) == REFERENCE_TYPE)
return (convert_from_reference
(convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
--- 5352,5357 ----
*************** build_reinterpret_cast (type, expr)
*** 5521,5533 ****
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
if (TREE_CODE (type) == REFERENCE_TYPE)
--- 5435,5440 ----
*************** build_const_cast (type, expr)
*** 5622,5634 ****
expr = TREE_OPERAND (expr, 0);
}
- if (type_unknown_p (expr))
- {
- expr = instantiate_type (type, expr, 1);
- if (expr == error_mark_node)
- return error_mark_node;
- }
-
intype = TREE_TYPE (expr);
if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1))
--- 5529,5534 ----
*************** build_c_cast (type, expr)
*** 5667,5672 ****
--- 5567,5573 ----
tree type, expr;
{
register tree value = expr;
+ tree otype;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
*************** build_c_cast (type, expr)
*** 5721,5740 ****
return t;
}
- if (TREE_CODE (type) == VOID_TYPE)
- value = build1 (CONVERT_EXPR, type, value);
- else if (TREE_TYPE (value) == NULL_TREE
- || type_unknown_p (value))
- {
- value = instantiate_type (type, value, 1);
- /* Did we lose? */
- if (value == error_mark_node)
- return error_mark_node;
- }
- else
- {
- tree otype;
-
/* Convert functions and arrays to pointers and
convert references to their expanded types,
but don't convert any other types. If, however, we are
--- 5622,5627 ----
*************** build_c_cast (type, expr)
*** 5825,5831 ****
TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
- }
/* Always produce some operator for an explicit cast,
so we can tell (for -pedantic) that the cast is no lvalue. */
--- 5712,5717 ----
*************** build_modify_expr (lhs, modifycode, rhs)
*** 6107,6120 ****
current_function_just_assigned_this = 1;
}
- /* The TREE_TYPE of RHS may be TYPE_UNKNOWN. This can happen
- when the type of RHS is not yet known, i.e. its type
- is inherited from LHS. */
- rhs = require_instantiated_type (lhstype, newrhs, error_mark_node);
- if (rhs == error_mark_node)
- return error_mark_node;
- newrhs = rhs;
-
if (modifycode != INIT_EXPR)
{
/* Make modifycode now either a NOP_EXPR or an INIT_EXPR. */
--- 5993,5998 ----
*************** build_ptrmemfunc (type, pfn, force)
*** 6529,6537 ****
pfn, NULL_TREE);
}
! if (TREE_CODE (pfn) == TREE_LIST
! || (TREE_CODE (pfn) == ADDR_EXPR
! && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST))
return instantiate_type (type, pfn, 1);
if (!force
--- 6407,6413 ----
pfn, NULL_TREE);
}
! if (type_unknown_p (pfn))
return instantiate_type (type, pfn, 1);
if (!force
*************** convert_for_assignment (type, rhs, errty
*** 6608,6616 ****
if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
cp_warning ("converting NULL to non-pointer type");
- if (coder == UNKNOWN_TYPE)
- rhs = instantiate_type (type, rhs, 1);
-
if (coder == ERROR_MARK)
return error_mark_node;
--- 6484,6489 ----
*************** convert_for_assignment (type, rhs, errty
*** 6640,6651 ****
}
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
! || TREE_CODE (TREE_TYPE (rhs)) == FUNCTION_TYPE
! || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
rhs = default_conversion (rhs);
else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
--- 6513,6529 ----
}
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
! || is_overloaded_fn (rhs))
rhs = default_conversion (rhs);
else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
+ /* If rhs is some sort of overloaded function, ocp_convert will either
+ do the right thing or complain; we don't need to check anything else.
+ So just hand off. */
+ if (type_unknown_p (rhs))
+ return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
+
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
*************** convert_for_initialization (exp, type, r
*** 7066,7078 ****
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
-
- if (coder == UNKNOWN_TYPE)
- {
- rhs = instantiate_type (type, rhs, 1);
- rhstype = TREE_TYPE (rhs);
- coder = TREE_CODE (rhstype);
- }
if (coder == ERROR_MARK)
return error_mark_node;
--- 6944,6949 ----
Index: typeck2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck2.c,v
retrieving revision 1.37
diff -c -p -w -r1.37 typeck2.c
*** typeck2.c 1998/10/26 02:35:21 1.37
--- typeck2.c 1998/10/28 06:14:05
*************** store_init_value (decl, init)
*** 646,658 ****
else
init = TREE_VALUE (init);
}
- else if (TREE_TYPE (init) != 0
- && TREE_CODE (TREE_TYPE (init)) == OFFSET_TYPE)
- {
- /* Use the type of our variable to instantiate
- the type of our initializer. */
- init = instantiate_type (type, init, 1);
- }
else if (TREE_CODE (init) == TREE_LIST
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
--- 646,651 ----