]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/8700 (unhelpful error message for binding temp to reference)
authorMark Mitchell <mark@codesourcery.com>
Tue, 11 Mar 2003 15:43:14 +0000 (15:43 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Tue, 11 Mar 2003 15:43:14 +0000 (15:43 +0000)
PR c++/8700
* call.c (convert_class_to_reference): Adjust usage of
splice_viable.
(any_viable): Remove.
(splice_viable): Combine with any_viable.
(print_z_candidates): Avoid printing duplicates.
(build_user_type_conversion_1): Adjust usage of splice_viable.
(build_new_function_call): Likewise.
(build_operator_new_call): Likewise.
(build_object_call): Likewise.
(build_conditional_expr): Likewise.
(build_new_op): Likewise.
(build_new_method_call): Likewise.
(joust): Remove spurious comment.
* cp-tree.h (DECL_FRIENDLIST): Correct documentation.
* decl2.c (arg_assoc_class): Simplify.
* friend.c (add_friend): Likewise.

From-SVN: r64173

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/friend.c

index f0421f1c44ead3eaac2725cc0e2aaa5efa51f8fa..121c2aefbac8a11c3fdcb9afed4e882fa742b914 100644 (file)
@@ -1,3 +1,23 @@
+2003-03-11  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/8700
+       * call.c (convert_class_to_reference): Adjust usage of
+       splice_viable.
+       (any_viable): Remove.
+       (splice_viable): Combine with any_viable.
+       (print_z_candidates): Avoid printing duplicates.
+       (build_user_type_conversion_1): Adjust usage of splice_viable.
+       (build_new_function_call): Likewise.
+       (build_operator_new_call): Likewise.
+       (build_object_call): Likewise.
+       (build_conditional_expr): Likewise.
+       (build_new_op): Likewise.
+       (build_new_method_call): Likewise.
+       (joust): Remove spurious comment.
+       * cp-tree.h (DECL_FRIENDLIST): Correct documentation.
+       * decl2.c (arg_assoc_class): Simplify.
+       * friend.c (add_friend): Likewise.
+
 2003-03-11  Jason Merrill  <jason@redhat.com>
 
        PR c++/8660
index ed9227f2309a0c4e883250684a6ad725da671a06..c8baf749588c7f5f13cd200e374920488ea24c6d 100644 (file)
@@ -58,8 +58,7 @@ static tree resolve_args (tree);
 static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
 static void print_z_candidates (struct z_candidate *);
 static tree build_this (tree);
-static struct z_candidate *splice_viable (struct z_candidate *);
-static bool any_viable (struct z_candidate *);
+static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
 static bool any_strictly_viable (struct z_candidate *);
 static struct z_candidate *add_template_candidate
         (struct z_candidate **, tree, tree, tree, tree, tree, 
@@ -958,6 +957,7 @@ convert_class_to_reference (tree t, tree s, tree expr)
   tree reference_type;
   struct z_candidate *candidates;
   struct z_candidate *cand;
+  bool any_viable_p;
 
   conversions = lookup_conversions (s);
   if (!conversions)
@@ -1053,12 +1053,12 @@ convert_class_to_reference (tree t, tree s, tree expr)
       conversions = TREE_CHAIN (conversions);
     }
 
+  candidates = splice_viable (candidates, pedantic, &any_viable_p);
   /* If none of the conversion functions worked out, let our caller
      know.  */
-  if (!any_viable (candidates))
+  if (!any_viable_p)
     return NULL_TREE;
-  
-  candidates = splice_viable (candidates);
+
   cand = tourney (candidates);
   if (!cand)
     return NULL_TREE;
@@ -2373,14 +2373,42 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
                                 conversion_path, 0, obj, DEDUCE_CONV);
 }
 
+/* The CANDS are the set of candidates that were considered for
+   overload resolution.  Return the set of viable candidates.  If none
+   of the candidates were viable, set *ANY_VIABLE_P to true.  STRICT_P
+   is true if a candidate should be considered viable only if it is
+   strictly viable.  */
 
