From 2e12a8554c9ed35fd6aa786c1ef5eee96bf8a6b6 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 24 Aug 2017 18:39:41 +0000 Subject: [PATCH] Conversion operators kept on single overload set Conversion operators kept on single overload set * class.c (add_method): Keep all conv-ops on one slot. * name-lookup.c (lookup_conversion_operator): Pull the desired conv op out of overload set. * search.c (lookup_conversions_r): Lose template/non-template distinction. (lookup_conversions): Likewise. From-SVN: r251340 --- gcc/cp/ChangeLog | 10 ++++ gcc/cp/class.c | 38 ++++--------- gcc/cp/name-lookup.c | 33 ++++++------ gcc/cp/search.c | 149 ++++++++++++++------------------------------------- 4 files changed, 77 insertions(+), 153 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5d2a3c6..92ecf91 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-08-24 Nathan Sidwell + + Conversion operators kept on single overload set + * class.c (add_method): Keep all conv-ops on one slot. + * name-lookup.c (lookup_conversion_operator): Pull the desired + conv op out of overload set. + * search.c (lookup_conversions_r): Lose template/non-template + distinction. + (lookup_conversions): Likewise. + 2017-08-23 Nathan Sidwell * cp-tree.h (lookup_field_1, lookup_fnfields_slot, diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 78a9b5f..a08ce89 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -1014,30 +1014,16 @@ modify_vtable_entry (tree t, bool add_method (tree type, tree method, bool via_using) { - unsigned slot; - bool template_conv_p = false; - bool conv_p; - vec *method_vec; - bool complete_p; - bool insert_p = false; - tree current_fns; - if (method == error_mark_node) return false; - complete_p = COMPLETE_TYPE_P (type); - conv_p = DECL_CONV_FN_P (method); - if (conv_p) - template_conv_p = (TREE_CODE (method) == TEMPLATE_DECL - && DECL_TEMPLATE_CONV_FN_P (method)); + bool complete_p = COMPLETE_TYPE_P (type); + bool conv_p = DECL_CONV_FN_P (method); - method_vec = CLASSTYPE_METHOD_VEC (type); + vec *method_vec = CLASSTYPE_METHOD_VEC (type); if (!method_vec) { - /* Make a new method vector. We start with 8 entries. We must - allocate at least two (for constructors and destructors), and - we're going to end up with an assignment operator at some - point as well. */ + /* Make a new method vector. We start with 8 entries. */ vec_alloc (method_vec, 8); CLASSTYPE_METHOD_VEC (type) = method_vec; } @@ -1045,24 +1031,22 @@ add_method (tree type, tree method, bool via_using) /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ grok_special_member_properties (method); + bool insert_p = true; + unsigned slot; tree m; - insert_p = true; /* See if we already have an entry with this name. */ for (slot = CLASSTYPE_FIRST_CONVERSION_SLOT; vec_safe_iterate (method_vec, slot, &m); ++slot) { m = OVL_FIRST (m); - if (template_conv_p) + if (conv_p) { - if (TREE_CODE (m) == TEMPLATE_DECL - && DECL_TEMPLATE_CONV_FN_P (m)) + if (DECL_CONV_FN_P (m)) insert_p = false; break; } - if (conv_p && !DECL_CONV_FN_P (m)) - break; if (DECL_NAME (m) == DECL_NAME (method)) { insert_p = false; @@ -1073,7 +1057,8 @@ add_method (tree type, tree method, bool via_using) && DECL_NAME (m) > DECL_NAME (method)) break; } - current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; + tree current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; + gcc_assert (!DECL_EXTERN_C_P (method)); /* Check to see if we've already got this method. */ for (ovl_iterator iter (current_fns); iter; ++iter) @@ -1216,8 +1201,7 @@ add_method (tree type, tree method, bool via_using) } /* A class should never have more than one destructor. */ - if (current_fns && DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (method)) - return false; + gcc_assert (!current_fns || !DECL_DESTRUCTOR_P (method)); current_fns = ovl_insert (method, current_fns, via_using); diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 12c507e..3d69e1d 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -1096,34 +1096,31 @@ lookup_arg_dependent (tree name, tree fns, vec *args) static tree lookup_conversion_operator (tree class_type, tree type) { - tree tpls = NULL_TREE; + tree convs = NULL_TREE; if (TYPE_HAS_CONVERSION (class_type)) { - tree fns; + tree fns = NULL_TREE; + tree tpls = NULL_TREE; vec *methods = CLASSTYPE_METHOD_VEC (class_type); - for (int i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (methods, i, &fns); ++i) + vec_safe_iterate (methods, CLASSTYPE_FIRST_CONVERSION_SLOT, &fns); + if (fns && !DECL_CONV_FN_P (OVL_FIRST (fns))) + fns = NULL_TREE; + for (ovl_iterator iter (fns); iter; ++iter) { - /* All the conversion operators come near the beginning of - the class. Therefore, if FN is not a conversion - operator, there is no matching conversion operator in - CLASS_TYPE. */ - tree fn = OVL_FIRST (fns); - if (!DECL_CONV_FN_P (fn)) - break; + if (same_type_p (DECL_CONV_FN_TYPE (*iter), type)) + convs = lookup_add (*iter, convs); - if (TREE_CODE (fn) == TEMPLATE_DECL) - /* All the templated conversion functions are on the same - slot, so remember it. */ - tpls = fns; - else if (same_type_p (DECL_CONV_FN_TYPE (fn), type)) - return fns; + if (TREE_CODE (*iter) == TEMPLATE_DECL) + tpls = lookup_add (*iter, tpls); } + + if (!convs) + convs = tpls; } - return tpls; + return convs; } /* TYPE is a class type. Return the member functions in the method diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 9e15b02..31f4dd6 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -38,8 +38,7 @@ static tree dfs_dcast_hint_post (tree, void *); static tree dfs_debug_mark (tree, void *); static int check_hidden_convs (tree, int, int, tree, tree, tree); static tree split_conversions (tree, tree, tree, tree); -static int lookup_conversions_r (tree, int, int, - tree, tree, tree, tree, tree *, tree *); +static int lookup_conversions_r (tree, int, int, tree, tree, tree *); static int look_for_overrides_r (tree, tree); static tree lookup_field_r (tree, void *); static tree dfs_accessible_post (tree, void *); @@ -2333,14 +2332,13 @@ split_conversions (tree my_convs, tree parent_convs, } /* Worker for lookup_conversions. Lookup conversion functions in - BINFO and its children. VIRTUAL_DEPTH is nonzero, if BINFO is in - a morally virtual base, and VIRTUALNESS is nonzero, if we've - encountered virtual bases already in the tree walk. PARENT_CONVS & - PARENT_TPL_CONVS are lists of list of conversions within parent - binfos. OTHER_CONVS and OTHER_TPL_CONVS are conversions found - elsewhere in the tree. Return the conversions found within this - portion of the graph in CONVS and TPL_CONVS. Return nonzero is we - encountered virtualness. We keep template and non-template + BINFO and its children. VIRTUAL_DEPTH is nonzero, if BINFO is in a + morally virtual base, and VIRTUALNESS is nonzero, if we've + encountered virtual bases already in the tree walk. PARENT_CONVS + is a list of conversions within parent binfos. OTHER_CONVS are + conversions found elsewhere in the tree. Return the conversions + found within this portion of the graph in CONVS. Return nonzero if + we encountered virtualness. We keep template and non-template conversions separate, to avoid unnecessary type comparisons. The located conversion functions are held in lists of lists. The @@ -2353,26 +2351,17 @@ split_conversions (tree my_convs, tree parent_convs, is the converted-to type. */ static int -lookup_conversions_r (tree binfo, - int virtual_depth, int virtualness, - tree parent_convs, tree parent_tpl_convs, - tree other_convs, tree other_tpl_convs, - tree *convs, tree *tpl_convs) +lookup_conversions_r (tree binfo, int virtual_depth, int virtualness, + tree parent_convs, tree other_convs, tree *convs) { int my_virtualness = 0; tree my_convs = NULL_TREE; - tree my_tpl_convs = NULL_TREE; tree child_convs = NULL_TREE; - tree child_tpl_convs = NULL_TREE; - unsigned i; - tree base_binfo; - vec *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo)); - tree conv; /* If we have no conversion operators, then don't look. */ if (!TYPE_HAS_CONVERSION (BINFO_TYPE (binfo))) { - *convs = *tpl_convs = NULL_TREE; + *convs = NULL_TREE; return 0; } @@ -2381,60 +2370,32 @@ lookup_conversions_r (tree binfo, virtual_depth++; /* First, locate the unhidden ones at this level. */ - for (i = CLASSTYPE_FIRST_CONVERSION_SLOT; - vec_safe_iterate (method_vec, i, &conv); - ++i) - { - tree cur = OVL_FIRST (conv); - - if (!DECL_CONV_FN_P (cur)) - break; + vec *method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo)); + tree conv = NULL_TREE; + vec_safe_iterate (method_vec, CLASSTYPE_FIRST_CONVERSION_SLOT, &conv); + if (conv && !DECL_CONV_FN_P (OVL_FIRST (conv))) + conv = NULL_TREE; - if (TREE_CODE (cur) == TEMPLATE_DECL) - /* Only template conversions can be overloaded, and we must - flatten them out and check each one individually. */ - for (ovl_iterator iter (conv); iter; ++iter) - { - tree tpl = *iter; - tree type = DECL_CONV_FN_TYPE (tpl); + for (ovl_iterator iter (conv); iter; ++iter) + { + tree fn = *iter; + tree type = DECL_CONV_FN_TYPE (fn); - if (check_hidden_convs (binfo, virtual_depth, virtualness, - type, parent_tpl_convs, other_tpl_convs)) - { - my_tpl_convs = tree_cons (binfo, tpl, my_tpl_convs); - TREE_TYPE (my_tpl_convs) = type; - if (virtual_depth) - { - TREE_STATIC (my_tpl_convs) = 1; - my_virtualness = 1; - } - } - } - else + if (TREE_CODE (fn) != TEMPLATE_DECL && type_uses_auto (type)) { - tree name = DECL_NAME (cur); + mark_used (fn); + type = DECL_CONV_FN_TYPE (fn); + } - if (!IDENTIFIER_MARKED (name)) + if (check_hidden_convs (binfo, virtual_depth, virtualness, + type, parent_convs, other_convs)) + { + my_convs = tree_cons (binfo, fn, my_convs); + TREE_TYPE (my_convs) = type; + if (virtual_depth) { - tree type = DECL_CONV_FN_TYPE (cur); - if (type_uses_auto (type)) - { - mark_used (cur); - type = DECL_CONV_FN_TYPE (cur); - } - - if (check_hidden_convs (binfo, virtual_depth, virtualness, - type, parent_convs, other_convs)) - { - my_convs = tree_cons (binfo, conv, my_convs); - TREE_TYPE (my_convs) = type; - if (virtual_depth) - { - TREE_STATIC (my_convs) = 1; - my_virtualness = 1; - } - IDENTIFIER_MARKED (name) = 1; - } + TREE_STATIC (my_convs) = 1; + my_virtualness = 1; } } } @@ -2446,41 +2407,27 @@ lookup_conversions_r (tree binfo, TREE_STATIC (parent_convs) = 1; } - if (my_tpl_convs) - { - parent_tpl_convs = tree_cons (binfo, my_tpl_convs, parent_tpl_convs); - if (virtual_depth) - TREE_STATIC (parent_tpl_convs) = 1; - } - child_convs = other_convs; - child_tpl_convs = other_tpl_convs; /* Now iterate over each base, looking for more conversions. */ + unsigned i; + tree base_binfo; for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) { - tree base_convs, base_tpl_convs; + tree base_convs; unsigned base_virtualness; base_virtualness = lookup_conversions_r (base_binfo, virtual_depth, virtualness, - parent_convs, parent_tpl_convs, - child_convs, child_tpl_convs, - &base_convs, &base_tpl_convs); + parent_convs, child_convs, + &base_convs); if (base_virtualness) my_virtualness = virtualness = 1; child_convs = chainon (base_convs, child_convs); - child_tpl_convs = chainon (base_tpl_convs, child_tpl_convs); } - /* Unmark the conversions found at this level */ - for (conv = my_convs; conv; conv = TREE_CHAIN (conv)) - IDENTIFIER_MARKED (OVL_NAME (TREE_VALUE (conv))) = 0; - *convs = split_conversions (my_convs, parent_convs, child_convs, other_convs); - *tpl_convs = split_conversions (my_tpl_convs, parent_tpl_convs, - child_tpl_convs, other_tpl_convs); return my_virtualness; } @@ -2497,17 +2444,16 @@ lookup_conversions_r (tree binfo, tree lookup_conversions (tree type) { - tree convs, tpl_convs; - tree list = NULL_TREE; + tree convs; complete_type (type); if (!CLASS_TYPE_P (type) || !TYPE_BINFO (type)) return NULL_TREE; - lookup_conversions_r (TYPE_BINFO (type), 0, 0, - NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE, - &convs, &tpl_convs); + lookup_conversions_r (TYPE_BINFO (type), 0, 0, NULL_TREE, NULL_TREE, &convs); + tree list = NULL_TREE; + /* Flatten the list-of-lists */ for (; convs; convs = TREE_CHAIN (convs)) { @@ -2522,19 +2468,6 @@ lookup_conversions (tree type) } } - for (; tpl_convs; tpl_convs = TREE_CHAIN (tpl_convs)) - { - tree probe, next; - - for (probe = TREE_VALUE (tpl_convs); probe; probe = next) - { - next = TREE_CHAIN (probe); - - TREE_CHAIN (probe) = list; - list = probe; - } - } - return list; } -- 2.7.4