Commit 02020185 by Jason Merrill

init.c (resolve_offset_ref): Handle default-initialization.

	* init.c (resolve_offset_ref): Handle default-initialization.
	* except.c (build_throw): Handle throwing NULL.
	* typeck.c (build_x_function_call): Use resolve_offset_ref.
	* search.c (compute_access): Only strip an anonymous union
	for a FIELD_DECL.
	* call.c (add_builtin_candidates): Tweak.
	* cvt.c (build_expr_type_conversion): Restore code for conversion
	from class types.
	* decl2.c (delete_sanity): Use it.  Clean up.
	* typeck.c (comp_ptr_ttypes_real): Fix cv-qual comparisons.
        * typeck.c (c_expand_return): Don't warn about void expressions on
        return statements in functions returning void.

From-SVN: r20399
parent 0365438d
1998-06-10 Jason Merrill <jason@yorick.cygnus.com>
* init.c (resolve_offset_ref): Handle default-initialization.
* except.c (build_throw): Handle throwing NULL.
* typeck.c (build_x_function_call): Use resolve_offset_ref.
* search.c (compute_access): Only strip an anonymous union
for a FIELD_DECL.
* call.c (add_builtin_candidates): Tweak.
* cvt.c (build_expr_type_conversion): Restore code for conversion
from class types.
* decl2.c (delete_sanity): Use it. Clean up.
* typeck.c (comp_ptr_ttypes_real): Fix cv-qual comparisons.
1998-06-10 Branko Cibej <branko.cibej@hermes.si>
* typeck.c (c_expand_return): Don't warn about void expressions on
return statements in functions returning void.
1998-06-09 Mark Mitchell <mark@markmitchell.com>
* pt.c (fn_type_unification): Revise documentation. Tidy.
......
......@@ -1807,6 +1807,11 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
{
tree convs = lookup_conversions (argtypes[i]);
if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR)
return candidates;
convs = lookup_conversions (argtypes[i]);
if (code == COND_EXPR)
{
if (real_lvalue_p (args[i]))
......@@ -1817,8 +1822,7 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
(NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]);
}
else if (! convs || (i == 0 && code == MODIFY_EXPR
&& code2 == NOP_EXPR))
else if (! convs)
return candidates;
for (; convs; convs = TREE_CHAIN (convs))
......
......@@ -941,12 +941,15 @@ build_expr_type_conversion (desires, expr, complain)
int complain;
{
tree basetype = TREE_TYPE (expr);
tree conv;
tree winner = NULL_TREE;
if (TREE_CODE (basetype) == OFFSET_TYPE)
expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
if (! IS_AGGR_TYPE (basetype))
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE:
......@@ -966,13 +969,73 @@ build_expr_type_conversion (desires, expr, complain)
case FUNCTION_TYPE:
case ARRAY_TYPE:
return ((desires & WANT_POINTER) ? default_conversion (expr)
: NULL_TREE);
return (desires & WANT_POINTER) ? default_conversion (expr)
: NULL_TREE;
default:
return NULL_TREE;
}
/* The code for conversions from class type is currently only used for
delete expressions. Other expressions are handled by build_new_op. */
if (! TYPE_HAS_CONVERSION (basetype))
return NULL_TREE;
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
int win = 0;
tree candidate;
tree cand = TREE_VALUE (conv);
if (winner && winner == cand)
continue;
candidate = TREE_TYPE (TREE_TYPE (cand));
if (TREE_CODE (candidate) == REFERENCE_TYPE)
candidate = TREE_TYPE (candidate);
switch (TREE_CODE (candidate))
{
case BOOLEAN_TYPE:
case INTEGER_TYPE:
win = (desires & WANT_INT); break;
case ENUMERAL_TYPE:
win = (desires & WANT_ENUM); break;
case REAL_TYPE:
win = (desires & WANT_FLOAT); break;
case POINTER_TYPE:
win = (desires & WANT_POINTER); break;
default:
break;
}
if (win)
{
if (winner)
{
if (complain)
{
cp_error ("ambiguous default type conversion from `%T'",
basetype);
cp_error (" candidate conversions include `%D' and `%D'",
winner, cand);
}
return error_mark_node;
}
else
winner = cand;
}
}
if (winner)
{
tree type = TREE_TYPE (TREE_TYPE (winner));
if (TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}
return NULL_TREE;
}
......
......@@ -1236,9 +1236,7 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
tree exp, size;
int doing_vec, use_global_delete;
{
tree t;
tree type;
enum tree_code code;
tree t, type;
/* For a regular vector delete (aka, no size argument) we will pass
this down as a NULL_TREE into build_vec_delete. */
tree maxindex = NULL_TREE;
......@@ -1254,65 +1252,45 @@ delete_sanity (exp, size, doing_vec, use_global_delete)
return t;
}
t = exp;
if (TREE_CODE (t) == OFFSET_REF)
t = resolve_offset_ref (t);
t = stabilize_reference (convert_from_reference (t));
type = TREE_TYPE (t);
code = TREE_CODE (type);
if (TREE_CODE (exp) == OFFSET_REF)
exp = resolve_offset_ref (exp);
exp = convert_from_reference (exp);
t = stabilize_reference (exp);
t = build_expr_type_conversion (WANT_POINTER, t, 1);
switch (doing_vec)
{
case 2:
maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
pedwarn ("anachronistic use of array size in vector delete");
/* Fall through. */
case 1:
break;
default:
if (code != POINTER_TYPE)
if (t == NULL_TREE || t == error_mark_node)
{
cp_error ("type `%#T' argument given to `delete', expected pointer",
type);
TREE_TYPE (exp));
return error_mark_node;
}
/* Deleting a pointer with the value zero is valid and has no effect. */
if (integer_zerop (t))
return build1 (NOP_EXPR, void_type_node, t);
if (doing_vec == 2)
{
maxindex = build_binary_op (MINUS_EXPR, size, integer_one_node, 1);
pedwarn ("anachronistic use of array size in vector delete");
}
if (code == POINTER_TYPE)
{
#if 0
type = TREE_TYPE (t);
/* As of Valley Forge, you can delete a pointer to const. */
if (TREE_READONLY (TREE_TYPE (type)))
{
error ("`const *' cannot be deleted");
return error_mark_node;
}
#endif
/* You can't delete functions. */
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
error ("cannot delete a function");
return error_mark_node;
}
}
#if 0
/* If the type has no destructor, then we should build a regular
delete, instead of a vector delete. Otherwise, we would end
up passing a bogus offset into __builtin_delete, which is
not expecting it. */
if (doing_vec
&& TREE_CODE (type) == POINTER_TYPE
&& !TYPE_HAS_DESTRUCTOR (TREE_TYPE (type)))
{
doing_vec = 0;
use_global_delete = 1;
}
#endif
/* An array can't have been allocated by new, so complain. */
if (TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE)
cp_warning ("deleting array `%#D'", TREE_OPERAND (t, 0));
/* Deleting a pointer with the value zero is valid and has no effect. */
if (integer_zerop (t))
return build1 (NOP_EXPR, void_type_node, t);
if (doing_vec)
return build_vec_delete (t, maxindex, integer_one_node,
......
......@@ -1077,13 +1077,21 @@ tree
build_throw (e)
tree e;
{
if (e != error_mark_node)
{
if (e == error_mark_node)
return e;
if (processing_template_decl)
return build_min (THROW_EXPR, void_type_node, e);
if (! flag_ansi && e == null_node)
{
cp_warning ("throwing NULL");
e = integer_zero_node;
}
e = build1 (THROW_EXPR, void_type_node, e);
TREE_SIDE_EFFECTS (e) = 1;
TREE_USED (e) = 1;
}
return e;
}
......@@ -197,9 +197,11 @@ perform_member_init (member, name, init, explicit)
{
if (explicit)
{
cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor",
member, current_class_type);
init = error_mark_node;
/* default-initialization. */
if (AGGREGATE_TYPE_P (type))
init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
else
init = integer_zero_node;
}
/* member traversal: note it leaves init NULL */
else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)
......@@ -222,7 +224,8 @@ perform_member_init (member, name, init, explicit)
current_member_init_list. */
if (init || explicit)
{
decl = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
decl = build_component_ref (current_class_ref, name, NULL_TREE,
explicit);
expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
}
}
......@@ -238,7 +241,8 @@ perform_member_init (member, name, init, explicit)
push_obstacks_nochange ();
resume_temporary_allocation ();
expr = build_component_ref (current_class_ref, name, NULL_TREE, explicit);
expr = build_component_ref (current_class_ref, name, NULL_TREE,
explicit);
expr = build_delete (type, expr, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
......
......@@ -962,14 +962,13 @@ compute_access (basetype_path, field)
previous_scope = current_scope ();
context = DECL_CLASS_CONTEXT (field);
if (context == NULL_TREE)
context = DECL_CONTEXT (field);
context = DECL_REAL_CONTEXT (field);
/* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
slot set to the union type rather than the record type containing
the anonymous union. */
if (context && ANON_UNION_TYPE_P (context))
if (context && ANON_UNION_TYPE_P (context)
&& TREE_CODE (field) == FIELD_DECL)
context = TYPE_CONTEXT (context);
/* Virtual function tables are never private. But we should know that
......
......@@ -2564,8 +2564,19 @@ build_x_function_call (function, params, decl)
decl = current_class_ref;
decl_addr = build_unary_op (ADDR_EXPR, decl, 0);
function = get_member_function_from_ptrfunc (&decl_addr,
TREE_OPERAND (function, 1));
/* Sigh. OFFSET_REFs are being used for too many things.
They're being used both for -> and ->*, and we want to resolve
the -> cases here, but leave the ->*. We could use
resolve_offset_ref for those, too, but it would call
get_member_function_from_ptrfunc and decl_addr wouldn't get
updated properly. Nasty. */
if (TREE_CODE (TREE_OPERAND (function, 1)) == FIELD_DECL)
function = resolve_offset_ref (function);
else
function = TREE_OPERAND (function, 1);
function = get_member_function_from_ptrfunc (&decl_addr, function);
params = expr_tree_cons (NULL_TREE, decl_addr, params);
return build_function_call (function, params);
}
......@@ -7271,8 +7282,7 @@ c_expand_return (retval)
if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl))
|| TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("`return' with a value, in function returning void");
expand_return (retval);
return;
......@@ -7477,22 +7487,17 @@ comp_ptr_ttypes_real (to, from, constp)
so the usual checks are not appropriate. */
if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE)
{
switch (comp_cv_qualification (from, to))
{
case 1:
/* FROM is more cv-qualified than TO. */
if (TYPE_READONLY (from) > TYPE_READONLY (to)
|| TYPE_VOLATILE (from) > TYPE_VOLATILE (to))
return 0;
case -1:
/* TO is more cv-qualified than FROM. */
if (TYPE_READONLY (to) > TYPE_READONLY (from)
|| TYPE_VOLATILE (to) > TYPE_VOLATILE (from))
{
if (constp == 0)
return 0;
else
++to_more_cv_qualified;
break;
default:
break;
}
if (constp > 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment