re PR c++/18073 (mmintrin.h rejected by C++ frontend)
authorMark Mitchell <mark@codesourcery.com>
Thu, 21 Oct 2004 21:23:42 +0000 (21:23 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 21 Oct 2004 21:23:42 +0000 (21:23 +0000)
PR c++/18073
PR c++/10841
* cp-tree.h (convert_to_base): Change prototype.
(build_ptrmemfunc): Likewise.
(convert_ptrmem): New function.
* call.c (struct conversion): Adjust documentation for base_p.
(standard_conversion): Set base_p for ck_pmem conversions as
appropriate.
(convert_like_real): Use convert_to_base for ck_pmem and ck_ptr
conversions.
* class.c (convert_to_base): Handle both pointers and objects.
Add nonnull parameter.
(build_vfield_ref): Adjust call to convert_to_base.
* cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc.
(convert_force): Likewise.
* typeck.c (build_unary_op): Likewise.
(convert_ptrmem): New function.
(build_static_cast_1): Use it.
(build_reinterpret_cast): Allow conversions to vector types.
(get_delta_difference): Add c_cast_p parameter.
(build_ptrmemfunc): Likewise.  Adjust calls to
get_delta_difference.

PR c++/10841
* g++.dg/conversion/cast1.C: New test.
* g++.dg/overload/pmf1.C: Adjust error marker.

From-SVN: r89403

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/conversion/cast1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/overload/pmf1.C

index 3adc303036df62e4a66f42351e9c673d847c5a63..2c78f23b265c811f5f51f9c3ae3cc0fe7c981dbe 100644 (file)
@@ -1,3 +1,28 @@
+2004-10-21  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/18073
+       PR c++/10841
+       * cp-tree.h (convert_to_base): Change prototype.
+       (build_ptrmemfunc): Likewise.
+       (convert_ptrmem): New function.
+       * call.c (struct conversion): Adjust documentation for base_p.
+       (standard_conversion): Set base_p for ck_pmem conversions as
+       appropriate.
+       (convert_like_real): Use convert_to_base for ck_pmem and ck_ptr
+       conversions.
+       * class.c (convert_to_base): Handle both pointers and objects.
+       Add nonnull parameter.
+       (build_vfield_ref): Adjust call to convert_to_base.
+       * cvt.c (cp_convert_to_pointer): Adjust call to build_ptrmemfunc.
+       (convert_force): Likewise.
+       * typeck.c (build_unary_op): Likewise.
+       (convert_ptrmem): New function.
+       (build_static_cast_1): Use it.
+       (build_reinterpret_cast): Allow conversions to vector types.
+       (get_delta_difference): Add c_cast_p parameter.
+       (build_ptrmemfunc): Likewise.  Adjust calls to
+       get_delta_difference.
+
 2004-10-21  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR c++/13560
index 46b270e3ff3edfaddefb54176492bd1f2c1966d4..aedc9278b9d735c3393e7b649f471d329e866368 100644 (file)
@@ -92,8 +92,8 @@ struct conversion {
      copy constructor must be accessible, even though it is not being
      used.  */
   BOOL_BITFIELD check_copy_constructor_p : 1;
-  /* If KIND is ck_ptr, true to indicate that a conversion from a
-     pointer-to-derived to pointer-to-base is being performed.  */
+  /* If KIND is ck_ptr or ck_pmem, true to indicate that a conversion
+     from a pointer-to-derived to pointer-to-base is being performed.  */ 
   BOOL_BITFIELD base_p : 1;
   /* The type of the expression resulting from the conversion.  */
   tree type;
@@ -779,6 +779,7 @@ standard_conversion (tree to, tree from, tree expr)
                                         TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
       from = build_ptrmemfunc_type (build_pointer_type (from));
       conv = build_conv (ck_pmem, from, conv);
+      conv->base_p = true;
     }
   else if (tcode == BOOLEAN_TYPE)
     {
@@ -4270,8 +4271,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
            check_constructor_callable (TREE_TYPE (expr), expr);
          /* Build an expression for `*((base*) &expr)'.  */
          expr = build_unary_op (ADDR_EXPR, expr, 0);
-         expr = perform_implicit_conversion (build_pointer_type (totype), 
-                                             expr);
+         expr = convert_to_base (expr, build_pointer_type (totype),
+                                 !c_cast_p, /*nonnull=*/true);
          expr = build_indirect_ref (expr, "implicit conversion");
          return expr;
        }
@@ -4338,19 +4339,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 
     case ck_ptr:
       if (convs->base_p)
-       {
-         tree binfo;
-
-         binfo = lookup_base (TREE_TYPE (TREE_TYPE (expr)),
-                              TREE_TYPE (totype), 
-                              c_cast_p ? ba_unique : ba_check,
-                              NULL);
-         if (binfo == error_mark_node)
-           return error_mark_node;
-         expr = build_base_path (PLUS_EXPR, expr, binfo, /*nonnull=*/0);
-       }
+       expr = convert_to_base (expr, totype, !c_cast_p,
+                               /*nonnull=*/false);
       return build_nop (totype, expr);
 
+    case ck_pmem:
+      return convert_ptrmem (totype, expr, /*allow_inverse_p=*/false,
+                            c_cast_p);
+
     default:
       break;
     }