-static bool
-any_viable (struct z_candidate *cands)
+static struct z_candidate*
+splice_viable (struct z_candidate *cands,
+              bool strict_p,
+              bool *any_viable_p)
 {
-  for (; cands; cands = cands->next)
-    if (pedantic ? cands->viable == 1 : cands->viable)
-      return true;
-  return false;
+  struct z_candidate *viable;
+  struct z_candidate **last_viable;
+  struct z_candidate **cand;
+
+  viable = NULL;
+  last_viable = &viable;
+  *any_viable_p = false;
+
+  cand = &cands; 
+  while (*cand) 
+    {
+      struct z_candidate *c = *cand;
+      if (strict_p ? c->viable == 1 : c->viable)
+       {
+         *last_viable = c;
+         *cand = c->next;
+         c->next = NULL;
+         last_viable = &c->next;
+         *any_viable_p = true;
+       }
+      else
+       cand = &c->next;
+    }
+
+  return viable ? viable : cands;
 }
 
 static bool
@@ -2392,22 +2420,6 @@ any_strictly_viable (struct z_candidate *cands)
   return false;
 }
 
-static struct z_candidate *
-splice_viable (struct z_candidate *cands)
-{
-  struct z_candidate **p = &cands;
-
-  for (; *p; )
-    {
-      if (pedantic ? (*p)->viable == 1 : (*p)->viable)
-       p = &((*p)->next);
-      else
-       *p = (*p)->next;
-    }
-
-  return cands;
-}
-
 static tree
 build_this (tree obj)
 {
@@ -2415,10 +2427,49 @@ build_this (tree obj)
   return build_unary_op (ADDR_EXPR, obj, 0);
 }
 
