cp-tree.h (OVL_NESTED_P, [...]): New.
authorNathan Sidwell <nathan@acm.org>
Tue, 16 May 2017 18:29:36 +0000 (18:29 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 16 May 2017 18:29:36 +0000 (18:29 +0000)
* cp-tree.h (OVL_NESTED_P, OVL_LOOKUP_P): New.
(ovl_first): Move inline definition to end of file.
(ovl_make, lookup_add): Declare.
(get_fns, get_first_fn): Make pure.
* tree.c (ovl_cache): New.
(ovl_make, lookup_add): New.
* pt.c (do_class_deduction): Don't add candidates that will be
elided.

From-SVN: r248121

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/cp/tree.c

index 4d508ec09dc1f6941c0e62b815e21d8d1b65ac33..5d336127cdbc6f1ec1fc92bb5f174bf4fc864546 100644 (file)
@@ -1,7 +1,16 @@
 2017-05-16  Nathan Sidwell  <nathan@acm.org>
 
+       * cp-tree.h (OVL_NESTED_P, OVL_LOOKUP_P): New.
+       (ovl_first): Move inline definition to end of file.
+       (ovl_make, lookup_add): Declare.
+       (get_fns, get_first_fn): Make pure.
+       * tree.c (ovl_cache): New.
+       (ovl_make, lookup_add): New.
+       * pt.c (do_class_deduction): Don't add candidates that will be
+       elided.
+
        * call.c (build_user_type_conversion_1): Use OVL_FIRST.
-       (print_error_for_call_faulure): Use OVL_NAME.
+       (print_error_for_call_failure): Use OVL_NAME.
        (build_op_call_1): Use ovl_iterator.
        (add_candidates): Use OVL_FIRST & lkp_iterator.
        (build_op_delete_call): Use MAYBE_BASELINK_FUNCTIONS &
index b81e94ddf9acdac10ef1ba87bf30672382a0ee55..739ff184abb3e98b64f8b2a24cc85f691d071e3b 100644 (file)
@@ -371,11 +371,13 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
       CALL_EXPR_ORDERED_ARGS (in CALL_EXPR, AGGR_INIT_EXPR)
       DECLTYPE_FOR_REF_CAPTURE (in DECLTYPE_TYPE)
       CONSTUCTOR_C99_COMPOUND_LITERAL (in CONSTRUCTOR)
+      OVL_NESTED_P (in OVERLOAD)
    4: TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
          CALL_EXPR, or FIELD_DECL).
       IDENTIFIER_TYPENAME_P (in IDENTIFIER_NODE)
       DECL_TINFO_P (in VAR_DECL)
       FUNCTION_REF_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
+      OVL_LOOKUP_P (in OVERLOAD)
    5: C_IS_RESERVED_WORD (in IDENTIFIER_NODE)
       DECL_VTABLE_OR_VTT_P (in VAR_DECL)
       FUNCTION_RVALUE_QUALIFIED (in FUNCTION_TYPE, METHOD_TYPE)
@@ -626,6 +628,11 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
    and can be freed afterward.  */
 #define OVL_ARG_DEPENDENT(NODE) TREE_LANG_FLAG_0 (OVERLOAD_CHECK (NODE))
 
+/* If set, this overload contains a nested overload.  */
+#define OVL_NESTED_P(NODE)     TREE_LANG_FLAG_3 (OVERLOAD_CHECK (NODE))
+/* If set, this overload was constructed during lookup.  */
+#define OVL_LOOKUP_P(NODE)     TREE_LANG_FLAG_4 (OVERLOAD_CHECK (NODE))
+
 /* The first decl of an overload.  */
 #define OVL_FIRST(NODE)        ovl_first (NODE)
 /* The name of the overload set.  */
@@ -6733,17 +6740,14 @@ extern tree hash_tree_cons                      (tree, tree, tree);
 extern tree hash_tree_chain                    (tree, tree);
 extern tree build_qualified_name               (tree, tree, tree, bool);
 extern tree build_ref_qualified_type           (tree, cp_ref_qualifier);
