call.c (merge_conversion_sequences): New function.
authorMark Mitchell <mark@codesourcery.com>
Fri, 7 Mar 2003 07:02:02 +0000 (07:02 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Fri, 7 Mar 2003 07:02:02 +0000 (07:02 +0000)
* call.c (merge_conversion_sequences): New function.
(build_conv): Set ICS_USER_FLAG for USER_CONVs.
(convert_class_to_reference): Correct handling of second
standard conversion sequence in a user-defined conversion
sequence.
(build_user_type_conversion_1): Use merge_conversion_sequences.
* cp-tree.def: Add comments for CONV nodes.

* g++.dg/init/ref3.C: New test.

From-SVN: r63930

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.def
gcc/cp/rtti.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/ref3.C [new file with mode: 0644]

index 9044978501f8c78ddf35c18fe8419a6ee557b7f8..668c6e7135ea71c73fe7c77141e02e5016dc1e25 100644 (file)
@@ -1,3 +1,13 @@
+2003-03-06  Mark Mitchell  <mark@codesourcery.com>
+
+       * call.c (merge_conversion_sequences): New function.
+       (build_conv): Set ICS_USER_FLAG for USER_CONVs.
+       (convert_class_to_reference): Correct handling of second
+       standard conversion sequence in a user-defined conversion
+       sequence.
+       (build_user_type_conversion_1): Use merge_conversion_sequences.
+       * cp-tree.def: Add comments for CONV nodes.
+
 2003-03-07  Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
        * error.c (init_error): Use C90 prototype style.
index c5fd77b0acf0b57f4b1d00be6a35c4d3dc009a92..15dbbe1d2b4322bcb92c0881d1ff35c2266becef 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions related to invoking methods and overloaded functions.
-   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) and
    modified by Brendan Kehoe (brendan@cygnus.com).
 
@@ -106,6 +106,7 @@ static tree call_builtin_trap (void);
 static tree prep_operand (tree);
 static void add_candidates (tree, tree, tree, tree,
                            int, struct z_candidate **);
+static tree merge_conversion_sequences (tree, tree);
 
 tree
 build_vfield_ref (tree datum, tree type)
@@ -560,7 +561,12 @@ struct z_candidate GTY(()) {
   tree fn;
   /* The arguments to use when calling this function.  */
   tree args;
+  /* The implicit conversion sequences for each of the arguments to
+     FN.  */
   tree convs;
+  /* If FN is a user-defined conversion, the standard conversion
+     sequence from the type returned by FN to the desired destination
+     type.  */
   tree second_conv;
   int viable;
   /* If FN is a member function, the binfo indicating the path used to
@@ -667,7 +673,7 @@ build_conv (enum tree_code code, tree type, tree from)
       break;
     }
   ICS_STD_RANK (t) = rank;
-  ICS_USER_FLAG (t) = ICS_USER_FLAG (from);
+  ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));
   ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
   return t;
 }
@@ -1034,15 +1040,15 @@ convert_class_to_reference (tree t, tree s, tree expr)
                                           LOOKUP_NORMAL);
          
          if (cand)
-           {
-             conv = build1 (IDENTITY_CONV, s, expr);
-             conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
-                                conv);
-             TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
-             ICS_USER_FLAG (conv) = 1;
-             cand->second_conv
-               = direct_reference_binding (reference_type, conv);
-           }
+           /* Build a standard conversion sequence indicating the
+              binding from the reference type returned by the
+              function to the desired REFERENCE_TYPE.  */
+           cand->second_conv
+             = (direct_reference_binding 
+                (reference_type, 
+                 build1 (IDENTITY_CONV, 
+                         TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
+                         NULL_TREE)));
        }
       conversions = TREE_CHAIN (conversions);
     }
@@ -1063,11 +1069,21 @@ convert_class_to_reference (tree t, tree s, tree expr)
                          build_this (expr),
                          TREE_CHAIN (cand->args));
 