index a0a2ed48bce11628dc1add33d83183f7f9aa9079..15ca26ad460273814e7aca1e7e91f973197e011f 100644 (file)
@@ -426,22 +426,34 @@ build_simple_base_path (tree expr, tree binfo)
   gcc_unreachable ();
 }
 
-/* Convert OBJECT to the base TYPE.  If CHECK_ACCESS is true, an error
-   message is emitted if TYPE is inaccessible.  OBJECT is assumed to
-   be non-NULL.  */
+/* Convert OBJECT to the base TYPE.  OBJECT is an expression whose
+   type is a class type or a pointer to a class type.  In the former
+   case, TYPE is also a class type; in the latter it is another
+   pointer type.  If CHECK_ACCESS is true, an error message is emitted
+   if TYPE is inaccessible.  If OBJECT has pointer type, the value is
+   assumed to be non-NULL.  */
 
 tree
-convert_to_base (tree object, tree type, bool check_access)
+convert_to_base (tree object, tree type, bool check_access, bool nonnull)
 {
   tree binfo;
+  tree object_type;
 
-  binfo = lookup_base (TREE_TYPE (object), type, 
+  if (TYPE_PTR_P (TREE_TYPE (object)))
+    {
+      object_type = TREE_TYPE (TREE_TYPE (object));
+      type = TREE_TYPE (type);
+    }
+  else
+    object_type = TREE_TYPE (object);
+
+  binfo = lookup_base (object_type, type,
                       check_access ? ba_check : ba_unique, 
                       NULL);
   if (!binfo || binfo == error_mark_node)
     return error_mark_node;
 
-  return build_base_path (PLUS_EXPR, object, binfo, /*nonnull=*/1);
+  return build_base_path (PLUS_EXPR, object, binfo, nonnull);
 }
 
 /* EXPR is an expression with unqualified class type.  BASE is a base
@@ -485,7 +497,8 @@ build_vfield_ref (tree datum, tree type)
 
   /* First, convert to the requested type.  */
   if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (datum), type))
-    datum = convert_to_base (datum, type, /*check_access=*/false);
+    datum = convert_to_base (datum, type, /*check_access=*/false,
+                            /*nonnull=*/true);
 
   /* Second, the requested type may not be the owner of its own vptr.
      If not, convert to the base class that owns it.  We cannot use
index 0f75fce38124836eaa90dd60b39a5c7cb10db579..580a73b4db87ddd4f7c2a08637df4813cd2453c4 100644 (file)
@@ -3594,7 +3594,7 @@ extern void validate_conversion_obstack (void);
 
 /* in class.c */
 extern tree build_base_path                    (enum tree_code, tree, tree, int);
