* 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
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 &
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)
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. */
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);
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 */
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)))
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;
}
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;
{
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");
}
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