-  conv = cand->second_conv;
+  /* Build a user-defined conversion sequence representing the
+     conversion.  */
+  conv = build_conv (USER_CONV,
+                    TREE_TYPE (TREE_TYPE (cand->fn)),
+                    build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+  TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
+
+  /* Merge it with the standard conversion sequence from the
+     conversion function's return type to the desired type.  */
+  cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
+
   if (cand->viable == -1)
     ICS_BAD_FLAG (conv) = 1;
   
-  return conv;
+  return cand->second_conv;
 }
 
 /* A reference of the indicated TYPE is being bound directly to the
@@ -1077,7 +1093,13 @@ convert_class_to_reference (tree t, tree s, tree expr)
 static tree
 direct_reference_binding (tree type, tree conv)
 {
-  tree t = TREE_TYPE (type);
+  tree t;
+
+  my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 20030306);
+  my_friendly_assert (TREE_CODE (TREE_TYPE (conv)) != REFERENCE_TYPE,
+                     20030306);
+
+  t = TREE_TYPE (type);
 
   /* [over.ics.rank] 
      
@@ -2428,6 +2450,35 @@ print_z_candidates (struct z_candidate *candidates)
     }
 }
 
+/* USER_SEQ is a user-defined conversion sequence, beginning with a
+   USER_CONV.  STD_SEQ is the standard conversion sequence applied to
+   the result of the conversion function to convert it to the final
+   desired type.  Merge the the two sequences into a single sequence,
+   and return the merged sequence.  */
+
+static tree
+merge_conversion_sequences (tree user_seq, tree std_seq)
+{
+  tree *t;
+
+  my_friendly_assert (TREE_CODE (user_seq) == USER_CONV,
+                     20030306);
+
+  /* Find the end of the second conversion sequence.  */
+  t = &(std_seq); 
+  while (TREE_CODE (*t) != IDENTITY_CONV)
+    t = &TREE_OPERAND (*t, 0);
+
+  /* Replace the identity conversion with the user conversion
+     sequence.  */
+  *t = user_seq;
+
+  /* The entire sequence is a user-conversion sequence.  */
+  ICS_USER_FLAG (std_seq) = 1;
+
+  return std_seq;
+}
+
 /* Returns the best overload candidate to perform the requested
    conversion.  This function is used for three the overloading situations
    described in [over.match.copy], [over.match.conv], and [over.match.ref].
@@ -2439,7 +2490,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
 {
   struct z_candidate *candidates, *cand;
   tree fromtype = TREE_TYPE (expr);
-  tree ctors = NULL_TREE, convs = NULL_TREE, *p;
+  tree ctors = NULL_TREE, convs = NULL_TREE;
   tree args = NULL_TREE;
 
   /* We represent conversion within a hierarchy using RVALUE_CONV and
@@ -2583,18 +2634,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
       return cand;
     }
 
-  for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; )
-    p = &(TREE_OPERAND (*p, 0));
-
-  *p = build
+  /* Build the user conversion sequence.  */
+  convs = build_conv
     (USER_CONV,
      (DECL_CONSTRUCTOR_P (cand->fn)
       ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
-     expr, build_zc_wrapper (cand));
-  
-  ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
+     build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
+  TREE_OPERAND (convs, 1) = build_zc_wrapper (cand);
+
+  /* Combine it with the second conversion sequence.  */
+  cand->second_conv = merge_conversion_sequences (convs,
+                                                 cand->second_conv);
+
   if (cand->viable == -1)
-    ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
+    ICS_BAD_FLAG (cand->second_conv) = 1;
 
   return cand;
 }
index f621844e350572e2ca4ad84572c027dc5bbbbcd7..86103c41eef186ee073dbad5c048ed831bec7862 100644 (file)
@@ -1,8 +1,8 @@
 /* This file contains the definitions and documentation for the
    additional tree codes used in the GNU C++ compiler (see tree.def
    for the standard codes).
-   Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998,
-   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003, 
+   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -270,7 +270,13 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
 
 DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
 
-/* And some codes for expressing conversions for overload resolution.  */
+/* The following codes are used to represent implicit conversion
+   sequences, in the sense of [over.best.ics].  The conversion
+   sequences are connected through their first operands, with the
+   first conversion to be performed at the end of the chain.
+
+   The innermost conversion (i.e, the one at the end of the chain) is
+   always an IDENTITY_CONV, corresponding to the identity conversion.  */
 
 DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
 DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
index 9ebae8b5448e302429faf4e1c75db84cfd3daae5..eab85f700504396abefad8e154592a5bd166f746 100644 (file)
@@ -378,13 +378,8 @@ get_tinfo_decl (tree type)
 static tree
 get_tinfo_ptr (tree type)
 {
-  tree exp = get_tinfo_decl (type);
-  
-   /* Convert to type_info type.  */
-  exp = build_unary_op (ADDR_EXPR, exp, 0);
-  exp = ocp_convert (type_info_ptr_type, exp, CONV_REINTERPRET, 0);
-
-  return exp;
+  return build_nop (type_info_ptr_type, 
+                   build_address (get_tinfo_decl (type)));
 }
 
 /* Return the type_info object for TYPE.  */
index 9fabfd1805cc48699f1c6ac9584ea90056193121..36715896476025c8e23fa777db3025ba15fdc1cc 100644 (file)
@@ -1,5 +1,7 @@
 2003-03-06  Mark Mitchell  <mark@codesourcery.com>
 
+       * g++.dg/init/ref3.C: New test.
+
        PR c++/9965
        * g++.dg/init/ref2.C: New test.
        
diff --git a/gcc/testsuite/g++.dg/init/ref3.C b/gcc/testsuite/g++.dg/init/ref3.C
new file mode 100644 (file)
index 0000000..776f2d0
--- /dev/null
@@ -0,0 +1,12 @@
+struct Base { };
+struct Derived : public Base { };
+struct Choose {
+  operator Base&();
+  operator Derived&();
+};
+
+void f()
+{
+  Choose c;
+  Base& ref = c;
+}