-extern tree convert_to_base                     (tree, tree, bool);
+extern tree convert_to_base                     (tree, tree, bool, bool);
 extern tree convert_to_base_statically (tree, tree);
 extern tree build_vtbl_ref                     (tree, tree);
 extern tree build_vfn_ref                      (tree, tree);
@@ -4267,7 +4267,7 @@ extern tree dubious_conversion_warnings         (tree, tree, const char *, tree,
 extern tree convert_for_initialization         (tree, tree, tree, int, const char *, tree, int);
 extern int comp_ptr_ttypes                     (tree, tree);
 extern int ptr_reasonably_similar              (tree, tree);
-extern tree build_ptrmemfunc                   (tree, tree, int);
+extern tree build_ptrmemfunc                   (tree, tree, int, bool);
 extern int cp_type_quals                        (tree);
 extern bool cp_has_mutable_p                     (tree);
 extern bool at_least_as_qualified_p              (tree, tree);
@@ -4291,6 +4291,7 @@ extern tree non_reference                       (tree);
 extern tree lookup_anon_field                   (tree, tree);
 extern bool invalid_nonstatic_memfn_p           (tree);
 extern tree convert_member_func_to_ptr          (tree, tree);
+extern tree convert_ptrmem                      (tree, tree, bool, bool);
 
 /* in typeck2.c */
 extern void require_complete_eh_spec_types     (tree, tree);
index 02230301117164058a4da2feb0ed20f40a1e71b2..7f0f64c9c46f767fabf40c8ba95a528036602101 100644 (file)
@@ -217,7 +217,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
       return build_nop (type, expr);
     }
   else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
-    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
+    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
+                            /*c_cast_p=*/false);
   else if (TYPE_PTRMEMFUNC_P (intype))
     {
       if (!warn_pmf2ptr)
@@ -241,7 +242,8 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
   if (integer_zerop (expr))
     {
       if (TYPE_PTRMEMFUNC_P (type))
-       return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
+       return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
+                                /*c_cast_p=*/false);
 
       if (TYPE_PTRMEM_P (type))
        {
@@ -960,10 +962,9 @@ convert_force (tree type, tree expr, int convtype)
        || integer_zerop (e)
        || TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
       && TYPE_PTRMEMFUNC_P (type))
-    {
-      /* compatible pointer to member functions.  */
-      return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
-    }
+    /* compatible pointer to member functions.  */
+    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
+                            /*c_cast_p=*/1);
 
   return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
 }
index 0f6f65b41886ac4bd2cceccbc04c9719feddc3bc..cc91b653aae01646d68e4cb9582b8ecf70216e32 100644 (file)
@@ -52,7 +52,7 @@ static bool comp_except_types (tree, tree, bool);
 static bool comp_array_types (tree, tree, bool);
 static tree common_base_type (tree, tree);
 static tree pointer_diff (tree, tree, tree);
-static tree get_delta_difference (tree, tree, int);
+static tree get_delta_difference (tree, tree, bool, bool);
 static void casts_away_constness_r (tree *, tree *);
 static bool casts_away_constness (tree, tree);
 static void maybe_warn_about_returning_address_of_local (tree);
@@ -4146,7 +4146,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
            && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
          {
            build_ptrmemfunc_type (argtype);
-           addr = build_ptrmemfunc (argtype, addr, 0);
+           addr = build_ptrmemfunc (argtype, addr, 0,
+                                    /*c_cast_p=*/false);
          }
 
        return addr;
@@ -4485,6 +4486,38 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
           description, src_type, dest_type);
 }
 
