OSDN Git Service

* call.c (NEED_TEMPORARY_P): New macro.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jul 1999 01:01:16 +0000 (01:01 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 23 Jul 1999 01:01:16 +0000 (01:01 +0000)
(standard_conversion): Set it, for derived-to-base conversions.
(reference_related_p): New function.
(reference_compatible_p): Likewise.
(convert_class_to_reference): Likewise.
(direct_reference_binding): Likewise.
(reference_binding): Rework for standards-compliance.
(convert_like): Adjust accordingly.
(maybe_handle_ref_bind): Simplify; the right conversion sequences
are now built up in reference_binding.
(initialize_reference): New function.
* cp-tree.h (ICS_USER_FLAG): Document.
(ICS_THIS_FLAG): Likewise.
(ICS_BAD_FLAG): Likewise.
(NEED_TEMPORARY_P): Likewise.
(cp_lvalue_kind): New type.
(real_lvalue_p): Return it.
* error.c (dump_expr): Provide more accurate representation for
AGGR_INIT_EXPRs.
* init.c (expand_default_init): Do not try to perform implicit
conversions for a brace-enclosed initializer.
* search.c (lookup_conversions): Document.
* tree.c (lvalue_p_1): Return a cp_lvalue_kind.  Calculate
appropriately.
(real_lvalue_p): Adjust accordingly.
(lvalue_p): Likewise.
(build_cplus_new): Don't allow the creation of an abstract class.
* typeck.c (convert_for_initialization): Use initialize_reference.

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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/bitfld1.C
gcc/testsuite/g++.old-deja/g++.robertl/eb76.C

index d5d2fa1..c111a86 100644 (file)
@@ -1,3 +1,34 @@
+1999-07-22  Mark Mitchell  <mark@codesourcery.com>
+
+       * call.c (NEED_TEMPORARY_P): New macro.
+       (standard_conversion): Set it, for derived-to-base conversions.
+       (reference_related_p): New function.
+       (reference_compatible_p): Likewise.
+       (convert_class_to_reference): Likewise.
+       (direct_reference_binding): Likewise.
+       (reference_binding): Rework for standards-compliance.
+       (convert_like): Adjust accordingly.
+       (maybe_handle_ref_bind): Simplify; the right conversion sequences
+       are now built up in reference_binding.
+       (initialize_reference): New function.
+       * cp-tree.h (ICS_USER_FLAG): Document.
+       (ICS_THIS_FLAG): Likewise.
+       (ICS_BAD_FLAG): Likewise.
+       (NEED_TEMPORARY_P): Likewise.
+       (cp_lvalue_kind): New type.
+       (real_lvalue_p): Return it.
+       * error.c (dump_expr): Provide more accurate representation for
+       AGGR_INIT_EXPRs.
+       * init.c (expand_default_init): Do not try to perform implicit
+       conversions for a brace-enclosed initializer.
+       * search.c (lookup_conversions): Document.
+       * tree.c (lvalue_p_1): Return a cp_lvalue_kind.  Calculate
+       appropriately.
+       (real_lvalue_p): Adjust accordingly.
+       (lvalue_p): Likewise.
+       (build_cplus_new): Don't allow the creation of an abstract class.
+       * typeck.c (convert_for_initialization): Use initialize_reference.
+       
 1999-07-21  Gavin Romig-Koch  <gavin@cygnus.com>
 
        * lex.c (real_yylex) : Correct the test for overflow when lexing
index cdfba04..22f30dc 100644 (file)
@@ -92,6 +92,10 @@ static struct z_candidate * add_candidate PROTO((struct z_candidate *,
                                                 tree, tree, int));
 static tree source_type PROTO((tree));
 static void add_warning PROTO((struct z_candidate *, struct z_candidate *));
+static int reference_related_p PROTO ((tree, tree));
+static int reference_compatible_p PROTO ((tree, tree));
+static tree convert_class_to_reference PROTO ((tree, tree, tree));
+static tree direct_reference_binding PROTO ((tree, tree));
 
 tree
 build_vfield_ref (datum, type)
@@ -534,6 +538,10 @@ struct z_candidate {
 #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
 #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
 
+/* In a REF_BIND or a BASE_CONV, this indicates that a temporary
+   should be created to hold the result of the conversion.  */
+#define NEED_TEMPORARY_P(NODE) (TREE_LANG_FLAG_4 ((NODE)))
+
 #define USER_CONV_CAND(NODE) \
   ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
 #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
@@ -767,6 +775,11 @@ standard_conversion (to, from, expr)
       if (TREE_CODE (conv) == RVALUE_CONV)
        conv = TREE_OPERAND (conv, 0);
       conv = build_conv (BASE_CONV, to, conv);
+      /* The derived-to-base conversion indicates the initialization
+        of a parameter with base type from an object of a derived
+        type.  A temporary object is created to hold the result of
+        the conversion.  */
+      NEED_TEMPORARY_P (conv) = 1;
     }
   else
     return 0;
@@ -774,6 +787,197 @@ standard_conversion (to, from, expr)
   return conv;
 }
 
