From patchwork Fri Oct 2 18:23:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 1376026 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.a=rsa-sha256 header.s=20161025 header.b=WlqcobLt; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C2yzv5FB0z9sS8 for ; Sat, 3 Oct 2020 04:23:37 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8D8EC398E464; Fri, 2 Oct 2020 18:23:34 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qv1-xf2e.google.com (mail-qv1-xf2e.google.com [IPv6:2607:f8b0:4864:20::f2e]) by sourceware.org (Postfix) with ESMTPS id 9BFA0388E81A for ; Fri, 2 Oct 2020 18:23:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 9BFA0388E81A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=acm.org Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=nathanmsidwell@gmail.com Received: by mail-qv1-xf2e.google.com with SMTP id h1so1341331qvo.9 for ; Fri, 02 Oct 2020 11:23:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:to:cc:from:subject:message-id:date:user-agent:mime-version :content-language; bh=YSxOHna0u5EmaaTZ9R89/g2QpSKUjAKou/LayTmIHrw=; b=WlqcobLtXzAQtLQ5sZFXR2cyRRtVJHqDiiZgj8QcemTvSEaGbVGL1J7mpEAJDIbMTJ +uO47hwqKMWY/FJfxuzc6cZCqX+vPAinpz/XTOhK9bGw9Edap0mSWMrFYBIim4599sjU FDETgVyqplUCupUWCezJhSvzZCIVkgCi0aSkco8k+5xYrII33pXApve9oNmcNJSef1eM bJ8xtp0UqBI2NoWU/2Hu9kZHw6czcjQNBn5vDJ2dcY8jfoffyw+0ItJxVedqrNS55aX5 hUHqTi9sZoLoKNRtrLbMI9Nl3gbVsu/PkCheTekDApYtTC38p4APYTvjilU8Tvej5UfQ uPWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:cc:from:subject:message-id:date :user-agent:mime-version:content-language; bh=YSxOHna0u5EmaaTZ9R89/g2QpSKUjAKou/LayTmIHrw=; b=YksN/IbQMXLtEYOVfbXcocLRi/LHXnWxIOWHUnnJoNBuifLn4Cqf0wjWf3J2QcnMnd Lg68EX5buHtt1oOT3aKKpu1AB9AZ4omeqHXGb0c2j0NJb0SvjAke2f7OJfrqInR251cb RLnZLXVb7EOt3SoyS0wZevdbEFcnuUSVNlySTF+j2MDzjzI14bAZUyTbBemnnx8CYRGj L6gccugmT1L17J+fuse1MBbqLjVzUnklY+jkS8jx2S9dbBGNL8Ed9v6RhzZNcnEl9Xzr 16fZptWzCZWgc1aqdJ9TIVedIkWmK0wgLaUZBZxHD+hI7ECJ/GdjJY0c24mmfNc5bc3W XxrQ== X-Gm-Message-State: AOAM5307sLtIViLXtiS/RYwLoe3FITxqBmrv5EEmzLVU5VNdTmGj7Pbt miJ4mGrSzzGz7B5biOBAxUc= X-Google-Smtp-Source: ABdhPJwC0NCe/4o791+DiK3uDd7NP94pOAPFHJlLYdcXuLcmd/wugh9xeZ7ZlL0N7Rj46RHoxZDWOA== X-Received: by 2002:a0c:b2ce:: with SMTP id d14mr3449503qvf.40.1601663010822; Fri, 02 Oct 2020 11:23:30 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a8:1102:4d4:12a8:4b39:fdd5? ([2620:10d:c091:480::1:e7d]) by smtp.googlemail.com with ESMTPSA id u90sm1464845qtd.29.2020.10.02.11.23.28 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 02 Oct 2020 11:23:29 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: c++: Hash table iteration for namespace-member spelling suggestions Message-ID: <86c6a298-4f6b-aeb2-a9bb-dac5015d7f30@acm.org> Date: Fri, 2 Oct 2020 14:23:27 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Thunderbird/68.5.0 MIME-Version: 1.0 Content-Language: en-US X-Spam-Status: No, score=-10.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_EF, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" For 'no such binding' errors, we iterate over binding levels to find a close match. At the namespace level we were using DECL_ANTICIPATED to skip undeclared builtins. But (a) there are other unnameable things there and (b) decl-anticipated is about to go away. This changes the namespace scanning to iterate over the hash table, and look at non-hidden bindings. This does mean we look at fewer strings (hurrarh), but the order we meet them is somewhat 'random'. Our distance measure is not very fine grained, and a couple of testcases change their suggestion. I notice for the c/c++ common one, we now match the output of the C compiler. For the other one we think 'int' and 'int64_t' have the same distance from 'int64', and now meet the former first. That's a little unfortunate. If it's too problematic I suppose we could sort the strings via an intermediate array before measuring distance. gcc/cp/ * name-lookup.c (consider_decl): New, broken out of ... (consider_binding_level): ... here. Iterate the hash table for namespace bindings. gcc/testsuite/ * c-c++-common/spellcheck-reserved.c: Adjust diagnostic. * g++.dg/spellcheck-typenames.C: Adjust diagnostic. pushing to trunk nathan diff --git i/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c index 6204444f3a6..4024ceaa74b 100644 --- i/gcc/cp/name-lookup.c +++ w/gcc/cp/name-lookup.c @@ -6106,6 +6106,39 @@ qualified_namespace_lookup (tree scope, name_lookup *lookup) return found; } +static void +consider_decl (tree decl, best_match &bm, + bool consider_impl_names) +{ + /* Skip compiler-generated variables (e.g. __for_begin/__for_end + within range for). */ + if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)) + return; + + tree suggestion = DECL_NAME (decl); + if (!suggestion) + return; + + /* Don't suggest names that are for anonymous aggregate types, as + they are an implementation detail generated by the compiler. */ + if (IDENTIFIER_ANON_P (suggestion)) + return; + + const char *suggestion_str = IDENTIFIER_POINTER (suggestion); + + /* Ignore internal names with spaces in them. */ + if (strchr (suggestion_str, ' ')) + return; + + /* Don't suggest names that are reserved for use by the + implementation, unless NAME began with an underscore. */ + if (!consider_impl_names + && name_reserved_for_implementation_p (suggestion_str)) + return; + + bm.consider (suggestion_str); +} + /* Helper function for lookup_name_fuzzy. Traverse binding level LVL, looking for good name matches for NAME (and BM). */ @@ -6129,54 +6162,63 @@ consider_binding_level (tree name, best_match &bm, with an underscore. */ bool consider_implementation_names = (IDENTIFIER_POINTER (name)[0] == '_'); - for (tree t = lvl->names; t; t = TREE_CHAIN (t)) - { - tree d = t; - - /* OVERLOADs or decls from using declaration are wrapped into - TREE_LIST. */ - if (TREE_CODE (d) == TREE_LIST) - d = OVL_FIRST (TREE_VALUE (d)); - - /* Don't use bindings from implicitly declared functions, - as they were likely misspellings themselves. */ - if (TREE_TYPE (d) == error_mark_node) - continue; - - /* Skip anticipated decls of builtin functions. */ - if (TREE_CODE (d) == FUNCTION_DECL - && fndecl_built_in_p (d) - && DECL_ANTICIPATED (d)) - continue; + if (lvl->kind != sk_namespace) + for (tree t = lvl->names; t; t = TREE_CHAIN (t)) + { + tree d = t; - /* Skip compiler-generated variables (e.g. __for_begin/__for_end - within range for). */ - if (TREE_CODE (d) == VAR_DECL - && DECL_ARTIFICIAL (d)) - continue; + /* OVERLOADs or decls from using declaration are wrapped into + TREE_LIST. */ + if (TREE_CODE (d) == TREE_LIST) + d = OVL_FIRST (TREE_VALUE (d)); - tree suggestion = DECL_NAME (d); - if (!suggestion) - continue; - - /* Don't suggest names that are for anonymous aggregate types, as - they are an implementation detail generated by the compiler. */ - if (IDENTIFIER_ANON_P (suggestion)) - continue; + /* Don't use bindings from implicitly declared functions, + as they were likely misspellings themselves. */ + if (TREE_TYPE (d) == error_mark_node) + continue; - const char *suggestion_str = IDENTIFIER_POINTER (suggestion); + /* If we want a typename, ignore non-types. */ + if (kind == FUZZY_LOOKUP_TYPENAME + && TREE_CODE (STRIP_TEMPLATE (d)) != TYPE_DECL) + continue; - /* Ignore internal names with spaces in them. */ - if (strchr (suggestion_str, ' ')) - continue; + consider_decl (d, bm, consider_implementation_names); + } + else + { + /* Iterate over the namespace hash table, that'll have fewer + entries than the decl list. */ + tree ns = lvl->this_entity; - /* Don't suggest names that are reserved for use by the - implementation, unless NAME began with an underscore. */ - if (name_reserved_for_implementation_p (suggestion_str) - && !consider_implementation_names) - continue; + hash_table::iterator end + (DECL_NAMESPACE_BINDINGS (ns)->end ()); + for (hash_table::iterator iter + (DECL_NAMESPACE_BINDINGS (ns)->begin ()); iter != end; ++iter) + { + tree binding = *iter; + tree value = NULL_TREE; - bm.consider (suggestion_str); + if (STAT_HACK_P (binding)) + { + if (!STAT_TYPE_HIDDEN_P (binding) + && STAT_TYPE (binding)) + consider_decl (STAT_TYPE (binding), bm, + consider_implementation_names); + else if (!STAT_DECL_HIDDEN_P (binding)) + value = STAT_DECL (binding); + } + else + value = binding; + + value = ovl_skip_hidden (value); + if (value) + { + value = OVL_FIRST (value); + if (!(kind == FUZZY_LOOKUP_TYPENAME + && TREE_CODE (STRIP_TEMPLATE (value)) != TYPE_DECL)) + consider_decl (value, bm, consider_implementation_names); + } + } } } diff --git i/gcc/testsuite/c-c++-common/spellcheck-reserved.c w/gcc/testsuite/c-c++-common/spellcheck-reserved.c index ed292f2bae0..175ba4a2e0f 100644 --- i/gcc/testsuite/c-c++-common/spellcheck-reserved.c +++ w/gcc/testsuite/c-c++-common/spellcheck-reserved.c @@ -30,7 +30,7 @@ void test (const char *buf, char ch) { __builtin_strtchr (buf, ch); /* { dg-line misspelled_reserved } */ /* { dg-warning "did you mean '__builtin_strchr'" "" { target c } misspelled_reserved } */ - /* { dg-error "'__builtin_strtchr' was not declared in this scope; did you mean '__builtin_strrchr'\\?" "" { target c++ } misspelled_reserved } */ + /* { dg-error "'__builtin_strtchr' was not declared in this scope; did you mean '__builtin_strchr'\\?" "" { target c++ } misspelled_reserved } */ } /* Similarly for a name that begins with a single underscore. */ diff --git i/gcc/testsuite/g++.dg/spellcheck-typenames.C w/gcc/testsuite/g++.dg/spellcheck-typenames.C index 6adf724a3b7..ff53ecc6303 100644 --- i/gcc/testsuite/g++.dg/spellcheck-typenames.C +++ w/gcc/testsuite/g++.dg/spellcheck-typenames.C @@ -54,11 +54,11 @@ struct some_thing test_6; // { dg-error "aggregate 'some_thing test_6' has incom { dg-end-multiline-output "" } */ typedef long int64_t; -int64 i; // { dg-error "1: 'int64' does not name a type; did you mean 'int64_t'?" } +int64 i; // { dg-error "1: 'int64' does not name a type; did you mean 'int'?" } /* { dg-begin-multiline-output "" } int64 i; ^~~~~ - int64_t + int { dg-end-multiline-output "" } */ /* Verify that gcc doesn't offer nonsensical suggestions. */