+/* Returns true iff functions are equivalent. Equivalent functions are
+   not '==' only if one is a function-local extern function or if
+   both are extern "C".  */
+
+static inline int
+equal_functions (tree fn1, tree fn2)
+{
+  if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
+      || DECL_EXTERN_C_FUNCTION_P (fn1))
+    return decls_match (fn1, fn2);
+  return fn1 == fn2;
+}
+
 static void
 print_z_candidates (struct z_candidate *candidates)
 {
-  const char *str = "candidates are:";
+  const char *str;
+  struct z_candidate *cand1;
+  struct z_candidate **cand2;
+
+  /* There may be duplicates in the set of candidates.  We put off
+     checking this condition as long as possible, since we have no way
+     to eliminate duplicates from a set of functions in less than n^2
+     time.  Now we are about to emit an error message, so it is more
+     permissible to go slowly.  */
+  for (cand1 = candidates; cand1; cand1 = cand1->next)
+    {
+      tree fn = cand1->fn;
+      /* Skip builtin candidates and conversion functions.  */
+      if (TREE_CODE (fn) != FUNCTION_DECL)
+       continue;
+      cand2 = &cand1->next;
+      while (*cand2)
+       {
+         if (TREE_CODE ((*cand2)->fn) == FUNCTION_DECL
+             && equal_functions (fn, (*cand2)->fn))
+           *cand2 = (*cand2)->next;
+         else
+           cand2 = &(*cand2)->next;
+       }
+    }
+
+  str = "candidates are:";
   for (; candidates; candidates = candidates->next)
     {
       if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
@@ -2487,6 +2538,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
   tree fromtype = TREE_TYPE (expr);
   tree ctors = NULL_TREE, convs = NULL_TREE;
   tree args = NULL_TREE;
+  bool any_viable_p;
 
   /* We represent conversion within a hierarchy using RVALUE_CONV and
      BASE_CONV, as specified by [over.best.ics]; these become plain
@@ -2602,12 +2654,11 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
        }
     }
 
-  if (! any_viable (candidates))
+  candidates = splice_viable (candidates, pedantic, &any_viable_p);
+  if (!any_viable_p)
     return 0;
 
-  candidates = splice_viable (candidates);
   cand = tourney (candidates);
-
   if (cand == 0)
     {
       if (flags & LOOKUP_COMPLAIN)
@@ -2802,15 +2853,11 @@ perform_overload_resolution (tree fn,
                  LOOKUP_NORMAL,
                  candidates);
 
-  if (! any_viable (*candidates))
-    {
-      *any_viable_p = false;
-      return NULL;
-    }
+  *candidates = splice_viable (*candidates, pedantic, any_viable_p);
+  if (!*any_viable_p)
+    return NULL;
 
-  *candidates = splice_viable (*candidates);
   cand = tourney (*candidates);
-
   return cand;
 }
 
@@ -2840,7 +2887,7 @@ build_new_function_call (tree fn, tree args)
               DECL_NAME (OVL_CURRENT (fn)), args);
       else
        error ("call of overloaded `%D(%A)' is ambiguous",
-              DECL_NAME (OVL_FUNCTION (fn)), args);
+              DECL_NAME (OVL_CURRENT (fn)), args);
       if (candidates)
        print_z_candidates (candidates);
       return error_mark_node;
@@ -2884,7 +2931,7 @@ build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
               DECL_NAME (OVL_CURRENT (fns)), args);
       else
        error ("call of overlopaded `%D(%A)' is ambiguous",
-              DECL_NAME (OVL_FUNCTION (fns)), args);
+              DECL_NAME (OVL_CURRENT (fns)), args);
       if (candidates)
        print_z_candidates (candidates);
       return error_mark_node;
@@ -2943,6 +2990,7 @@ build_object_call (tree obj, tree args)
   struct z_candidate *candidates = 0, *cand;
   tree fns, convs, mem_args = NULL_TREE;
   tree type = TREE_TYPE (obj);
+  bool any_viable_p;
 
   if (TYPE_PTRMEMFUNC_P (type))
     {
@@ -3011,16 +3059,15 @@ build_object_call (tree obj, tree args)
          }
     }
 
-  if (! any_viable (candidates))
+  candidates = splice_viable (candidates, pedantic, &any_viable_p);
+  if (!any_viable_p)
     {
       error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
       print_z_candidates (candidates);
       return error_mark_node;
     }
 
-  candidates = splice_viable (candidates);
   cand = tourney (candidates);
-
   if (cand == 0)
     {
       error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
@@ -3302,6 +3349,7 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
     {
       tree args[3];
       tree conv;
+      bool any_viable_p;
 
       /* Rearrange the arguments so that add_builtin_candidate only has
         to know about two args.  In build_builtin_candidates, the
@@ -3320,13 +3368,13 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
 
         If the overload resolution fails, the program is
         ill-formed.  */
-      if (!any_viable (candidates))
+      candidates = splice_viable (candidates, pedantic, &any_viable_p);
+      if (!any_viable_p)
        {
          op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
          print_z_candidates (candidates);
          return error_mark_node;
        }
-      candidates = splice_viable (candidates);
       cand = tourney (candidates);
       if (!cand)
        {
@@ -3565,7 +3613,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
   tree args[3];
   enum tree_code code2 = NOP_EXPR;
   tree conv;
-  bool viable_candidates;
+  bool strict_p;
+  bool any_viable_p;
 
   if (error_operand_p (arg1) 
       || error_operand_p (arg2) 
@@ -3675,15 +3724,16 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
         operators.  The built-in candidate set for COMPONENT_REF
         would be empty too, but since there are no such built-in
         operators, we accept non-strict matches for them.  */
-      viable_candidates = any_strictly_viable (candidates);
+      strict_p = true;
       break;
 
     default:
-      viable_candidates = any_viable (candidates);
+      strict_p = pedantic;
       break;
     }      
 
-  if (! viable_candidates)
+  candidates = splice_viable (candidates, strict_p, &any_viable_p);
+  if (!any_viable_p)
     {
       switch (code)
        {
@@ -3717,9 +3767,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3)
        }
       return error_mark_node;
     }
-  candidates = splice_viable (candidates);
-  cand = tourney (candidates);
 
+  cand = tourney (candidates);
   if (cand == 0)
     {
       if (flags & LOOKUP_COMPLAIN)
@@ -4885,6 +4934,7 @@ build_new_method_call (tree instance, tree fns, tree args,
   tree fn;
   tree class_type;
   int template_only = 0;
+  bool any_viable_p;
 
   my_friendly_assert (instance != NULL_TREE, 20020729);
 
@@ -5001,7 +5051,8 @@ build_new_method_call (tree instance, tree fns, tree args,
                                flags);
     }
 
-  if (! any_viable (candidates))
+  candidates = splice_viable (candidates, pedantic, &any_viable_p);
+  if (!any_viable_p)
     {
       /* XXX will LOOKUP_SPECULATIVELY be needed when this is done?  */
       if (flags & LOOKUP_SPECULATIVELY)
@@ -5023,9 +5074,8 @@ build_new_method_call (tree instance, tree fns, tree args,
       print_z_candidates (candidates);
       return error_mark_node;
     }
-  candidates = splice_viable (candidates);
-  cand = tourney (candidates);
 
+  cand = tourney (candidates);
   if (cand == 0)
     {
       char *pretty_name;
@@ -5555,19 +5605,6 @@ add_warning (struct z_candidate *winner, struct z_candidate *loser)
                                winner->warnings);
 }
 
-/* Returns true iff functions are equivalent. Equivalent functions are
-   not '==' only if one is a function-local extern function or if
-   both are extern "C".  */
-
-static inline int
-equal_functions (tree fn1, tree fn2)
-{
-  if (DECL_LOCAL_FUNCTION_P (fn1) || DECL_LOCAL_FUNCTION_P (fn2)
-      || DECL_EXTERN_C_FUNCTION_P (fn1))
-    return decls_match (fn1, fn2);
-  return fn1 == fn2;
-}
-
 /* Compare two candidates for overloading as described in
    [over.match.best].  Return values:
 
@@ -5748,7 +5785,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
          TREE_VEC_LENGTH (cand1->convs)
         - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
            - DECL_CONSTRUCTOR_P (cand1->fn)));
-      /* HERE */
       if (winner)
         return winner;
     }
@@ -5805,7 +5841,7 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
   if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
       && equal_functions (cand1->fn, cand2->fn))
     return 1;
-
 tweak:
 
   /* Extension: If the worst conversion for one candidate is worse than the
index a45e546f5bb63f93b635cd5033a4f91cc55dc81c..db603bacb737292d371a0e07128e34ff9b71ca26 100644 (file)
@@ -2657,14 +2657,8 @@ struct lang_decl GTY(())
 /* The format of each node in the DECL_FRIENDLIST is as follows:
 
    The TREE_PURPOSE will be the name of a function, i.e., an
-   IDENTIFIER_NODE.  The TREE_VALUE will be itself a TREE_LIST, the
-   list of functions with that name which are friends.  The
-   TREE_PURPOSE of each node in this sublist will be error_mark_node,
-   if the function was declared a friend individually, in which case
-   the TREE_VALUE will be the function_decl.  If, however, all
-   functions with a given name in a class were declared to be friends,
-   the TREE_PUROSE will be the class type, and the TREE_VALUE will be
-   NULL_TREE.  */
+   IDENTIFIER_NODE.  The TREE_VALUE will be itself a TREE_LIST, whose
+   TREE_VALUEs are friends with the given name.  */
 #define DECL_FRIENDLIST(NODE)          (DECL_INITIAL (NODE))
 #define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
 #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
index 6a4250efb38f7cf5105bc769bd5137567fb966ac..c2f1f6c35597340b516165841b3c5be267c1ab72 100644 (file)
@@ -3936,13 +3936,12 @@ arg_assoc_class (struct arg_lookup *k, tree type)
   /* Process friends.  */
   for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list; 
        list = TREE_CHAIN (list))