+/* Returns non-zero if T1 is reference-related to T2.  */
+
+static int
+reference_related_p (t1, t2)
+     tree t1;
+     tree t2;
+{
+  t1 = TYPE_MAIN_VARIANT (t1);
+  t2 = TYPE_MAIN_VARIANT (t2);
+
+  /* [dcl.init.ref]
+
+     Given types "cv1 T1" and "cv2 T2," "cv1 T1" is reference-related
+     to "cv2 T2" if T1 is the same type as T2, or T1 is a base class
+     of T2.  */
+  return (same_type_p (t1, t2)
+         || (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
+             && DERIVED_FROM_P (t1, t2)));
+}
+
+/* Returns non-zero if T1 is reference-compatible with T2.  */
+
+static int
+reference_compatible_p (t1, t2)
+     tree t1;
+     tree t2;
+{
+  /* [dcl.init.ref]
+
+     "cv1 T1" is reference compatible with "cv2 T2" if T1 is
+     reference-related to T2 and cv1 is the same cv-qualification as,
+     or greater cv-qualification than, cv2.  */
+  return (reference_related_p (t1, t2)
+         && at_least_as_qualified_p (t1, t2));
+}
+
+/* Determine whether or not the EXPR (of class type S) can be
+   converted to T as in [over.match.ref].  */
+
+static tree
+convert_class_to_reference (t, s, expr)
+     tree t;
+     tree s;
+     tree expr;
+{
+  tree conversions;
+  tree arglist;
+  tree conv;
+  struct z_candidate *candidates;
+  struct z_candidate *cand;
+
+  /* [over.match.ref]
+
+     Assuming that "cv1 T" is the underlying type of the reference
+     being initialized, and "cv S" is the type of the initializer
+     expression, with S a class type, the candidate functions are
+     selected as follows:
+
+     --The conversion functions of S and its base classes are
+       considered.  Those that are not hidden within S and yield type
+       "reference to cv2 T2", where "cv1 T" is reference-compatible
+       (_dcl.init.ref_) with "cv2 T2", are candidate functions.
+
+     The argument list has one argument, which is the initializer
+     expression.  */
+
+  candidates = 0;
+
+  /* Conceptually, we should take the address of EXPR and put it in
+     the argument list.  Unfortunately, however, that can result in
+     error messages, which we should not issue now because we are just
+     trying to find a conversion operator.  Therefore, we use NULL,
+     cast to the appropriate type.  */
+  arglist = build_int_2 (0, 0);
+  TREE_TYPE (arglist) = build_pointer_type (s);
+  arglist = build_scratch_list (NULL_TREE, arglist);
+  
+  for (conversions = lookup_conversions (s);
+       conversions;
+       conversions = TREE_CHAIN (conversions))
+    {
+      tree fns = TREE_VALUE (conversions);
+
+      while (fns)
+       {
+         tree f = OVL_CURRENT (fns);
+         tree t2 = TREE_TYPE (TREE_TYPE (f));
+         struct z_candidate *old_candidates = candidates;
+
+         /* If this is a template function, try to get an exact
+             match.  */
+         if (TREE_CODE (f) == TEMPLATE_DECL)
+           {
+             candidates 
+               = add_template_candidate (candidates,
+                                         f,
+                                         NULL_TREE,
+                                         arglist,
+                                         build_reference_type (t),
+                                         LOOKUP_NORMAL,
+                                         DEDUCE_CONV);
+             
+             if (candidates != old_candidates)
+               {
+                 /* Now, see if the conversion function really returns
+                    an lvalue of the appropriate type.  From the
+                    point of view of unification, simply returning an
+                    rvalue of the right type is good enough.  */
+                 f = candidates->fn;
+                 t2 = TREE_TYPE (TREE_TYPE (f));
+                 if (TREE_CODE (t2) != REFERENCE_TYPE
+                     || !reference_compatible_p (t, TREE_TYPE (t2)))
+                   candidates = candidates->next;
+               }
+           }
+         else if (TREE_CODE (t2) == REFERENCE_TYPE
+                  && reference_compatible_p (t, TREE_TYPE (t2)))
+           candidates 
+             = add_function_candidate (candidates, f, arglist, 
+                                       LOOKUP_NORMAL);
+
+         if (candidates != old_candidates)
+           candidates->basetype_path = TREE_PURPOSE (conversions);
+
+         fns = OVL_NEXT (fns);
+       }
+    }
+
+  /* If none of the conversion functions worked out, let our caller
+     know.  */
+  if (!any_viable (candidates))
+    return NULL_TREE;
+  
+  candidates = splice_viable (candidates);
+  cand = tourney (candidates);
+  if (!cand)
+    return NULL_TREE;
+
+  conv = build_conv (IDENTITY_CONV, s, expr);
+  conv = build_conv (USER_CONV,
+                    non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
+                    expr);
+  TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
+  ICS_USER_FLAG (conv) = 1;
+  if (cand->viable == -1)
+    ICS_BAD_FLAG (conv) = 1;
+  cand->second_conv = conv;
+
+  return conv;
+}
+
+/* A reference of the indicated TYPE is being bound directly to the
+   expression represented by the implicit conversion sequence CONV.
+   Return a conversion sequence for this binding.  */
+
+static tree
+direct_reference_binding (type, conv)
+     tree type;
+     tree conv;
+{
+  tree t = TREE_TYPE (type);
+
+  /* [over.ics.rank] 
+     
+     When a parameter of reference type binds directly
+     (_dcl.init.ref_) to an argument expression, the implicit
+     conversion sequence is the identity conversion, unless the
+     argument expression has a type that is a derived class of the
+     parameter type, in which case the implicit conversion sequence is
+     a derived-to-base Conversion.
+        
+     If the parameter binds directly to the result of applying a
+     conversion function to the argument expression, the implicit
+     conversion sequence is a user-defined conversion sequence
+     (_over.ics.user_), with the second standard conversion sequence
+     either an identity conversion or, if the conversion function
+     returns an entity of a type that is a derived class of the
+     parameter type, a derived-to-base conversion.  */
+  if (!same_type_p (TYPE_MAIN_VARIANT (t),
+                   TYPE_MAIN_VARIANT (TREE_TYPE (conv))))
+    {
+      /* Represent the derived-to-base conversion.  */
+      conv = build_conv (BASE_CONV, t, conv);
+      /* We will actually be binding to the base-class subobject in
+        the derived class, so we mark this conversion appropriately.
+        That way, convert_like knows not to generate a temporary.  */
+      NEED_TEMPORARY_P (conv) = 0;
+    }
+  return build_conv (REF_BIND, type, conv);
+}
+
 /* Returns the conversion path from type FROM to reference type TO for
    purposes of reference binding.  For lvalue binding, either pass a
    reference type to FROM or an lvalue expression to EXPR.
@@ -786,11 +990,12 @@ reference_binding (rto, rfrom, expr, flags)
      tree rto, rfrom, expr;
      int flags;
 {
-  tree conv;
-  int lvalue = 1;
+  tree conv = NULL_TREE;
   tree to = TREE_TYPE (rto);
   tree from = rfrom;
-  int related;
+  int related_p;
+  int compatible_p;
+  cp_lvalue_kind lvalue_p = clk_none;
 
   if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
     {
@@ -800,54 +1005,123 @@ reference_binding (rto, rfrom, expr, flags)
       from = TREE_TYPE (expr);
     }
 
-  if (TREE_CODE (from) == REFERENCE_TYPE)
-    from = TREE_TYPE (from);
-  else if (! expr || ! real_lvalue_p (expr))
-    lvalue = 0;
+  related_p = reference_related_p (to, from);
+  compatible_p = reference_compatible_p (to, from);
 
-  related = (same_type_p (TYPE_MAIN_VARIANT (to),
-                         TYPE_MAIN_VARIANT (from))
-            || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
-                && DERIVED_FROM_P (to, from)));
+  if (TREE_CODE (from) == REFERENCE_TYPE)
+    {
+      /* Anything with reference type is an lvalue.  */
+      lvalue_p = clk_ordinary;
+      from = TREE_TYPE (from);
+    }
+  else if (expr)
+    lvalue_p = real_lvalue_p (expr);
 
