From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9708 invoked by alias); 19 Dec 2016 16:18:07 -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 9662 invoked by uid 89); 19 Dec 2016 16:18:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-5.0 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=Offer, misspelled, cpp0x, H*Ad:U*dmalcolm 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; Mon, 19 Dec 2016 16:18:03 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8E78F8123D for ; Mon, 19 Dec 2016 16:18:02 +0000 (UTC) Received: from c64.redhat.com (vpn-230-239.phx2.redhat.com [10.3.230.239]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id uBJGI195017570; Mon, 19 Dec 2016 11:18:02 -0500 From: David Malcolm To: gcc-patches@gcc.gnu.org Cc: David Malcolm Subject: [PATCH] Offer suggestions for misspelled attributes (PR c/70186) Date: Mon, 19 Dec 2016 16:18:00 -0000 Message-Id: <1482166289-33945-1-git-send-email-dmalcolm@redhat.com> X-IsSubscribed: yes X-SW-Source: 2016-12/txt/msg01611.txt.bz2 Our -Wattributes warnings can be rather cryptic. The following patch improves this warning: ../../src/pr70186.c:1:8: warning: 'visbility' attribute directive ignored [-Wattributes] struct S *foo __attribute__ ((visbility("hidden"))); ^ by adding suggestions when unrecognized attributes are encountered, turning it into this: ../../src/pr70186.c:1:8: warning: 'visbility' attribute directive ignored; did you mean 'visibility'? [-Wattributes] struct S *foo __attribute__ ((visbility("hidden"))); ^ Successfully bootstrapped®rtested on x86_64-pc-linux-gnu. Rather late for gcc 7, sorry. Is this OK for next stage 1, or OK for stage 3 now? (if this looks low-enough risk) gcc/ChangeLog: PR c/70186 * attribs.c: Include "spellcheck.h". (extract_attribute_substring): Fix leading comment. Return a bool signifying if truncation for underscores occurred. (struct edit_distance_traits): New class. (fuzzy_lookup_scoped_attribute_spec): New function, based on lookup_scoped_attribute_spec. (decl_attributes): Move warning about ignored attributes to.. (warn_about_unidentified_attribute): ...this new function, and potentially offer suggestions for misspelled attributes. gcc/testsuite/ChangeLog: PR c/70186 * c-c++-common/spellcheck-attributes.c: New test case. * g++.dg/cpp0x/spellcheck-attributes.C: New test case. --- gcc/attribs.c | 115 ++++++++++++++++++--- gcc/testsuite/c-c++-common/spellcheck-attributes.c | 5 + gcc/testsuite/g++.dg/cpp0x/spellcheck-attributes.C | 18 ++++ 3 files changed, 126 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/spellcheck-attributes.c create mode 100644 gcc/testsuite/g++.dg/cpp0x/spellcheck-attributes.C diff --git a/gcc/attribs.c b/gcc/attribs.c index e66349a..ff5ce0d 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -28,6 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "stor-layout.h" #include "langhooks.h" #include "plugin.h" +#include "spellcheck.h" /* Table of the tables of attributes (common, language, format, machine) searched. */ @@ -97,10 +98,11 @@ static const struct attribute_spec empty_attribute_table[] = { NULL, 0, 0, false, false, false, NULL, false } }; -/* Return base name of the attribute. Ie '__attr__' is turned into 'attr'. - To avoid need for copying, we simply return length of the string. */ +/* Extract base name of the attribute. Ie '__attr__' is turned into 'attr'. + To avoid need for copying, we simply update length of the string. + Return true if the string was truncated, false otherwise. */ -static void +static bool extract_attribute_substring (struct substring *str) { if (str->length > 4 && str->str[0] == '_' && str->str[1] == '_' @@ -108,7 +110,9 @@ extract_attribute_substring (struct substring *str) { str->length -= 4; str->str += 2; + return true; } + return false; } /* Insert an array of attributes ATTRIBUTES into a namespace. This @@ -343,6 +347,101 @@ get_attribute_namespace (const_tree attr) return get_identifier ("gnu"); } +/* Specialization of edit_distance_traits for struct substring. */ + +template <> +struct edit_distance_traits +{ + static size_t get_length (struct substring *substr) + { + gcc_assert (substr); + return substr->length; + } + + static const char *get_string (struct substring *substr) + { + gcc_assert (substr); + return substr->str; + } +}; + +/* Look for near matches for the scoped attribute with namespace NS and + name NAME. + Return the best matching attribute name, or NULL if none is found. + If it returns non-NULL then *UNDERSCORES is written to, with true + iff leading and trailing underscores were stripped from NAME + before the match. */ + +static const char * +fuzzy_lookup_scoped_attribute_spec (const_tree ns, const_tree name, + bool *underscores) +{ + struct substring attr; + scoped_attributes *attrs; + + const char *ns_str = (ns != NULL_TREE) ? IDENTIFIER_POINTER (ns): NULL; + + attrs = find_attribute_namespace (ns_str); + + if (attrs == NULL) + return NULL; + + attr.str = IDENTIFIER_POINTER (name); + attr.length = IDENTIFIER_LENGTH (name); + *underscores = extract_attribute_substring (&attr); + + best_match bm (&attr); + + hash_table *h = attrs->attribute_hash; + for (hash_table::iterator iter = h->begin (); + iter != h->end (); ++iter) + bm.consider ((*iter)->name); + return bm.get_best_meaningful_candidate (); +} + +/* Warn about attribute A being unrecognized with name NAME (an identifier), + within namespace NS (an identifier, or NULL_TREE). + Issue a hint if it appears to be misspelled. */ + +static void +warn_about_unidentified_attribute (tree a, tree ns, tree name) +{ + bool underscores; + const char *hint + = fuzzy_lookup_scoped_attribute_spec (ns, name, &underscores); + + if (ns == NULL_TREE || !cxx11_attribute_p (a)) + if (hint) + if (underscores) + warning (OPT_Wattributes, + ("%qE attribute directive ignored" + "; did you mean %<__%s__%>?"), + name, hint); + else + warning (OPT_Wattributes, + ("%qE attribute directive ignored" + "; did you mean %qs?"), + name, hint); + else + warning (OPT_Wattributes, "%qE attribute directive ignored", + name); + else + if (hint) + if (underscores) + warning (OPT_Wattributes, + ("%<%E::%E%> scoped attribute directive" + " ignored; did you mean %<%E::__%s__%>?"), + ns, name, ns, hint); + else + warning (OPT_Wattributes, + ("%<%E::%E%> scoped attribute directive ignored" + "; did you mean %<%E::%s%>?"), + ns, name, ns, hint); + else + warning (OPT_Wattributes, + "%<%E::%E%> scoped attribute directive ignored", + ns, name); +} /* Process the attributes listed in ATTRIBUTES and install them in *NODE, which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, @@ -431,15 +530,7 @@ decl_attributes (tree *node, tree attributes, int flags) if (spec == NULL) { if (!(flags & (int) ATTR_FLAG_BUILT_IN)) - { - if (ns == NULL_TREE || !cxx11_attribute_p (a)) - warning (OPT_Wattributes, "%qE attribute directive ignored", - name); - else - warning (OPT_Wattributes, - "%<%E::%E%> scoped attribute directive ignored", - ns, name); - } + warn_about_unidentified_attribute (a, ns, name); continue; } else if (list_length (args) < spec->min_length diff --git a/gcc/testsuite/c-c++-common/spellcheck-attributes.c b/gcc/testsuite/c-c++-common/spellcheck-attributes.c new file mode 100644 index 0000000..a0da879 --- /dev/null +++ b/gcc/testsuite/c-c++-common/spellcheck-attributes.c @@ -0,0 +1,5 @@ +struct S *s1 __attribute__ ((visbility("hidden"))); +/* { dg-warning ".visbility. attribute directive ignored; did you mean .visibility." "" { target *-*-* } .-1 } */ + +struct S *s2 __attribute__ ((__visbility__("hidden"))); +/* { dg-warning ".__visbility__. attribute directive ignored; did you mean .__visibility__." "" { target *-*-* } .-1 } */ diff --git a/gcc/testsuite/g++.dg/cpp0x/spellcheck-attributes.C b/gcc/testsuite/g++.dg/cpp0x/spellcheck-attributes.C new file mode 100644 index 0000000..ca72608 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/spellcheck-attributes.C @@ -0,0 +1,18 @@ +// { dg-do compile { target c++11 } } + +int +test () +{ + [[gnu::unused]] lab_1: + + [[gnu::unuse]] lab_2: + /* { dg-warning ".gnu::unuse. scoped attribute directive ignored; did you mean .gnu::unused.." "" { target *-*-* } .-1 } */ + return 0; + + [[gnu::__unused__]] lab_3: + + [[gnu::__unuse__]] lab_4: + /* { dg-warning ".gnu::__unuse__. scoped attribute directive ignored; did you mean .gnu::__unused__.." "" { target *-*-* } .-1 } */ + return 0; + +} -- 1.8.5.3