-inline tree
-ovl_first (tree node)
-{
-  while (TREE_CODE (node) == OVERLOAD)
-    node = OVL_FUNCTION (node);
-  return node;
-}
+inline tree ovl_first                          (tree) ATTRIBUTE_PURE;
+extern tree ovl_make                           (tree fn,
+                                                tree next = NULL_TREE);
+extern tree lookup_add                         (tree lookup, tree ovl);
 extern int is_overloaded_fn                    (tree);
 extern tree dependent_name                     (tree);
-extern tree get_fns                            (tree);
-extern tree get_first_fn                       (tree);
+extern tree get_fns                            (tree) ATTRIBUTE_PURE;
+extern tree get_first_fn                       (tree) ATTRIBUTE_PURE;
 extern tree ovl_cons                           (tree, tree);
 extern tree build_overload                     (tree, tree);
 extern tree ovl_scope                          (tree);
@@ -7188,6 +7192,16 @@ extern tree cp_ubsan_maybe_instrument_downcast   (location_t, tree, tree, tree);
 extern tree cp_ubsan_maybe_instrument_cast_to_vbase (location_t, tree, tree);
 extern void cp_ubsan_maybe_initialize_vtbl_ptrs (tree);
 
+/* Inline bodies.  */
+
+inline tree
+ovl_first (tree node)
+{
+  while (TREE_CODE (node) == OVERLOAD)
+    node = OVL_FUNCTION (node);
+  return node;
+}
+
 /* -- end of C++ */
 
 #endif /* ! GCC_CP_TREE_H */
index 5fc47abf46f0bca6f37215120b6a9785f5c9bbcb..242b78c42aaf9d953dca0aa718848d2df5c1a326 100644 (file)
@@ -25157,9 +25157,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
   tree cands = lookup_qualified_name (CP_DECL_CONTEXT (tmpl), dname,
                                      /*type*/false, /*complain*/false,
                                      /*hidden*/false);
+  bool elided = false;
   if (cands == error_mark_node)
     cands = NULL_TREE;
 
+  /* Prune explicit deduction guides in copy-initialization context.  */
+  if (flags & LOOKUP_ONLYCONVERTING)
+    {
+      for (lkp_iterator iter (cands); !elided && iter; ++iter)
+       if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
+         elided = true;
+
+      if (elided)
+       {
+         /* Found a nonconverting guide, prune the candidates.  */
+         tree pruned = NULL_TREE;
+         for (lkp_iterator iter (cands); iter; ++iter)
+           if (!DECL_NONCONVERTING_P (STRIP_TEMPLATE (*iter)))
+             pruned = lookup_add (pruned, *iter);
+
+         cands = pruned;
+       }
+    }
+
   tree outer_args = NULL_TREE;
   if (DECL_CLASS_SCOPE_P (tmpl)
       && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (tmpl)))
@@ -25171,11 +25191,15 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
   bool saw_ctor = false;
   if (CLASSTYPE_METHOD_VEC (type))
     // FIXME cache artificial deduction guides
