* [C++ PATCH] Overload iterators #3
@ 2017-05-16 18:34 Nathan Sidwell
0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2017-05-16 18:34 UTC (permalink / raw)
To: GCC Patches
[-- Attachment #1: Type: text/plain, Size: 639 bytes --]
This patch to do_class_deduction notices that we currently add some
candidates and them immediately elide them from the set. Why not just
not add them?
Adding to the overload set uses a new lookup_add function, which in turn
uses a new ovl_make. A couple of new OVL_foo flags appear, which will
be used more in subsequent patches.
Also, you may notice that nothing currently adds to the ovl_cache of
reuseable overload nodes. That'll be rectified shortly.
(I'll be killing the current ovl_cons and build_overload later. One
reason for the name changing is that it ensures I converted all the uses.)
nathan
--
Nathan Sidwell
[-- Attachment #2: ovl-iter-3.diff --]
[-- Type: text/x-patch, Size: 8521 bytes --]
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.
Index: cp-tree.h
===================================================================
--- cp-tree.h (revision 248120)
+++ cp-tree.h (working copy)
@@ -371,11 +371,13 @@ extern GTY(()) tree cp_global_trees[CPTI
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
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_do
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: pt.c
===================================================================
--- pt.c (revision 248120)
+++ pt.c (working copy)
@@ -25157,9 +25157,29 @@ do_class_deduction (tree ptype, tree tmp
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 tmp
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 tmp
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 tmp
{
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: tree.c
===================================================================
--- tree.c (revision 248120)
+++ tree.c (working copy)
@@ -2094,6 +2094,52 @@ build_ref_qualified_type (tree type, cp_
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
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2017-05-16 18:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-16 18:34 [C++ PATCH] Overload iterators #3 Nathan Sidwell
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).