From 51ddb82e4604cfdcc15d6a7b87b4bb713037205c Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 25 Aug 1998 01:48:47 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 14 +++++++ gcc/cp/call.c | 16 +++++-- gcc/cp/class.c | 106 +++++++++++++++++++++++++++-------------------- gcc/cp/typeck.c | 2 +- 4 files changed, 90 insertions(+), 48 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index edd3764178d..eeb2490ea67 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +1998-08-25 Jason Merrill + + * 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 * pt.c (tsubst_decl): Move special case code for dealing with diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 7c1e683baf0..5564fa3a535 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index afe430e0e61..d799f635931 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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 () diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5800f79eef9..c7530f06d7b 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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))