-  if (lvalue && related && at_least_as_qualified_p (to, from))
+  if (lvalue_p && compatible_p)
     {
-      conv = build1 (IDENTITY_CONV, from, expr);
+      /* [dcl.init.ref]
 
-      if (same_type_p (TYPE_MAIN_VARIANT (to),
-                      TYPE_MAIN_VARIANT (from)))
-       conv = build_conv (REF_BIND, rto, conv);
-      else
-       {
-         conv = build_conv (REF_BIND, rto, conv);
-         ICS_STD_RANK (conv) = STD_RANK;
-       }
+        If the intializer expression 
+        
+        -- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
+           is reference-compatible with "cv2 T2,"
+        
+        the reference is bound directly to the initializer exprssion
+        lvalue.  */
+      conv = build1 (IDENTITY_CONV, from, expr);
+      conv = direct_reference_binding (rto, conv);
+      if ((lvalue_p & clk_bitfield) != 0 
+         && CP_TYPE_CONST_NON_VOLATILE_P (to))
+       /* For the purposes of overload resolution, we ignore the fact
+          this expression is a bitfield. (In particular,
+          [over.ics.ref] says specifically that a function with a
+          non-const reference parameter is viable even if the
+          argument is a bitfield.)
+
+          However, when we actually call the function we must create
+          a temporary to which to bind the reference.  If the
+          reference is volatile, or isn't const, then we cannot make
+          a temporary, so we just issue an error when the conversion
+          actually occurs.  */
+       NEED_TEMPORARY_P (conv) = 1;
+      return conv;
     }
