From patchwork Fri Mar 31 16:41:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: David Malcolm X-Patchwork-Id: 745707 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3vvmgv5bhMz9ryv for ; Sat, 1 Apr 2017 03:10:50 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="G+1tSCQZ"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=Iy/PL0m9Cgyv7YtW PUg3waFYllAkaBp+1e/u7fyfFpY57Q5nYe6gkiSBifxt+drTr3J/SjDXP9JbuVRS m23Hu2dUkt8p2O4ApMTBSktJrQ5291cLfIT6zY0p/sY2fusudmEaMvuQkhv9N12E j6y4uzLHsBiUVdlGhO98bwP8LlE= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=VUZy+dkmS77VqYD1YP1g4U bJzH8=; b=G+1tSCQZOBa7VbieSRyOgyoAX07+F2ZaQXxbu0BIJtKTujv2QymKwi T2PFT8aqwWAlwffHYLaVqc/MW8RO8dnqa5sXyGi+n06bn+28Z0QhA4uxjstwVZYd a+lIBOjSl3BQ1EH0XwOJisjYtwzc7UowcHvVUAZ3DKYX+bACqtsI0= Received: (qmail 108193 invoked by alias); 31 Mar 2017 16:10:37 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 105956 invoked by uid 89); 31 Mar 2017 16:10:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=picking, purely, bmm, criterion X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 31 Mar 2017 16:10:34 +0000 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EBCA2C05490C for ; Fri, 31 Mar 2017 16:10:33 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com EBCA2C05490C Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx08.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=dmalcolm@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com EBCA2C05490C Received: from c64.redhat.com (ovpn-112-33.phx2.redhat.com [10.3.112.33]) by smtp.corp.redhat.com (Postfix) with ESMTP id 151DC17C33; Fri, 31 Mar 2017 16:10:32 +0000 (UTC) From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH] Fix spelling suggestions for reserved words (PR c++/80177) Date: Fri, 31 Mar 2017 12:41:00 -0400 Message-Id: <1490978460-36271-1-git-send-email-dmalcolm@redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes As noted in the PR, the C++ frontend currently offers a poor suggestion for this misspelling: a.C: In function ‘void f()’: a.C:3:3: error: ‘static_assertion’ was not declared in this scope static_assertion (1 == 0, "1 == 0"); ^~~~~~~~~~~~~~~~ a.C:3:3: note: suggested alternative: ‘__cpp_static_assert’ static_assertion (1 == 0, "1 == 0"); ^~~~~~~~~~~~~~~~ __cpp_static_assert when it ought to offer "static_assert" as a suggestion instead. The root causes are two issues within lookup_name_fuzzy (called here with FUZZY_LOOKUP_NAME): (a) If it finds a good enough match in the preprocessor it will return the best match *before* considering reserved words, rather than picking the closest match overall. The fix is to have merge all the results into one best_match instance, and pick the overall winner. However, given that some candidates are identifiers (trees), and others are cpp macros, the best_match instance's candidate type needs to be converted from tree to const char *. This has some minor knock-on effects within name-lookup.c. Sadly it means some extra calls to strlen (one per candidate), but this will be purely when error-handling. (b) It rejects "static_assert" here: 4998 if (!cp_keyword_starts_decl_specifier_p (resword->rid)) 4999 continue; as "static_assert" doesn't start a decl specifier. The fix is to only apply this rejection criterion if we're looking for typenames, rather than for names in general. This patch addresses both issues and adds test coverage. Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. Adds 7 PASS and 1 UNSUPPORTED (for -std=c++98) to g++.sum OK for next stage 1? gcc/cp/ChangeLog: PR c++/80177 * name-lookup.c (suggest_alternative_in_explicit_scope): Convert candidate type of bm from tree to const char *. (consider_binding_level): Likewise. (lookup_name_fuzzy): Likewise, using this to merge the best result from the preprocessor into bm, rather than immediately returning, so that better matches from reserved words can "win". Guard the rejection of keywords that don't start decl-specifiers so it only happens for FUZZY_LOOKUP_TYPENAME. gcc/testsuite/ChangeLog: PR c++/80177 * g++.dg/spellcheck-pr80177.C: New test case. --- gcc/cp/name-lookup.c | 37 +++++++++++++------------------ gcc/testsuite/g++.dg/spellcheck-pr80177.C | 7 ++++++ 2 files changed, 23 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/spellcheck-pr80177.C diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 994f7f0..16ec0a1 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -48,7 +48,8 @@ static bool lookup_using_namespace (tree, struct scope_binding *, tree, tree, int); static bool qualified_lookup_using_namespace (tree, tree, struct scope_binding *, int); -static void consider_binding_level (tree name, best_match &bm, +static void consider_binding_level (tree name, + best_match &bm, cp_binding_level *lvl, bool look_within_fields, enum lookup_name_fuzzy_kind kind); @@ -4550,14 +4551,13 @@ suggest_alternative_in_explicit_scope (location_t location, tree name, cp_binding_level *level = NAMESPACE_LEVEL (scope); - best_match bm (name); + best_match bm (name); consider_binding_level (name, bm, level, false, FUZZY_LOOKUP_NAME); /* See if we have a good suggesion for the user. */ - tree best_id = bm.get_best_meaningful_candidate (); - if (best_id) + const char *fuzzy_name = bm.get_best_meaningful_candidate (); + if (fuzzy_name) { - const char *fuzzy_name = IDENTIFIER_POINTER (best_id); gcc_rich_location richloc (location); richloc.add_fixit_replace (fuzzy_name); inform_at_rich_loc (&richloc, "suggested alternative: %qs", @@ -4797,7 +4797,7 @@ qualified_lookup_using_namespace (tree name, tree scope, Traverse binding level LVL, looking for good name matches for NAME (and BM). */ static void -consider_binding_level (tree name, best_match &bm, +consider_binding_level (tree name, best_match &bm, cp_binding_level *lvl, bool look_within_fields, enum lookup_name_fuzzy_kind kind) { @@ -4809,7 +4809,7 @@ consider_binding_level (tree name, best_match &bm, tree best_matching_field = lookup_member_fuzzy (type, name, want_type_p); if (best_matching_field) - bm.consider (best_matching_field); + bm.consider (IDENTIFIER_POINTER (best_matching_field)); } for (tree t = lvl->names; t; t = TREE_CHAIN (t)) @@ -4838,7 +4838,7 @@ consider_binding_level (tree name, best_match &bm, if (tree name = DECL_NAME (d)) /* Ignore internal names with spaces in them. */ if (!strchr (IDENTIFIER_POINTER (name), ' ')) - bm.consider (DECL_NAME (d)); + bm.consider (IDENTIFIER_POINTER (name)); } } @@ -4851,7 +4851,7 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind) { gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE); - best_match bm (name); + best_match bm (name); cp_binding_level *lvl; for (lvl = scope_chain->class_bindings; lvl; lvl = lvl->level_chain) @@ -4874,9 +4874,9 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind) the identifiers already checked. */ best_macro_match bmm (name, bm.get_best_distance (), parse_in); cpp_hashnode *best_macro = bmm.get_best_meaningful_candidate (); - /* If a macro is the closest so far to NAME, suggest it. */ + /* If a macro is the closest so far to NAME, consider it. */ if (best_macro) - return (const char *)best_macro->ident.str; + bm.consider ((const char *)best_macro->ident.str); /* Try the "starts_decl_specifier_p" keywords to detect "singed" vs "signed" typos. */ @@ -4884,8 +4884,9 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind) { const c_common_resword *resword = &c_common_reswords[i]; - if (!cp_keyword_starts_decl_specifier_p (resword->rid)) - continue; + if (kind == FUZZY_LOOKUP_TYPENAME) + if (!cp_keyword_starts_decl_specifier_p (resword->rid)) + continue; tree resword_identifier = ridpointers [resword->rid]; if (!resword_identifier) @@ -4897,16 +4898,10 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind) if (!C_IS_RESERVED_WORD (resword_identifier)) continue; - bm.consider (resword_identifier); + bm.consider (IDENTIFIER_POINTER (resword_identifier)); } - /* See if we have a good suggesion for the user. */ - tree best_id = bm.get_best_meaningful_candidate (); - if (best_id) - return IDENTIFIER_POINTER (best_id); - - /* No meaningful suggestion available. */ - return NULL; + return bm.get_best_meaningful_candidate (); } /* Subroutine of outer_binding. diff --git a/gcc/testsuite/g++.dg/spellcheck-pr80177.C b/gcc/testsuite/g++.dg/spellcheck-pr80177.C new file mode 100644 index 0000000..2ff24e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/spellcheck-pr80177.C @@ -0,0 +1,7 @@ +// { dg-do compile { target c++11 } } + +void pr80177 () +{ + static_assertion (1 == 0, "1 == 0"); // { dg-error "3: 'static_assertion' was not declared in this scope" } + // { dg-message "3: suggested alternative: 'static_assert'" "" { target *-*-* } .-1 } +}