+/* Convert EXPR (an expression with pointer-to-member type) to TYPE
+   (another pointer-to-member type in the same hierarchy) and return
+   the converted expression.  If ALLOW_INVERSE_P is permitted, a
+   pointer-to-derived may be converted to pointer-to-base; otherwise,
+   only the other direction is permitted.  If C_CAST_P is true, this
+   conversion is taking place as part of a C-style cast.  */
+
+tree 
+convert_ptrmem (tree type, tree expr, bool allow_inverse_p,
+               bool c_cast_p)
+{
+  if (TYPE_PTRMEM_P (type))
+    {
+      tree delta;
+
+      if (TREE_CODE (expr) == PTRMEM_CST)
+       expr = cplus_expand_constant (expr);
+      delta = get_delta_difference (TYPE_PTRMEM_CLASS_TYPE (TREE_TYPE (expr)),
+                                   TYPE_PTRMEM_CLASS_TYPE (type), 
+                                   allow_inverse_p,
+                                   c_cast_p);
+      if (!integer_zerop (delta))
+       expr = cp_build_binary_op (PLUS_EXPR, 
+                                  build_nop (ptrdiff_type_node, expr),
+                                  delta);
+      return build_nop (type, expr);
+    }
+  else
+    return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 
+                            allow_inverse_p, c_cast_p);
+}
+
 /* Perform a static_cast from EXPR to TYPE.  When C_CAST_P is true,
    this static_cast is being attempted as one of the possible casts
    allowed by a C-style cast.  (In that case, accessibility of base
@@ -4691,23 +4724,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       if (can_convert (t1, t2))
        {
          if (!c_cast_p)
-           check_for_casting_away_constness (intype, type, diag_fn, desc);
-         if (TYPE_PTRMEM_P (type))
-           {
-             tree delta;
-
-             if (TREE_CODE (expr) == PTRMEM_CST)
-               expr = cplus_expand_constant (expr);
-             delta = get_delta_difference (c1, c2, /*force=*/1);
-             if (!integer_zerop (delta))
-               expr = cp_build_binary_op (PLUS_EXPR, 
-                                          build_nop (ptrdiff_type_node, expr),
-                                          delta);
-             return build_nop (type, expr);
-           }
-         else
-           return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 
-                                    /*force=*/1);
+           check_for_casting_away_constness (intype, type, diag_fn, 
+                                             desc);
+         return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
+                                c_cast_p);
        }
     }
     
@@ -4945,6 +4965,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
       expr = decl_constant_value (expr);
       return fold_if_not_in_template (build_nop (type, expr));
     }