-    for (tree fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
+    for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type));
+        iter; ++iter)
       {
-       tree fn = OVL_CURRENT (fns);
-       tree guide = build_deduction_guide (fn, outer_args, complain);
-       cands = ovl_cons (guide, cands);
+       tree guide = build_deduction_guide (*iter, outer_args, complain);
+       if ((flags & LOOKUP_ONLYCONVERTING)
+           && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
+         elided = true;
+       else
+         cands = lookup_add (cands, guide);
 
        saw_ctor = true;
       }
@@ -25183,41 +25207,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
   if (!saw_ctor && args->length() == 0)
     {
       tree guide = build_deduction_guide (type, outer_args, complain);
-      cands = ovl_cons (guide, cands);
+      if ((flags & LOOKUP_ONLYCONVERTING)
+         && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
+       elided = true;
+      else
+       cands = lookup_add (cands, guide);
     }
   if (args->length() == 1)
     {
       tree guide = build_deduction_guide (build_reference_type (type),
                                          outer_args, complain);
-      cands = ovl_cons (guide, cands);
+      if ((flags & LOOKUP_ONLYCONVERTING)
+         && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
+       elided = true;
+      else
+       cands = lookup_add (cands, guide);
     }
 
-  /* Prune explicit deduction guides in copy-initialization context.  */
-  tree old_cands = cands;
-  if (flags & LOOKUP_ONLYCONVERTING)
+  if (elided && !cands)
     {
-      tree t = cands;
-      for (; t; t = OVL_NEXT (t))
-       if (DECL_NONCONVERTING_P (STRIP_TEMPLATE (OVL_CURRENT (t))))
-         break;
-      if (t)
-       {
-         tree pruned = NULL_TREE;
-         for (t = cands; t; t = OVL_NEXT (t))
-           {
-             tree f = OVL_CURRENT (t);
-             if (!DECL_NONCONVERTING_P (STRIP_TEMPLATE (f)))
-               pruned = build_overload (f, pruned);
-           }
-         cands = pruned;
-         if (cands == NULL_TREE)
-           {
-             error ("cannot deduce template arguments for copy-initialization"
-                    " of %qT, as it has no non-explicit deduction guides or "
-                    "user-declared constructors", type);
-             return error_mark_node;
-           }
-       }
+      error ("cannot deduce template arguments for copy-initialization"
+            " of %qT, as it has no non-explicit deduction guides or "
+            "user-declared constructors", type);
+      return error_mark_node;
     }
 
   ++cp_unevaluated_operand;
@@ -25227,7 +25239,7 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
     {
       error ("class template argument deduction failed:");
       t = build_new_function_call (cands, &args, complain | tf_decltype);
-      if (old_cands != cands)
+      if (elided)
        inform (input_location, "explicit deduction guides not considered "
                "for copy-initialization");
     }
index 83dd7a3f2a7f11f441b704fb2ea533f70babeaf3..edc012087462e8bce134daa7e8222fea07eefba9 100644 (file)
@@ -2094,6 +2094,52 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual)
   return t;
 }
 
+/* Cache of free ovl nodes.  Uses OVL_FUNCTION for chaining.  */
+static GTY((deletable)) tree ovl_cache;
+
+/* Make a raw overload node containing FN.  */
+
+tree
+ovl_make (tree fn, tree next)
+{
+  tree result = ovl_cache;
+
+  if (result)
+    {
+      ovl_cache = OVL_FUNCTION (result);
+      /* Zap the flags.  */
+      memset (result, 0, sizeof (tree_base));
+      TREE_SET_CODE (result, OVERLOAD);
+    }
+  else
+    result = make_node (OVERLOAD);
+
+  if (TREE_CODE (fn) == OVERLOAD)
+    OVL_NESTED_P (result) = true;
+
+  TREE_TYPE (result) = (next || TREE_CODE (fn) == TEMPLATE_DECL
+                       ? unknown_type_node : TREE_TYPE (fn));
+  OVL_FUNCTION (result) = fn;
+  OVL_CHAIN (result) = next;
+  return result;
+}
+
+/* Add a potential overload into a lookup set.  */
+
+tree
+lookup_add (tree lookup, tree ovl)
+{
+  if (lookup || TREE_CODE (ovl) == TEMPLATE_DECL)
+    {
+      lookup = ovl_make (ovl, lookup);
+      OVL_LOOKUP_P (lookup) = true;
+    }
+  else
+    lookup = ovl;
+
+  return lookup;
+}
+
 /* Returns nonzero if X is an expression for a (possibly overloaded)
    function.  If "f" is a function or function template, "f", "c->f",
    "c.f", "C::f", and "f<int>" will all be considered possibly