-  else
-    conv = NULL_TREE;
-
-  if (! conv)
+  else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
     {
-      conv = standard_conversion (to, rfrom, expr);
+      /* [dcl.init.ref]
+
+        If the initializer exprsesion
+
+        -- has a class type (i.e., T2 is a class type) can be
+           implicitly converted to an lvalue of type "cv3 T3," where
+           "cv1 T1" is reference-compatible with "cv3 T3".  (this
+           conversion is selected by enumerating the applicable
+           conversion functions (_over.match.ref_) and choosing the
+           best one through overload resolution.  (_over.match_). 
+
+        the reference is bound to the lvalue result of the conversion
+       in the second case.  */
+      conv = convert_class_to_reference (to, from, expr);
       if (conv)
-       {
-         conv = build_conv (REF_BIND, rto, conv);
+       return direct_reference_binding (rto, conv);
+    }
 
-         /* Bind directly to a base subobject of a class rvalue.  Do it
-             after building the conversion for proper handling of ICS_RANK.  */
-         if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV)
-           TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0);
-       }
-      if (conv
-         && ((! (CP_TYPE_CONST_NON_VOLATILE_P (to)
-                 && (flags & LOOKUP_NO_TEMP_BIND) == 0))
-             /* If T1 is reference-related to T2, cv1 must be the same
-                cv-qualification as, or greater cv-qualification than,
-                cv2; otherwise, the program is ill-formed.  */
-             || (related && !at_least_as_qualified_p (to, from))))
-       ICS_BAD_FLAG (conv) = 1;
+  /* [over.ics.rank]
+     
+     When a parameter of reference type is not bound directly to an
+     argument expression, the conversion sequence is the one required
+     to convert the argument expression to the underlying type of the
+     reference according to _over.best.ics_.  Conceptually, this
+     conversion sequence corresponds to copy-initializing a temporary
+     of the underlying type with the argument expression.  Any
+     difference in top-level cv-qualification is subsumed by the
+     initialization itself and does not constitute a conversion.  */
+
+  /* [dcl.init.ref]
+
+     Otherwise, the reference shall be to a non-volatile const type.  */
+  if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
+    return NULL_TREE;
+
+  /* [dcl.init.ref]
+     
+     If the initializer expression is an rvalue, with T2 a class type,
+     and "cv1 T1" is reference-compatible with "cv2 T2", the reference
+     is bound in one of the following ways:
+     
+     -- The reference is bound to the object represented by the rvalue
+        or to a sub-object within that object.  
+
+     In this case, the implicit conversion sequence is supposed to be
+     same as we would obtain by generating a temporary.  Fortunately,
+     if the types are reference compatible, then this is either an
+     identity conversion or the derived-to-base conversion, just as
+     for direct binding.  */
+  if (CLASS_TYPE_P (from) && compatible_p)
+    {
+      conv = build1 (IDENTITY_CONV, from, expr);
+      return direct_reference_binding (rto, conv);
     }
 
+  /* [dcl.init.ref]
+
+     Otherwise, a temporary of type "cv1 T1" is created and
+     initialized from the initializer expression using the rules for a
+     non-reference copy initialization.  If T1 is reference-related to
+     T2, cv1 must be the same cv-qualification as, or greater
+     cv-qualification than, cv2; otherwise, the program is ill-formed.  */
+  if (related_p && !at_least_as_qualified_p (to, from))
+    return NULL_TREE;
+
+  conv = implicit_conversion (to, from, expr, flags);
+  if (!conv)
+    return NULL_TREE;
+
+  conv = build_conv (REF_BIND, rto, conv);
+  /* This reference binding, unlike those above, requires the
+     creation of a temporary.  */
+  NEED_TEMPORARY_P (conv) = 1;
+
   return conv;
 }
 
