OSDN Git Service

PR c++/31074
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Apr 2007 23:43:18 +0000 (23:43 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 Apr 2007 23:43:18 +0000 (23:43 +0000)
        * call.c (reference_binding): Add c_cast_p parm.  If true,
        add quals to TO as needed to make it reference-compatible.

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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/inherit/conv3.C [new file with mode: 0644]

index 663b3e1..9d0ac8c 100644 (file)
@@ -1,3 +1,9 @@
+2007-04-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/31074
+       * call.c (reference_binding): Add c_cast_p parm.  If true,
+       add quals to TO as needed to make it reference-compatible.
+
 2007-04-11  Jan Hubicka  <jh@suse.cz>
 
        * cp/class.c (convert_to_base_statically): Fold produced tree; verify
 2007-04-11  Jan Hubicka  <jh@suse.cz>
 
        * cp/class.c (convert_to_base_statically): Fold produced tree; verify
index 320e51c..0b0bb64 100644 (file)
@@ -173,7 +173,7 @@ static struct z_candidate *add_function_candidate
        (struct z_candidate **, tree, tree, tree, tree, tree, int);
 static conversion *implicit_conversion (tree, tree, tree, bool, int);
 static conversion *standard_conversion (tree, tree, tree, bool, int);
        (struct z_candidate **, tree, tree, tree, tree, tree, int);
 static conversion *implicit_conversion (tree, tree, tree, bool, int);
 static conversion *standard_conversion (tree, tree, tree, bool, int);
-static conversion *reference_binding (tree, tree, tree, int);
+static conversion *reference_binding (tree, tree, tree, bool, int);
 static conversion *build_conv (conversion_kind, tree, conversion *);
 static bool is_subseq (conversion *, conversion *);
 static tree maybe_handle_ref_bind (conversion **);
 static conversion *build_conv (conversion_kind, tree, conversion *);
 static bool is_subseq (conversion *, conversion *);
 static tree maybe_handle_ref_bind (conversion **);
@@ -1105,10 +1105,11 @@ direct_reference_binding (tree type, conversion *conv)
    purposes of reference binding.  For lvalue binding, either pass a
    reference type to FROM or an lvalue expression to EXPR.  If the
    reference will be bound to a temporary, NEED_TEMPORARY_P is set for
    purposes of reference binding.  For lvalue binding, either pass a
    reference type to FROM or an lvalue expression to EXPR.  If the
    reference will be bound to a temporary, NEED_TEMPORARY_P is set for
-   the conversion returned.  */
+   the conversion returned.  If C_CAST_P is true, this
+   conversion is coming from a C-style cast.  */
 
 static conversion *
 
 static conversion *
-reference_binding (tree rto, tree rfrom, tree expr, int flags)
+reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
 {
   conversion *conv = NULL;
   tree to = TREE_TYPE (rto);
 {
   conversion *conv = NULL;
   tree to = TREE_TYPE (rto);
@@ -1138,6 +1139,11 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
      reference compatible.  We have do do this after stripping
      references from FROM.  */
   related_p = reference_related_p (to, from);
      reference compatible.  We have do do this after stripping
      references from FROM.  */
   related_p = reference_related_p (to, from);
+  /* If this is a C cast, first convert to an appropriately qualified
+     type, so that we can later do a const_cast to the desired type.  */
+  if (related_p && c_cast_p
+      && !at_least_as_qualified_p (to, from))
+    to = build_qualified_type (to, cp_type_quals (from));
   compatible_p = reference_compatible_p (to, from);
 
   if (lvalue_p && compatible_p)
   compatible_p = reference_compatible_p (to, from);
 
   if (lvalue_p && compatible_p)
@@ -1247,7 +1253,7 @@ reference_binding (tree rto, tree rfrom, tree expr, int flags)
   if (related_p && !at_least_as_qualified_p (to, from))
     return NULL;
 
   if (related_p && !at_least_as_qualified_p (to, from))
     return NULL;
 
-  conv = implicit_conversion (to, from, expr, /*c_cast_p=*/false,
+  conv = implicit_conversion (to, from, expr, c_cast_p,
                              flags);
   if (!conv)
     return NULL;
                              flags);
   if (!conv)
     return NULL;
@@ -1277,7 +1283,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
     return NULL;
 
   if (TREE_CODE (to) == REFERENCE_TYPE)
     return NULL;
 
   if (TREE_CODE (to) == REFERENCE_TYPE)
-    conv = reference_binding (to, from, expr, flags);
+    conv = reference_binding (to, from, expr, c_cast_p, flags);
   else
     conv = standard_conversion (to, from, expr, c_cast_p, flags);
 
   else
     conv = standard_conversion (to, from, expr, c_cast_p, flags);
 
@@ -6618,7 +6624,8 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
 
   /* Get the high-water mark for the CONVERSION_OBSTACK.  */
   p = conversion_obstack_alloc (0);
 
-  conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
+  conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false,
+                           LOOKUP_NORMAL);
   if (!conv || conv->bad_p)
     {
       if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
   if (!conv || conv->bad_p)
     {
       if (!(TYPE_QUALS (TREE_TYPE (type)) & TYPE_QUAL_CONST)
index 2b0d880..118d9ad 100644 (file)
@@ -1,3 +1,8 @@
+2007-04-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/31074
+       * conv3.C: New test.
+
 2007-04-13  Mike Stump  <mrs@apple.com>
 
        * obj-c++.dg/stubify-1.mm: Only run on powerpc.
 2007-04-13  Mike Stump  <mrs@apple.com>
 
        * obj-c++.dg/stubify-1.mm: Only run on powerpc.
diff --git a/gcc/testsuite/g++.dg/inherit/conv3.C b/gcc/testsuite/g++.dg/inherit/conv3.C
new file mode 100644 (file)
index 0000000..73d8c20
--- /dev/null
@@ -0,0 +1,31 @@
+// PR 31074
+// Bug: The reference cast wasn't finding the desired static_cast followed by
+// const_cast interpretation.
+
+struct Shape
+{
+  Shape() {}
+  virtual ~Shape() {}
+};
+
+struct Loop
+{
+  Loop() {}
+  virtual ~Loop() {}
+  virtual void func() {}
+};
+
+struct Rect :
+  public Shape,
+  public Loop
+{
+  Rect() {}
+  virtual ~Rect() {}
+};
+
+int main ()
+{
+  const Rect* rect = new Rect();
+  Loop &l = ((Loop&)(*rect));
+  return (&l != (const Loop *)rect);
+}