-    if (k->name == TREE_PURPOSE (list))
-      for (friends = TREE_VALUE (list); friends; 
+    if (k->name == FRIEND_NAME (list))
+      for (friends = FRIEND_DECLS (list); friends; 
           friends = TREE_CHAIN (friends))
        /* Only interested in global functions with potentially hidden
            (i.e. unqualified) declarations.  */
-       if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
-           && decl_namespace (TREE_VALUE (friends)) == context)
+       if (decl_namespace (TREE_VALUE (friends)) == context)
          if (add_function (k, TREE_VALUE (friends)))
            return true;
 
index 56b64525233062658f3afbd7b8e203523fec5dd4..3ecd3177195a509a4f4a1140e1cb092a91c72520 100644 (file)
@@ -165,7 +165,7 @@ add_friend (type, decl)
 
          maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
 
-         TREE_VALUE (list) = tree_cons (error_mark_node, decl,
+         TREE_VALUE (list) = tree_cons (NULL_TREE, decl,
                                         TREE_VALUE (list));
          return;
        }
@@ -175,7 +175,7 @@ add_friend (type, decl)
   maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
 
   DECL_FRIENDLIST (typedecl)
-    = tree_cons (DECL_NAME (decl), build_tree_list (error_mark_node, decl),
+    = tree_cons (DECL_NAME (decl), build_tree_list (NULL_TREE, decl),
                 DECL_FRIENDLIST (typedecl));
   if (!uses_template_parms (type))
     DECL_BEFRIENDING_CLASSES (decl)