@@ -2885,7 +3159,8 @@ convert_like (convs, expr)
 {
   if (ICS_BAD_FLAG (convs)
       && TREE_CODE (convs) != USER_CONV
-      && TREE_CODE (convs) != AMBIG_CONV)
+      && TREE_CODE (convs) != AMBIG_CONV
+      && TREE_CODE (convs) != REF_BIND)
     {
       tree t = convs; 
       for (; t; t = TREE_OPERAND (t, 0))
@@ -2938,8 +3213,6 @@ convert_like (convs, expr)
     case IDENTITY_CONV:
       if (type_unknown_p (expr))
        expr = instantiate_type (TREE_TYPE (convs), expr, 1);
-      if (TREE_READONLY_DECL_P (expr))
-       expr = decl_constant_value (expr);
       return expr;
     case AMBIG_CONV:
       /* Call build_user_type_conversion again for the error.  */
@@ -2954,6 +3227,12 @@ convert_like (convs, expr)
   if (expr == error_mark_node)
     return error_mark_node;
 
+  /* Convert a constant variable to its underlying value, unless we
+     are about to bind it to a reference, in which case we need to
+     leave it as an lvalue.  */
+  if (TREE_READONLY_DECL_P (expr) && TREE_CODE (convs) != REF_BIND)
+    expr = decl_constant_value (expr);
+
   switch (TREE_CODE (convs))
     {
     case RVALUE_CONV:
@@ -2961,6 +3240,12 @@ convert_like (convs, expr)
        return expr;
       /* else fall through */
     case BASE_CONV:
+      if (TREE_CODE (convs) == BASE_CONV
+         && !NEED_TEMPORARY_P (convs))
+       /* We are going to bind a reference directly to a base-class
+          subobject of EXPR.  We don't have to generate any code
+          here.  */
+       return expr;
       {
        tree cvt_expr = build_user_type_conversion
          (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
@@ -2988,10 +3273,37 @@ convert_like (convs, expr)
       }
 
     case REF_BIND:
-      return convert_to_reference
-       (TREE_TYPE (convs), expr,
-        CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
-        error_mark_node);
+      {
+       tree ref_type = TREE_TYPE (convs);
+
+       /* If necessary, create a temporary.  */
+       if (NEED_TEMPORARY_P (convs))
+         {
+           tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
+           tree slot = build_decl (VAR_DECL, NULL_TREE, type);
+           DECL_ARTIFICIAL (slot) = 1;
+           expr = build (TARGET_EXPR, type, slot, expr,
+                         NULL_TREE, NULL_TREE);
+           TREE_SIDE_EFFECTS (expr) = 1;
+         }
+
+       /* Take the address of the thing to which we will bind the
+          reference.  */
+       expr = build_unary_op (ADDR_EXPR, expr, 1);
+       if (expr == error_mark_node)
+         return error_mark_node;
+
+       /* Convert it to a pointer to the type referred to by the
+          reference.  This will adjust the pointer if a derived to
+          base conversion is being performed.  */
+       expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)), 
+                          expr);
+       /* Convert the pointer to the desired reference type.  */
+       expr = build1 (NOP_EXPR, ref_type, expr);
+
+       return expr;
+      }
+
     case LVALUE_CONV:
       return decay_conversion (expr);
 
@@ -3687,43 +3999,8 @@ maybe_handle_ref_bind (ics, target_type)
 {
   if (TREE_CODE (*ics) == REF_BIND)
     {
-      /* [over.ics.rank] 
-        
-        When a parameter of reference type binds directly
-        (_dcl.init.ref_) to an argument expression, the implicit
-        conversion sequence is the identity conversion, unless the
-        argument expression has a type that is a derived class of the
-        parameter type, in which case the implicit conversion
-        sequence is a derived-to-base Conversion.
-        
-        If the parameter binds directly to the result of applying a
-        conversion function to the argument expression, the implicit
-        conversion sequence is a user-defined conversion sequence
-        (_over.ics.user_), with the second standard conversion
-        sequence either an identity conversion or, if the conversion
-        function returns an entity of a type that is a derived class
-        of the parameter type, a derived-to-base Conversion.
-        
-        When a parameter of reference type is not bound directly to
-        an argument expression, the conversion sequence is the one
-        required to convert the argument expression to the underlying
-        type of the reference according to _over.best.ics_.
-        Conceptually, this conversion sequence corresponds to
-        copy-initializing a temporary of the underlying type with the
-        argument expression.  Any difference in top-level
-        cv-qualification is subsumed by the initialization itself and
-        does not constitute a conversion.  */
-
-      tree old_ics = *ics;
-
       *target_type = TREE_TYPE (TREE_TYPE (*ics));
       *ics = TREE_OPERAND (*ics, 0);
-      if (TREE_CODE (*ics) == IDENTITY_CONV
-         && is_properly_derived_from (TREE_TYPE (*ics), *target_type))
-       *ics = build_conv (BASE_CONV, *target_type, *ics);
-      ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
-      ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
-      
       return 1;
     }
   
@@ -4386,3 +4663,24 @@ can_convert_arg (to, from, arg)
   tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
   return (t && ! ICS_BAD_FLAG (t));
 }
