typeck.c (convert_for_assignment): Converting from pm of vbase to derived is an error, not a sorry.

* typeck.c (convert_for_assignment): Converting from pm of vbase
	to derived is an error, not a sorry.
	* call.c (build_over_call): Use convert_pointer_to_real for 'this'.
	* class.c (fixed_type_or_null): Rename from
	resolves_to_fixed_type_p.  Return the dynamic type of the
	expression, if fixed, or null.
	(resolves_to_fixed_type_p): Use it.  Return 0 if the dynamic type
	does not match the static type.
	(build_vbase_path): Rename 'alias_this' to 'nonnull'.  Use
	resolves_to_fixed_type_p again.

From-SVN: r21958
This commit is contained in:
Jason Merrill 1998-08-25 01:48:47 +00:00 committed by Jason Merrill
parent 1dd503e847
commit 51ddb82e46
4 changed files with 90 additions and 48 deletions

View File

@ -1,3 +1,17 @@
1998-08-25 Jason Merrill <jason@yorick.cygnus.com>
* typeck.c (convert_for_assignment): Converting from pm of vbase
to derived is an error, not a sorry.
* call.c (build_over_call): Use convert_pointer_to_real for 'this'.
* class.c (fixed_type_or_null): Rename from
resolves_to_fixed_type_p. Return the dynamic type of the
expression, if fixed, or null.
(resolves_to_fixed_type_p): Use it. Return 0 if the dynamic type
does not match the static type.
(build_vbase_path): Rename 'alias_this' to 'nonnull'. Use
resolves_to_fixed_type_p again.
1998-08-24 Mark Mitchell <mark@markmitchell.com>
* pt.c (tsubst_decl): Move special case code for dealing with

View File

