OSDN Git Service

* typeck.c (convert_for_assignment): Converting from pm of vbase
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Aug 1998 01:48:47 +0000 (01:48 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 25 Aug 1998 01:48:47 +0000 (01:48 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@21958 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/typeck.c

index edd3764..eeb2490 100644 (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
index 7c1e683..5564fa3 100644 (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;
index afe430e..d799f63 100644 (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;
 }
 \f
-/* 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);
+}
+
 \f
 void
 init_class_processing ()
index 5800f79..c7530f0 100644 (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))