+
+/* Convert EXPR to the indicated reference TYPE, in a way suitable for
+   initializing a variable of that TYPE.  Return the converted
+   expression.  */
+
+tree
+initialize_reference (type, expr)
+     tree type;
+     tree expr;
+{
+  tree conv;
+
+  conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
+  if (!conv || ICS_BAD_FLAG (conv))
+    {
+      cp_error ("could not convert `%E' to `%T'", expr, type);
+      return error_mark_node;
+    }
+
+  return convert_like (conv, expr);
+}
index 55c93ea..50d28ca 100644 (file)
@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA.  */
       TREE_INDIRECT_USING (in NAMESPACE_DECL).
       IDENTIFIER_MARKED (used by search routines).
       LOCAL_BINDING_P (in CPLUS_BINDING)
+      ICS_USER_FLAG (in _CONV)
    1: IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -43,17 +44,21 @@ Boston, MA 02111-1307, USA.  */
       C_DECLARED_LABEL_FLAG.
       INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
       BASELINK_P (in TREE_LIST)
+      ICS_ELLIPSIS_FLAG (in _CONV)
    2: IDENTIFIER_OPNAME_P.
       BINFO_VBASE_MARKED.
       BINFO_FIELDS_MARKED.
       TYPE_VIRTUAL_P.
+      ICS_THIS_FLAG (in _CONV)
    3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
       BINFO_VTABLE_PATH_MARKED.
       BINFO_PUSHDECLS_MARKED.
       (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
+      ICS_BAD_FLAG (in _CONV)
    4: BINFO_NEW_VTABLE_MARKED.
       TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
           or FIELD_DECL).
+      NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
    5: Not used.
    6: Not used.
 
@@ -2140,6 +2145,14 @@ extern int flag_new_for_scope;
 enum tag_types { record_type, class_type, union_type, enum_type,
                   signature_type };
 
+/* The various kinds of lvalues we distinguish.  */
+typedef enum cp_lvalue_kind {
+  clk_none = 0,     /* Things that are not an lvalue.  */
+  clk_ordinary = 1, /* An ordinary lvalue.  */
+  clk_class = 2,    /* An rvalue of class-type.  */
+  clk_bitfield = 4, /* An lvalue for a bit-field.  */
+} cp_lvalue_kind;
+
 /* Zero means prototype weakly, as in ANSI C (no args means nothing).
    Each language context defines how this variable should be set.  */
 extern int strict_prototype;
@@ -2753,6 +2766,7 @@ extern int enforce_access                       PROTO((tree, tree));
 extern tree convert_default_arg                 PROTO((tree, tree, tree));
 extern tree convert_arg_to_ellipsis             PROTO((tree));
 extern int is_properly_derived_from             PROTO((tree, tree));
+extern tree initialize_reference                PROTO((tree, tree));
 
 /* in class.c */
 extern tree build_vbase_path                   PROTO((enum tree_code, tree, tree, tree, int));
@@ -3363,7 +3377,7 @@ extern tree arbitrate_lookup                      PROTO((tree, tree, tree));
 extern int pod_type_p                          PROTO((tree));
 extern void unshare_base_binfos                        PROTO((tree));
 extern int member_p                            PROTO((tree));
-extern int real_lvalue_p                       PROTO((tree));
+extern cp_lvalue_kind real_lvalue_p            PROTO((tree));
 extern tree build_min                          PVPROTO((enum tree_code, tree, ...));
 extern tree build_min_nt                       PVPROTO((enum tree_code, ...));
 extern tree min_tree_cons                      PROTO((tree, tree, tree));
index 544e66e..60d73de 100644 (file)
@@ -1409,7 +1409,22 @@ dump_expr (t, nop)
       break;
 
     case AGGR_INIT_EXPR:
