From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6076 invoked by alias); 5 Sep 2017 20:17:19 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 6061 invoked by uid 89); 5 Sep 2017 20:17:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.6 required=5.0 tests=BAYES_00,FREEMAIL_FROM,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,RCVD_IN_SORBS_SPAM,SPF_PASS autolearn=ham version=3.3.2 spammy=H*MI:1b5a, H*M:1b5a X-HELO: mail-yw0-f172.google.com Received: from mail-yw0-f172.google.com (HELO mail-yw0-f172.google.com) (209.85.161.172) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 05 Sep 2017 20:17:12 +0000 Received: by mail-yw0-f172.google.com with SMTP id x144so16355961ywg.2 for ; Tue, 05 Sep 2017 13:17:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=2p2ER5E7OFGL5sF047+ZwzMyrRXtnUHHsP78XSyQ9Ps=; b=rP1zFOpeHp9ZGRmaJ3/snR3nGYaujTkCixhqf9itIw8sdij1Zv5tc87OK0BtiriyLQ qAvVhfHxKQd1FpJ6BYouWz9wrIjyWmwg0tMQN9GgmH7cdI3gM/nHniwoy3dQJgCPESUm ICeG7I3GKvx2fQ0j67xQQmuFu5QRp5bnqCgOhiL6/O+9+0+GwItto2L8o/0K+jiKHKh6 HfjnnQhCM6wbmhVVri7OOxvr8E5XiHNrQ54l0ZmFE1Ogv8IHc1G7YOpX4tlM+gTd8sDu 0h2NaUHw4NuzoPKES0cggXUFu9bwDv+GHG0M0AVLrUZbOcQXg0YiCDONrKjM1WxW3rzN ycqA== X-Gm-Message-State: AHPjjUhcj9tz7qk0o+EJIHA4FtdkonYLzZ5sLRmrzP6GPaj8lUY824wb cRJk2kBNP6bkcg== X-Google-Smtp-Source: ADKCNb4ToAp4/CWqEnRtQVdousRtitw+7keyYchGBzJdioWrGLdNKFO+blt1+QZNqxCiCFk+4QHaog== X-Received: by 10.129.49.75 with SMTP id x72mr235135ywx.298.1504642630642; Tue, 05 Sep 2017 13:17:10 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a3:20fb:7500:e7fb:4a6f:2254? ([2620:10d:c091:200::16fd]) by smtp.googlemail.com with ESMTPSA id d5sm497906ywc.35.2017.09.05.13.17.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 05 Sep 2017 13:17:10 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] more conversion operator changes Message-ID: <6ddc1630-1b5a-56c4-7682-9fffc4505b58@acm.org> Date: Tue, 05 Sep 2017 20:17:00 -0000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------B59F7905CE5DEB98BAD5EA8A" X-SW-Source: 2017-09/txt/msg00300.txt.bz2 This is a multi-part message in MIME format. --------------B59F7905CE5DEB98BAD5EA8A Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 722 This patch moves add_method's management of METHOD_VEC into a new function in name-lookup.c. That function will create a slot, if there isn't one with the requested name -- we know in that case that add_method will succeed in adding the new method. The one quirk is the IDENTIFIER_BINDING machinery, which will perform a lookup in that case, so we have to protect lookup_fnfields_nolazy. I moved the TYPE_HAS_CONVERSION setting into grok_special_member_properties, as that seemed a more appropriate location. Finally I gave the conversion-operator marker function a FUNCTION_TYPE. that stops the tree_dumping machinery from barfing, which is annoying inside GDB. Applied to trunk. nathan -- Nathan Sidwell --------------B59F7905CE5DEB98BAD5EA8A Content-Type: text/x-patch; name="conv-op-2.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="conv-op-2.diff" Content-length: 9257 2017-09-05 Nathan Sidwell * class.c (add_method): Move slot search and insertion to ... * name-lookup.c (get_method_slot): ... this new function. (lookup_fnfields_slot_nolazy): Cope with NULL slot. * name-lookup.h (get_method_slot): Declare. * decl.c (cxx_init_decl_processinng): Give conv_op_marker a more realistic type. (grok_special_member_properties): Set TYPE_HAS_CONVERSION. Expicitly look at DECL_NAME for specialness. Improve TYPE_HAS_CONSTEXPR_CTOR setting. Index: class.c =================================================================== --- class.c (revision 251724) +++ class.c (working copy) @@ -1011,57 +1011,12 @@ add_method (tree type, tree method, bool if (method == error_mark_node) return false; - vec *method_vec = CLASSTYPE_METHOD_VEC (type); - if (!method_vec) - { - /* Make a new method vector. We start with 8 entries. */ - vec_alloc (method_vec, 8); - CLASSTYPE_METHOD_VEC (type) = method_vec; - } - /* Maintain TYPE_HAS_USER_CONSTRUCTOR, etc. */ grok_special_member_properties (method); - bool insert_p = true; - tree method_name = DECL_NAME (method); - bool complete_p = COMPLETE_TYPE_P (type); - bool conv_p = IDENTIFIER_CONV_OP_P (method_name); - - if (conv_p) - method_name = conv_op_identifier; - - /* See if we already have an entry with this name. */ - unsigned slot; - tree m; - for (slot = 0; vec_safe_iterate (method_vec, slot, &m); ++slot) - { - m = DECL_NAME (OVL_FIRST (m)); - if (m == method_name) - { - insert_p = false; - break; - } - if (complete_p && m > method_name) - break; - } - tree current_fns = insert_p ? NULL_TREE : (*method_vec)[slot]; + tree *slot = get_method_slot (type, DECL_NAME (method)); + tree current_fns = *slot; - tree conv_marker = NULL_TREE; - if (conv_p) - { - /* For conversion operators, we prepend a dummy overload - pointing at conv_op_marker. That function's DECL_NAME is - conv_op_identifier, so we can use identifier equality to - locate it. */ - if (current_fns) - { - gcc_checking_assert (OVL_FUNCTION (current_fns) == conv_op_marker); - conv_marker = current_fns; - current_fns = OVL_CHAIN (current_fns); - } - else - conv_marker = ovl_make (conv_op_marker, NULL_TREE); - } gcc_assert (!DECL_EXTERN_C_P (method)); /* Check to see if we've already got this method. */ @@ -1209,36 +1164,11 @@ add_method (tree type, tree method, bool current_fns = ovl_insert (method, current_fns, via_using); - if (conv_p) - { - TYPE_HAS_CONVERSION (type) = 1; - /* Prepend the marker function. */ - OVL_CHAIN (conv_marker) = current_fns; - current_fns = conv_marker; - } - else if (!complete_p && !IDENTIFIER_CDTOR_P (DECL_NAME (method))) + if (!DECL_CONV_FN_P (method) && !COMPLETE_TYPE_P (type)) push_class_level_binding (DECL_NAME (method), current_fns); - if (insert_p) - { - bool reallocated; + *slot = current_fns; - /* We only expect to add few methods in the COMPLETE_P case, so - just make room for one more method in that case. */ - if (complete_p) - reallocated = vec_safe_reserve_exact (method_vec, 1); - else - reallocated = vec_safe_reserve (method_vec, 1); - if (reallocated) - CLASSTYPE_METHOD_VEC (type) = method_vec; - if (slot == method_vec->length ()) - method_vec->quick_push (current_fns); - else - method_vec->quick_insert (slot, current_fns); - } - else - /* Replace the current slot. */ - (*method_vec)[slot] = current_fns; return true; } Index: decl.c =================================================================== --- decl.c (revision 251722) +++ decl.c (working copy) @@ -4073,13 +4073,6 @@ cxx_init_decl_processing (void) noexcept_deferred_spec = build_tree_list (make_node (DEFERRED_NOEXCEPT), NULL_TREE); - /* Create the conversion operator marker. This operator's DECL_NAME - is in the identifier table, so we can use identifier equality to - find it. This has no type and no context, so we can't - accidentally think it a real function. */ - conv_op_marker = build_lang_decl (FUNCTION_DECL, conv_op_identifier, - NULL_TREE); - #if 0 record_builtin_type (RID_MAX, NULL, string_type_node); #endif @@ -4094,6 +4087,12 @@ cxx_init_decl_processing (void) void_ftype_ptr = build_exception_variant (void_ftype_ptr, empty_except_spec); + /* Create the conversion operator marker. This operator's DECL_NAME + is in the identifier table, so we can use identifier equality to + find it. */ + conv_op_marker = build_lang_decl (FUNCTION_DECL, conv_op_identifier, + void_ftype); + /* C++ extensions */ unknown_type_node = make_node (LANG_TYPE); @@ -12793,7 +12792,7 @@ grok_special_member_properties (tree dec return; class_type = DECL_CONTEXT (decl); - if (DECL_CONSTRUCTOR_P (decl)) + if (IDENTIFIER_CTOR_P (DECL_NAME (decl))) { int ctor = copy_fn_p (decl); @@ -12823,10 +12822,10 @@ grok_special_member_properties (tree dec TYPE_HAS_LIST_CTOR (class_type) = 1; if (DECL_DECLARED_CONSTEXPR_P (decl) - && !copy_fn_p (decl) && !move_fn_p (decl)) + && !ctor && !move_fn_p (decl)) TYPE_HAS_CONSTEXPR_CTOR (class_type) = 1; } - else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR) + else if (DECL_NAME (decl) == cp_assignment_operator_id (NOP_EXPR)) { /* [class.copy] @@ -12847,6 +12846,9 @@ grok_special_member_properties (tree dec else if (move_fn_p (decl) && user_provided_p (decl)) TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1; } + else if (IDENTIFIER_CONV_OP_P (DECL_NAME (decl))) + TYPE_HAS_CONVERSION (class_type) = true; + /* Destructors are handled in check_methods. */ } Index: name-lookup.c =================================================================== --- name-lookup.c (revision 251722) +++ name-lookup.c (working copy) @@ -1155,13 +1155,18 @@ lookup_fnfields_slot_nolazy (tree type, } else for (int i = 0; vec_safe_iterate (method_vec, i, &fns); ++i) - { - if (OVL_NAME (fns) == lookup) - { - val = fns; - break; - } - } + /* We can get a NULL binding during insertion of a new + method name, because the identifier_binding machinery + performs a lookup. If we find such a NULL slot, that's + the thing we were looking for, so we might as well bail + out immediately. */ + if (!fns) + break; + else if (OVL_NAME (fns) == lookup) + { + val = fns; + break; + } /* Extract the conversion operators asked for, unless the general conversion operator was requested. */ @@ -1312,6 +1317,74 @@ lookup_fnfields_slot (tree type, tree na return lookup_fnfields_slot_nolazy (type, name); } +/* Find the slot containing overloads called 'NAME'. If there is no + such slot, create an empty one. KLASS might be complete at this + point, in which case we need to preserve ordering. Deals with + conv_op marker handling. */ + +tree * +get_method_slot (tree klass, tree name) +{ + bool complete_p = COMPLETE_TYPE_P (klass); + + vec *method_vec = CLASSTYPE_METHOD_VEC (klass); + if (!method_vec) + { + vec_alloc (method_vec, 8); + CLASSTYPE_METHOD_VEC (klass) = method_vec; + } + + if (IDENTIFIER_CONV_OP_P (name)) + name = conv_op_identifier; + + unsigned ix, length = method_vec->length (); + for (ix = 0; ix < length; ix++) + { + tree *slot = &(*method_vec)[ix]; + tree fn_name = OVL_NAME (*slot); + + if (fn_name == name) + { + if (name == conv_op_identifier) + { + gcc_checking_assert (OVL_FUNCTION (*slot) == conv_op_marker); + /* Skip the conv-op marker. */ + slot = &OVL_CHAIN (*slot); + } + return slot; + } + + if (complete_p && fn_name > name) + break; + } + + /* No slot found. Create one at IX. We know in this case that our + caller will succeed in adding the function. */ + if (complete_p) + { + /* Do exact allocation when complete, as we don't expect to add + many. */ + vec_safe_reserve_exact (method_vec, 1); + method_vec->quick_insert (ix, NULL_TREE); + } + else + { + gcc_checking_assert (ix == length); + vec_safe_push (method_vec, NULL_TREE); + } + CLASSTYPE_METHOD_VEC (klass) = method_vec; + + tree *slot = &(*method_vec)[ix]; + if (name == conv_op_identifier) + { + /* Install the marker prefix. */ + *slot = ovl_make (conv_op_marker, NULL_TREE); + slot = &OVL_CHAIN (*slot); + } + + return slot; +} + static struct { gt_pointer_operator new_value; void *cookie; Index: name-lookup.h =================================================================== --- name-lookup.h (revision 251722) +++ name-lookup.h (working copy) @@ -322,6 +322,7 @@ extern tree lookup_arg_dependent (tree, extern tree lookup_field_1 (tree, tree, bool); extern tree lookup_fnfields_slot (tree, tree); extern tree lookup_fnfields_slot_nolazy (tree, tree); +extern tree *get_method_slot (tree klass, tree name); extern void resort_type_method_vec (void *, void *, gt_pointer_operator, void *); extern void set_class_bindings (tree); --------------B59F7905CE5DEB98BAD5EA8A--