@ -3291,6 +3291,7 @@ build_over_call (cand, args, flags)
{
tree parmtype = TREE_VALUE (parm);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
tree t;
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
{
int dv = (TYPE_VOLATILE (TREE_TYPE (parmtype))
@ -3303,9 +3304,18 @@ build_over_call (cand, args, flags)
cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards %s",
TREE_TYPE (argtype), fn, p);
}
converted_args = expr_tree_cons
(NULL_TREE, convert_force (TREE_VALUE (parm), TREE_VALUE (arg), CONV_C_CAST),
converted_args);
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
X is called for an object that is not of type X, or of a type
derived from X, the behavior is undefined.
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
if (TREE_CODE (parmtype) == POINTER_TYPE)
t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
else
/* This happens with signatures. */
t = convert_force (parmtype, TREE_VALUE (arg), CONV_C_CAST);
converted_args = expr_tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
++i;

View File

@ -229,17 +229,17 @@ complete_type_p (expr)
TYPE is the type we want this path to have on exit.
ALIAS_THIS is non-zero if EXPR in an expression involving `this'. */
NONNULL is non-zero if we know (for any reason) that EXPR is
not, in fact, zero. */
tree
build_vbase_path (code, type, expr, path, alias_this)
build_vbase_path (code, type, expr, path, nonnull)
enum tree_code code;
tree type, expr, path;
int alias_this;
int nonnull;
{
register int changed = 0;
tree last = NULL_TREE, last_virtual = NULL_TREE;
int nonnull = 0;
int fixed_type_p;
tree null_expr = 0, nonnull_expr;
tree basetype;
@ -248,20 +248,16 @@ build_vbase_path (code, type, expr, path, alias_this)
if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
return build1 (NOP_EXPR, type, expr);
if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0))
nonnull = 1;
/* If -fthis-is-variable, we might have set nonnull incorrectly. We
don't care enough to get this right, so just clear it. */
if (flag_this_is_variable > 0)
nonnull = 0;
#if 0
/* We need additional logic to convert back to the unconverted type
(the static type of the complete object), and then convert back
to the type we want. Until that is done, or until we can
recognize when that is, we cannot do the short cut logic. (mrs) */
/* We could do better if we had additional logic to convert back to the
unconverted type (the static type of the complete object), and then
convert back to the type we want. Until that is done, we only optimize
if the complete type is the same type as expr has. */
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
#else
/* Do this, until we can undo any previous conversions. See net35.C
for a testcase. */
fixed_type_p = complete_type_p (expr);
#endif
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
@ -382,12 +378,7 @@ build_vbase_path (code, type, expr, path, alias_this)
expr = build1 (NOP_EXPR, type, expr);
#endif
/* For multiple inheritance: if `this' can be set by any
function, then it could be 0 on entry to any function.
Preserve such zeroness here. Otherwise, only in the
case of constructors need we worry, and in those cases,
it will be zero, or initialized to some valid value to
which we may add. */
/* If expr might be 0, we need to preserve that zeroness. */
if (nonnull == 0)
{
if (null_expr)
@ -4485,15 +4476,15 @@ finish_struct (t, list_of_fieldlists, attributes, warn_anon)
return t;
}
/* Return non-zero if the effective type of INSTANCE is static.
/* Return the dynamic type of INSTANCE, if known.
Used to determine whether the virtual function table is needed
or not.
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type. */
int
resolves_to_fixed_type_p (instance, nonnull)
tree
fixed_type_or_null (instance, nonnull)
tree instance;
int *nonnull;
{
@ -4511,9 +4502,9 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
return 1;
return TREE_TYPE (instance);
}
return 0;
return NULL_TREE;
case SAVE_EXPR:
/* This is a call to a constructor, hence it's never zero. */
@ -4521,33 +4512,33 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
return 1;
return TREE_TYPE (instance);
}
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case RTL_EXPR:
return 0;
return NULL_TREE;
case PLUS_EXPR:
case MINUS_EXPR:
if (TREE_CODE (TREE_OPERAND (instance, 1)) == INTEGER_CST)
/* Propagate nonnull. */
resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
if (TREE_CODE (TREE_OPERAND (instance, 0)) == ADDR_EXPR)
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
return 0;
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
return NULL_TREE;
case NOP_EXPR:
case CONVERT_EXPR:
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case ADDR_EXPR:
if (nonnull)
*nonnull = 1;
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 0), nonnull);
return fixed_type_or_null (TREE_OPERAND (instance, 0), nonnull);
case COMPONENT_REF:
return resolves_to_fixed_type_p (TREE_OPERAND (instance, 1), nonnull);
return fixed_type_or_null (TREE_OPERAND (instance, 1), nonnull);
case VAR_DECL:
case FIELD_DECL:
@ -4556,7 +4547,7 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
return 1;
return TREE_TYPE (TREE_TYPE (instance));
}
/* fall through... */
case TARGET_EXPR:
@ -4565,29 +4556,56 @@ resolves_to_fixed_type_p (instance, nonnull)
{
if (nonnull)
*nonnull = 1;
return 1;
return TREE_TYPE (instance);
}
else if (nonnull)
{
if (instance == current_class_ptr
&& flag_this_is_variable <= 0)
{
/* Some people still use `this = 0' inside destructors. */
*nonnull = ! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (current_function_decl));
/* In a constructor, we know our type. */
/* Normally, 'this' must be non-null. */
if (flag_this_is_variable == 0)
*nonnull = 1;
/* <0 means we're in a constructor and we know our type. */
if (flag_this_is_variable < 0)
return 1;
return TREE_TYPE (TREE_TYPE (instance));
}
else if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
/* Reference variables should be references to objects. */
*nonnull = 1;
}
return 0;
return NULL_TREE;
default:
return 0;
return NULL_TREE;
}
}
/* Return non-zero if the dynamic type of INSTANCE is known, and equivalent
to the static type. We also handle the case where INSTANCE is really
a pointer.
Used to determine whether the virtual function table is needed
or not.
*NONNULL is set iff INSTANCE can be known to be nonnull, regardless
of our knowledge of its type. */
int
resolves_to_fixed_type_p (instance, nonnull)
tree instance;
int *nonnull;
{
tree t = TREE_TYPE (instance);
tree fixed = fixed_type_or_null (instance, nonnull);
if (fixed == NULL_TREE)
return 0;
if (POINTER_TYPE_P (t))
t = TREE_TYPE (t);
return comptypes (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (fixed), 1);
}
void
init_class_processing ()

View File

@ -6830,7 +6830,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
&& binfo_member (TYPE_OFFSET_BASETYPE (ttr),
CLASSTYPE_VBASECLASSES (TYPE_OFFSET_BASETYPE (ttl))))
{
sorry ("%s between pointer to members converting across virtual baseclasses", errtype);
error ("%s between pointer to members converting across virtual baseclasses", errtype);
return error_mark_node;
}
else if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))