-      OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
+      {
+       tree fn = NULL_TREE;
+       
+       if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
+         fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
+
+       if (fn && TREE_CODE (fn) == FUNCTION_DECL)
+         {
+           if (DECL_CONSTRUCTOR_P (fn))
+             OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
+           else
+             dump_decl (fn, 0);
+         }
+       else
+         dump_expr (TREE_OPERAND (t, 0), 0);
+      }
       OB_PUTC ('(');
       if (TREE_OPERAND (t, 1))
        dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
index de3491a..8469fe6 100644 (file)
@@ -1177,6 +1177,10 @@ expand_default_init (binfo, true_exp, exp, init, flags)
           to run a new constructor; and catching an exception, where we
           have already built up the constructor call so we could wrap it
           in an exception region.  */;
+      else if (TREE_CODE (init) == CONSTRUCTOR)
+       /* A brace-enclosed initializer has whatever type is
+          required.  There's no need to convert it.  */
+       ;
       else
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
 
index f1be6db..6cde690 100644 (file)
@@ -3150,6 +3150,12 @@ add_conversions (binfo, data)
   return NULL_TREE;
 }
 
+/* Return a TREE_LIST containing all the non-hidden user-defined
+   conversion functions for TYPE (and its base-classes).  The
+   TREE_VALUE of each node is a FUNCTION_DECL or an OVERLOAD
+   containing the conversion functions.  The TREE_PURPOSE is the BINFO
+   from which the conversion functions in this node were selected.  */
+
 tree
 lookup_conversions (type)
      tree type;
index 2795c67..c32bf8f 100644 (file)
@@ -36,27 +36,30 @@ static int list_hash PROTO((tree, tree, tree));
 static tree list_hash_lookup PROTO((int, tree, tree, tree));
 static void propagate_binfo_offsets PROTO((tree, tree));
 static int avoid_overlap PROTO((tree, tree));
-static int lvalue_p_1 PROTO((tree, int));
+static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
 static int equal_functions PROTO((tree, tree));
 static tree no_linkage_helper PROTO((tree));
 static tree build_srcloc PROTO((char *, int));
 
 #define CEIL(x,y) (((x) + (y) - 1) / (y))
 
-/* Returns non-zero if REF is an lvalue.  If
-   TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
-   are considered lvalues.  */
+/* If REF is an lvalue, returns the kind of lvalue that REF is.
+   Otherwise, returns clk_none.  If TREAT_CLASS_RVALUES_AS_LVALUES is
+   non-zero, rvalues of class type are considered lvalues.  */
 
-static int
+static cp_lvalue_kind
 lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
      tree ref;
      int treat_class_rvalues_as_lvalues;
 {
+  cp_lvalue_kind op1_lvalue_kind = clk_none;
+  cp_lvalue_kind op2_lvalue_kind = clk_none;
+
   if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
-    return 1;
+    return clk_ordinary;
 
   if (ref == current_class_ptr && flag_this_is_variable <= 0)
-    return 0;
+    return clk_none;
 
   switch (TREE_CODE (ref))
     {
@@ -64,7 +67,6 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
         what they refer to are valid lvals.  */
     case PREINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
-    case COMPONENT_REF:
     case SAVE_EXPR:
     case UNSAVE_EXPR:
     case TRY_CATCH_EXPR:
@@ -75,20 +77,37 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
       return lvalue_p_1 (TREE_OPERAND (ref, 0),
                         treat_class_rvalues_as_lvalues);
 
+    case COMPONENT_REF:
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
+                                   treat_class_rvalues_as_lvalues);
+      if (op1_lvalue_kind 
+         /* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
+            situations.  */
+         && TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
+         && DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
+       {
+         /* Clear the ordinary bit.  If this object was a class
+            rvalue we want to preserve that information.  */
+         op1_lvalue_kind &= ~clk_ordinary;
+         /* The lvalue is for a btifield.  */
+         op1_lvalue_kind |= clk_bitfield;
+       }
+      return op1_lvalue_kind;
+
     case STRING_CST:
-      return 1;
+      return clk_ordinary;
 
     case VAR_DECL:
       if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
          && DECL_LANG_SPECIFIC (ref)
          && DECL_IN_AGGR_P (ref))
-       return 0;
+       return clk_none;
     case INDIRECT_REF:
     case ARRAY_REF:
     case PARM_DECL:
     case RESULT_DECL:
       if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
-       return 1;
+       return clk_ordinary;
       break;
 
       /* A currently unresolved scope ref.  */
@@ -96,72 +115,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
       my_friendly_abort (103);
     case OFFSET_REF:
       if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
-       return 1;
-      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 1),
-                            treat_class_rvalues_as_lvalues));
+       return clk_ordinary;
+      /* Fall through.  */
+    case MAX_EXPR:
+    case MIN_EXPR:
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
+                                   treat_class_rvalues_as_lvalues);
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+                                   treat_class_rvalues_as_lvalues);
       break;
 
     case COND_EXPR:
