From b294103fdfa14692e7c1e05375c2367f24a328e0 Mon Sep 17 00:00:00 2001 From: nathan Date: Wed, 20 Jun 2018 14:34:06 +0000 Subject: [PATCH] [PR c++/85634] Fix tsubst ICE https://gcc.gnu.org/ml/gcc-patches/2018-06/msg01237.html PR c++/85634 * cp-tree.h (lookup_keep): Drop KEEP parm. (lookup_list_keep): Delete. (maybe_get_fns): Declare. * parser.c (cp_parser_primary_expression): Call lookup_keep here. (cp_parser_template_id): Not here ... * decl.c (cp_finish_decl): ... nor here ... * init.c (build_raw_new_expr): ... nor here ... * pt.c (process_template_parm): ... nor here ... * semantics.c (perform_koenig_lookup): Call lookup_keep. (finish_call_expr): Not here. * tree.c (ovl_cache): Delete. (ovl_make, ovl_copy): No cache. (lookup_keep): Always keep. (lookup_list_keep): Delete. (maybe_get_fns): New, broken out of ... (get_fns): ... here. Call it. (built_min_nt_loc, build_min, build_min_non_dep): Drop lookup_keep. (build_min_nt_call_vec): Likewise. PR c++/85634 * g++.dg/lookup/pr85634.C: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@261802 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 22 ++++++ gcc/cp/cp-tree.h | 4 +- gcc/cp/decl.c | 7 +- gcc/cp/init.c | 7 +- gcc/cp/parser.c | 13 ++-- gcc/cp/pt.c | 3 - gcc/cp/semantics.c | 14 ++-- gcc/cp/tree.c | 122 ++++++++++------------------------ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/g++.dg/lookup/pr85634.C | 18 +++++ 10 files changed, 99 insertions(+), 116 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/pr85634.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 430b4352ca9..822a18acc2e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +2018-06-20 Nathan Sidwell + + PR c++/85634 + * cp-tree.h (lookup_keep): Drop KEEP parm. + (lookup_list_keep): Delete. + (maybe_get_fns): Declare. + * parser.c (cp_parser_primary_expression): Call lookup_keep here. + (cp_parser_template_id): Not here ... + * decl.c (cp_finish_decl): ... nor here ... + * init.c (build_raw_new_expr): ... nor here ... + * pt.c (process_template_parm): ... nor here ... + * semantics.c (perform_koenig_lookup): Call lookup_keep. + (finish_call_expr): Not here. + * tree.c (ovl_cache): Delete. + (ovl_make, ovl_copy): No cache. + (lookup_keep): Always keep. + (lookup_list_keep): Delete. + (maybe_get_fns): New, broken out of ... + (get_fns): ... here. Call it. + (built_min_nt_loc, build_min, build_min_non_dep): Drop lookup_keep. + (build_min_nt_call_vec): Likewise. + 2018-06-19 Jason Merrill * cp-tree.h (CONSTRUCTOR_NO_IMPLICIT_ZERO): Remove. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f0aae667723..ee9242f9313 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7094,11 +7094,11 @@ extern void lookup_mark (tree lookup, bool val); extern tree lookup_add (tree fns, tree lookup); extern tree lookup_maybe_add (tree fns, tree lookup, bool deduping); -extern void lookup_keep (tree lookup, bool keep); -extern void lookup_list_keep (tree list, bool keep); +extern void lookup_keep (tree lookup); extern int is_overloaded_fn (tree) ATTRIBUTE_PURE; extern bool really_overloaded_fn (tree) ATTRIBUTE_PURE; extern tree dependent_name (tree); +extern tree maybe_get_fns (tree) ATTRIBUTE_PURE; extern tree get_fns (tree) ATTRIBUTE_PURE; extern tree get_first_fn (tree) ATTRIBUTE_PURE; extern tree ovl_scope (tree); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 90714cce062..f12a01b28f5 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6973,11 +6973,8 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } if (init) - { - if (TREE_CODE (init) == TREE_LIST) - lookup_list_keep (init, true); - DECL_INITIAL (decl) = init; - } + DECL_INITIAL (decl) = init; + if (dep_init) { retrofit_lang_decl (decl); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 57697d67035..810a776a3c8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2403,12 +2403,7 @@ build_raw_new_expr (vec *placement, tree type, tree nelts, else if (init->is_empty ()) init_list = void_node; else - { - init_list = build_tree_list_vec (init); - for (tree v = init_list; v; v = TREE_CHAIN (v)) - if (TREE_CODE (TREE_VALUE (v)) == OVERLOAD) - lookup_keep (TREE_VALUE (v), true); - } + init_list = build_tree_list_vec (init); new_expr = build4 (NEW_EXPR, build_pointer_type (type), build_tree_list_vec (placement), type, nelts, diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index c6206fc353c..b618485ab2b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -5603,6 +5603,14 @@ cp_parser_primary_expression (cp_parser *parser, } } + if (processing_template_decl) + if (tree fns = maybe_get_fns (decl)) + /* It's too difficult to mark ths in all the places where + we know for sure we need to keep the lookup, so do it + now. The cost is extra GC to recycle the lookups + resolved at parse time. */ + lookup_keep (fns); + decl = (finish_id_expression (id_expression, decl, parser->scope, idk, @@ -15989,11 +15997,6 @@ cp_parser_template_id (cp_parser *parser, token->type = CPP_TEMPLATE_ID; token->location = combined_loc; - /* We must mark the lookup as kept, so we don't throw it away on - the first parse. */ - if (is_overloaded_fn (template_id)) - lookup_keep (get_fns (template_id), true); - /* Retrieve any deferred checks. Do not pop this access checks yet so the memory will not be reclaimed during token replacing below. */ token->u.tree_check_value = ggc_cleared_alloc (); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 3386385b3f8..be42b20df76 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -4431,9 +4431,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm, pushdecl (decl); - if (defval && TREE_CODE (defval) == OVERLOAD) - lookup_keep (defval, true); - /* Build the parameter node linking the parameter declaration, its default argument (if any), and its constraints (if any). */ parm = build_tree_list (defval, parm); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 2356940a6bb..38b7b66e214 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2325,6 +2325,11 @@ perform_koenig_lookup (cp_expr fn, vec *args, else fn = identifier; } + else if (TREE_CODE (fn) == OVERLOAD && processing_template_decl) + /* FIXME: We shouldn't really need to mark the lookup here, as + resolving the (non-dependent) call should save the single + function we resolve to. Related to PR c++/83529. */ + lookup_keep (fn); } if (fn && template_id && fn != error_mark_node) @@ -2385,10 +2390,7 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, SET_EXPR_LOCATION (result, cp_expr_loc_or_loc (fn, input_location)); KOENIG_LOOKUP_P (result) = koenig_p; if (is_overloaded_fn (fn)) - { - fn = get_fns (fn); - lookup_keep (fn, true); - } + fn = get_fns (fn); if (cfun) { @@ -2575,10 +2577,6 @@ finish_call_expr (tree fn, vec **args, bool disallow_virtual, result = convert_from_reference (result); } - /* Free or retain OVERLOADs from lookup. */ - if (is_overloaded_fn (orig_fn)) - lookup_keep (get_fns (orig_fn), processing_template_decl); - return result; } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 4e91dbb75da..e7bd79b6276 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2131,25 +2131,12 @@ build_ref_qualified_type (tree type, cp_ref_qualifier rqual) return build_cp_fntype_variant (type, rqual, raises, late); } -/* 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); + tree result = make_node (OVERLOAD); if (TREE_CODE (fn) == OVERLOAD) OVL_NESTED_P (result) = true; @@ -2164,17 +2151,7 @@ ovl_make (tree fn, tree next) static tree ovl_copy (tree ovl) { - 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); + tree result = make_node (OVERLOAD); gcc_checking_assert (!OVL_NESTED_P (ovl) && OVL_USED_P (ovl)); TREE_TYPE (result) = TREE_TYPE (ovl); @@ -2413,44 +2390,22 @@ ovl_used (tree ovl) } } -/* If KEEP is true, preserve the contents of a lookup so that it is - available for a later instantiation. Otherwise release the LOOKUP - nodes for reuse. */ +/* Preserve the contents of a lookup so that it is available for a + later instantiation. */ void -lookup_keep (tree lookup, bool keep) +lookup_keep (tree lookup) { for (; lookup && TREE_CODE (lookup) == OVERLOAD && OVL_LOOKUP_P (lookup) && !OVL_USED_P (lookup); lookup = OVL_CHAIN (lookup)) - if (keep) - { - OVL_USED_P (lookup) = true; - ovl_used (OVL_FUNCTION (lookup)); - } - else - { - OVL_FUNCTION (lookup) = ovl_cache; - ovl_cache = lookup; - } - - if (keep) - ovl_used (lookup); -} - -/* LIST is a TREE_LIST whose TREE_VALUEs may be OVERLOADS that need - keeping, or may be ignored. */ - -void -lookup_list_keep (tree list, bool keep) -{ - for (; list; list = TREE_CHAIN (list)) { - tree v = TREE_VALUE (list); - if (TREE_CODE (v) == OVERLOAD) - lookup_keep (v, keep); + OVL_USED_P (lookup) = true; + ovl_used (OVL_FUNCTION (lookup)); } + + ovl_used (lookup); } /* Returns nonzero if X is an expression for a (possibly overloaded) @@ -2505,10 +2460,11 @@ really_overloaded_fn (tree x) return is_overloaded_fn (x) == 2; } -/* Get the overload set FROM refers to. */ +/* Get the overload set FROM refers to. Returns NULL if it's not an + overload set. */ tree -get_fns (tree from) +maybe_get_fns (tree from) { /* A baselink is also considered an overloaded function. */ if (TREE_CODE (from) == OFFSET_REF @@ -2518,9 +2474,23 @@ get_fns (tree from) from = BASELINK_FUNCTIONS (from); if (TREE_CODE (from) == TEMPLATE_ID_EXPR) from = TREE_OPERAND (from, 0); - gcc_assert (TREE_CODE (from) == OVERLOAD - || TREE_CODE (from) == FUNCTION_DECL); - return from; + + if (TREE_CODE (from) == OVERLOAD + || TREE_CODE (from) == FUNCTION_DECL) + return from; + + return NULL; +} + +/* FROM refers to an overload set. Return that set (or die). */ + +tree +get_fns (tree from) +{ + tree res = maybe_get_fns (from); + + gcc_assert (res); + return res; } /* Return the first function of the overload set FROM refers to. */ @@ -3306,12 +3276,7 @@ build_min_nt_loc (location_t loc, enum tree_code code, ...) length = TREE_CODE_LENGTH (code); for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = x; - if (x && TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + TREE_OPERAND (t, i) = va_arg (p, tree); va_end (p); return t; @@ -3339,21 +3304,12 @@ build_min (enum tree_code code, tree tt, ...) { tree x = va_arg (p, tree); TREE_OPERAND (t, i) = x; - if (x) - { - if (!TYPE_P (x) && TREE_SIDE_EFFECTS (x)) - TREE_SIDE_EFFECTS (t) = 1; - if (TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + if (x && !TYPE_P (x) && TREE_SIDE_EFFECTS (x)) + TREE_SIDE_EFFECTS (t) = 1; } va_end (p); - if (code == CAST_EXPR) - /* The single operand is a TREE_LIST, which we have to check. */ - lookup_list_keep (TREE_OPERAND (t, 0), true); - return t; } @@ -3382,12 +3338,7 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...) TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep); for (i = 0; i < length; i++) - { - tree x = va_arg (p, tree); - TREE_OPERAND (t, i) = x; - if (x && TREE_CODE (x) == OVERLOAD) - lookup_keep (x, true); - } + TREE_OPERAND (t, i) = va_arg (p, tree); if (code == COMPOUND_EXPR && TREE_CODE (non_dep) != COMPOUND_EXPR) /* This should not be considered a COMPOUND_EXPR, because it @@ -3410,11 +3361,8 @@ build_min_nt_call_vec (tree fn, vec *args) CALL_EXPR_FN (ret) = fn; CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE; FOR_EACH_VEC_SAFE_ELT (args, ix, t) - { - CALL_EXPR_ARG (ret, ix) = t; - if (TREE_CODE (t) == OVERLOAD) - lookup_keep (t, true); - } + CALL_EXPR_ARG (ret, ix) = t; + return ret; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a2c5eabd5a6..25a7caaebe4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-06-20 Nathan Sidwell + + PR c++/85634 + * g++.dg/lookup/pr85634.C: New. + 2018-06-20 Kyrylo Tkachov * gcc.target/aarch64/ldp_stp_q.c: New test. diff --git a/gcc/testsuite/g++.dg/lookup/pr85634.C b/gcc/testsuite/g++.dg/lookup/pr85634.C new file mode 100644 index 00000000000..e3b36826993 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/pr85634.C @@ -0,0 +1,18 @@ +// PR c++/85634 ICE managing lookup set + +namespace N { + template void Foo (T *const &); +} + +using namespace N; + +template void Foo (const T &); + + +template +void Frob() +{ + void (*op)(const T&) = Foo; +} + +template void Frob(); -- 2.11.4.GIT