From: Nathan Sidwell Date: Tue, 16 May 2017 18:29:36 +0000 (+0000) Subject: cp-tree.h (OVL_NESTED_P, [...]): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e09ae85766973a7b5ad9f9502a8cfa0180040d4f;p=gcc.git cp-tree.h (OVL_NESTED_P, [...]): New. * 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4d508ec09dc..5d336127cdb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,7 +1,16 @@ 2017-05-16 Nathan Sidwell + * 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 & diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b81e94ddf9a..739ff184abb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 5fc47abf46f..242b78c42aa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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"); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 83dd7a3f2a7..edc01208746 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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" will all be considered possibly