+  else if (TREE_CODE (type) == VECTOR_TYPE)
+    return fold_if_not_in_template (convert_to_vector (type, expr));
   else
     {
       if (valid_p)
@@ -5546,8 +5568,10 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
 \f
 /* Get difference in deltas for different pointer to member function
    types.  Returns an integer constant of type PTRDIFF_TYPE_NODE.  If
-   the conversion is invalid, the constant is zero.  If FORCE is true,
-   then allow reverse conversions as well.
+   the conversion is invalid, the constant is zero.  If
+   ALLOW_INVERSE_P is true, then allow reverse conversions as well.
+   If C_CAST_P is true this conversion is taking place as part of a
+   C-style cast.
 
    Note that the naming of FROM and TO is kind of backwards; the return
    value is what we add to a TO in order to get a FROM.  They are named
@@ -5555,7 +5579,9 @@ build_x_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
    a pointer to member of FROM to a pointer to member of TO.  */
 
 static tree
-get_delta_difference (tree from, tree to, int force)
+get_delta_difference (tree from, tree to, 
+                     bool allow_inverse_p,
+                     bool c_cast_p)
 {
   tree binfo;
   tree virt_binfo;
@@ -5564,19 +5590,20 @@ get_delta_difference (tree from, tree to, int force)
 
   /* Assume no conversion is required.  */
   result = integer_zero_node;
-  binfo = lookup_base (to, from, ba_check, &kind);
+  binfo = lookup_base (to, from, c_cast_p ? ba_unique : ba_check, &kind);
   if (kind == bk_inaccessible || kind == bk_ambig)
     error ("   in pointer to member function conversion");
   else if (!binfo)
     {
-      if (!force)
+      if (!allow_inverse_p)
        {
          error_not_base_type (from, to);
          error ("   in pointer to member conversion");
        }
       else
        {
-         binfo = lookup_base (from, to, ba_check, &kind);
+         binfo = lookup_base (from, to, c_cast_p ? ba_unique : ba_check, 
+                              &kind);
          if (binfo)
            {
              virt_binfo = binfo_from_vbase (binfo);
@@ -5597,7 +5624,7 @@ get_delta_difference (tree from, tree to, int force)
       else
        {
          /* This is a reinterpret cast, we choose to do nothing.  */
-         if (force)
+         if (allow_inverse_p)
            warning ("pointer to member cast via virtual base %qT",
                     BINFO_TYPE (virt_binfo));
          else
@@ -5648,12 +5675,12 @@ build_ptrmemfunc1 (tree type, tree delta, tree pfn)
 
    If FORCE is nonzero, then force this conversion, even if
    we would rather not do it.  Usually set when using an explicit
-   cast.
+   cast.  A C-style cast is being processed iff C_CAST_P is true.
 
    Return error_mark_node, if something goes wrong.  */
 
 tree
-build_ptrmemfunc (tree type, tree pfn, int force)
+build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p)
 {
   tree fn;
   tree pfn_type;
@@ -5679,7 +5706,8 @@ build_ptrmemfunc (tree type, tree pfn, int force)
 
       n = get_delta_difference (TYPE_PTRMEMFUNC_OBJECT_TYPE (pfn_type),
                                TYPE_PTRMEMFUNC_OBJECT_TYPE (to_type),
-                               force);
+                               force,
+                               c_cast_p);
 
       /* We don't have to do any conversion to convert a
         pointer-to-member to its own type.  But, we don't want to
@@ -5754,7 +5782,8 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
   ptr_class = TYPE_PTRMEMFUNC_OBJECT_TYPE (type);
 
   /* First, calculate the adjustment to the function's class.  */
-  *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0);
+  *delta = get_delta_difference (fn_class, ptr_class, /*force=*/0,
+                                /*c_cast_p=*/0);
 
   if (!DECL_VIRTUAL_P (fn))
     *pfn = convert (TYPE_PTRMEMFUNC_FN_TYPE (type), build_addr_func (fn));
index b7f25ddf4dde71d7e34cc158ba62dc1df5ee9070..ae6231295cb96e2a54951013aa66ca64b83aa84f 100644 (file)
@@ -1,3 +1,9 @@
+2004-10-21  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/10841
+       * g++.dg/conversion/cast1.C: New test.
+       * g++.dg/overload/pmf1.C: Adjust error marker.
+
 2004-10-21  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR objc/17923
diff --git a/gcc/testsuite/g++.dg/conversion/cast1.C b/gcc/testsuite/g++.dg/conversion/cast1.C
new file mode 100644 (file)
index 0000000..f90b421
--- /dev/null
@@ -0,0 +1,22 @@
+// PR c++/10841
+
+int main() {
+  class Base { 
+  public: 
+    int i, j, k; 
+    void f(); };
+
+  class Derived : private Base { 
+  public: 
+    int m, n, p; 
+    void g(); 
+  };
+
+  Derived derived;
+  Base &base = (Base &)derived;
+  (int Base::*)&Derived::n;
+  (int Derived::*)&Base::j;
+  (void (Base::*)(void))&Derived::g;
+  (void (Derived::*)(void))&Base::f;
+}
+
index b97f64e764bfc1c15c0912da9e2fd12354c4d66e..d20074931797df1c80cd4cbafd42d816df6d9953 100644 (file)
@@ -17,5 +17,5 @@ void f (C) {}         // even though this would be well-formed
 
 int main ()
 {
-  f (aip);  // { dg-error "'A' is an inaccessible base of 'B'" "" }
+  f (aip);  // { dg-error "'A' is an inaccessible base of 'B'|conversion" "" }
 }