-      return (lvalue_p_1 (TREE_OPERAND (ref, 1),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 2),
-                            treat_class_rvalues_as_lvalues));
+      op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
+                                   treat_class_rvalues_as_lvalues);
+      op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
+                                   treat_class_rvalues_as_lvalues);
+      break;
 
     case MODIFY_EXPR:
-      return 1;
+      return clk_ordinary;
 
     case COMPOUND_EXPR:
       return lvalue_p_1 (TREE_OPERAND (ref, 1),
-                           treat_class_rvalues_as_lvalues);
-
-    case MAX_EXPR:
-    case MIN_EXPR:
-      return (lvalue_p_1 (TREE_OPERAND (ref, 0),
-                         treat_class_rvalues_as_lvalues)
-             && lvalue_p_1 (TREE_OPERAND (ref, 1),
-                            treat_class_rvalues_as_lvalues));
+                        treat_class_rvalues_as_lvalues);
 
     case TARGET_EXPR:
-      return treat_class_rvalues_as_lvalues;
+      return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
 
     case CALL_EXPR:
-      return (treat_class_rvalues_as_lvalues
-             && IS_AGGR_TYPE (TREE_TYPE (ref)));
+      return ((treat_class_rvalues_as_lvalues
+              && IS_AGGR_TYPE (TREE_TYPE (ref)))
+             ? clk_class : clk_none);
 
     case FUNCTION_DECL:
       /* All functions (except non-static-member functions) are
         lvalues.  */
-      return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
+      return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref) 
+             ? clk_none : clk_ordinary);
 
     default:
       break;
     }
 
-  return 0;
+  /* If one operand is not an lvalue at all, then this expression is
+     not an lvalue.  */
+  if (!op1_lvalue_kind || !op2_lvalue_kind)
+    return clk_none;
+
+  /* Otherwise, it's an lvalue, and it has all the odd properties
+     contributed by either operand.  */
+  op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
+  /* It's not an ordinary lvalue if it involves either a bit-field or
+     a class rvalue.  */
+  if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
+    op1_lvalue_kind &= ~clk_ordinary;
+  return op1_lvalue_kind;
 }
 
-/* Return nonzero if REF is an lvalue valid for this language.
-   Lvalues can be assigned, unless they have TREE_READONLY, or unless
-   they are FUNCTION_DECLs.  Lvalues can have their address taken,
-   unless they have DECL_REGISTER.  */
+/* If REF is an lvalue, returns the kind of lvalue that REF is.
+   Otherwise, returns clk_none.  Lvalues can be assigned, unless they
+   have TREE_READONLY, or unless they are FUNCTION_DECLs.  Lvalues can
+   have their address taken, unless they have DECL_REGISTER.  */
 
-int
+cp_lvalue_kind
 real_lvalue_p (ref)
      tree ref;
 {
   return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
 }
 
-/* This differs from real_lvalue_p in that class rvalues are considered
-   lvalues.  */
+/* This differs from real_lvalue_p in that class rvalues are
+   considered lvalues.  */
 
 int
 lvalue_p (ref)
      tree ref;
 {
-  return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
+  return 
+    (lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
 }
 
 /* Return nonzero if REF is an lvalue valid for this language;
@@ -193,6 +224,11 @@ build_cplus_new (type, init)
   tree slot;
   tree rval;
 
+  /* Make sure that we're not trying to create an instance of an
+     abstract class.  */
+  if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
+    abstract_virtuals_error (NULL_TREE, type);
+
   if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
     return convert (type, init);
 
index fa54e37..7add550 100644 (file)
@@ -7122,8 +7122,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
 
       if (fndecl)
        savew = warningcount, savee = errorcount;
-      rhs = convert_to_reference (type, rhs, CONV_IMPLICIT, flags,
-                                 exp ? exp : error_mark_node);
+      rhs = initialize_reference (type, rhs);
       if (fndecl)
        {
          if (warningcount > savew)
index ad21fd7..07f1021 100644 (file)
@@ -1,8 +1,6 @@
 // Build don't link:
 // Based on a bug report by Stephen Vavasis <vavasis@CS.Cornell.EDU>
 
-// excess errors test - XFAIL *-*-*
-
 // declares template operator!=
 #include <utility>
 
index e2817ee..f8dba7b 100644 (file)
@@ -1,6 +1,5 @@
 //Build don't link:
 // the template operator!= interferes.  It should be in a namespace.
-// excess errors test - XFAIL *-*-*
 
 #include <utility>