diff options
author | David Malcolm <dmalcolm@redhat.com> | 2016-07-20 18:42:11 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2016-07-20 18:42:11 +0000 |
commit | 52ed68f71a750260fd926479e41e3f7ad7cd9aa2 (patch) | |
tree | b49c604effb64ec60ec0f92309badfd3781fc6c4 /gcc/cp/parser.c | |
parent | 1397e163014843fa6803b3959adfc0011d75bc6a (diff) | |
download | gcc-52ed68f71a750260fd926479e41e3f7ad7cd9aa2.zip gcc-52ed68f71a750260fd926479e41e3f7ad7cd9aa2.tar.gz gcc-52ed68f71a750260fd926479e41e3f7ad7cd9aa2.tar.bz2 |
C++ FE: handle misspelled identifiers and typenames
gcc/cp/ChangeLog:
PR c/70339
PR c/71858
* name-lookup.c: Include gcc-rich-location.h, spellcheck-tree.h,
and parser.h.
(suggest_alternatives_for): If no candidates are found, try
lookup_name_fuzzy and report if if finds a suggestion.
(consider_binding_level): New function.
(lookup_name_fuzzy) New function.
* parser.c: Include gcc-rich-location.h.
(cp_lexer_next_token_is_decl_specifier_keyword): Move most of
logic into...
(cp_keyword_starts_decl_specifier_p): ...this new function.
(cp_parser_diagnose_invalid_type_name): When issuing
"does not name a type" errors, attempt to make a suggestion using
lookup_name_fuzzy.
* parser.h (cp_keyword_starts_decl_specifier_p): New prototype.
* search.c (lookup_field_fuzzy_info::fuzzy_lookup_field): Reject
types that are not CLASS_TYPE_P, rather than rejecting individual
tree codes.
gcc/testsuite/ChangeLog:
PR c/70339
PR c/71858
* g++.dg/spellcheck-identifiers.C: New test case, based on
gcc.dg/spellcheck-identifiers.c.
* g++.dg/spellcheck-identifiers-2.C: New test case, based on
gcc.dg/spellcheck-identifiers-2.c.
* g++.dg/spellcheck-typenames.C: New test case, based on
gcc.dg/spellcheck-typenames.c
From-SVN: r238538
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 84dad48..8fceaed 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -40,6 +40,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-indentation.h" #include "context.h" #include "cp-cilkplus.h" +#include "gcc-rich-location.h" /* The lexer. */ @@ -937,15 +938,12 @@ cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword) return cp_lexer_peek_token (lexer)->keyword != keyword; } -/* Return true if the next token is a keyword for a decl-specifier. */ +/* Return true if KEYWORD can start a decl-specifier. */ -static bool -cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) +bool +cp_keyword_starts_decl_specifier_p (enum rid keyword) { - cp_token *token; - - token = cp_lexer_peek_token (lexer); - switch (token->keyword) + switch (keyword) { /* auto specifier: storage-class-specifier in C++, simple-type-specifier in C++0x. */ @@ -985,14 +983,25 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) return true; default: - if (token->keyword >= RID_FIRST_INT_N - && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS - && int_n_enabled_p[token->keyword - RID_FIRST_INT_N]) + if (keyword >= RID_FIRST_INT_N + && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS + && int_n_enabled_p[keyword - RID_FIRST_INT_N]) return true; return false; } } +/* Return true if the next token is a keyword for a decl-specifier. */ + +static bool +cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer) +{ + cp_token *token; + + token = cp_lexer_peek_token (lexer); + return cp_keyword_starts_decl_specifier_p (token->keyword); +} + /* Returns TRUE iff the token T begins a decltype type. */ static bool @@ -3154,7 +3163,19 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree id, else if (!parser->scope) { /* Issue an error message. */ - error_at (location, "%qE does not name a type", id); + const char *suggestion = NULL; + if (TREE_CODE (id) == IDENTIFIER_NODE) + suggestion = lookup_name_fuzzy (id, FUZZY_LOOKUP_TYPENAME); + if (suggestion) + { + gcc_rich_location richloc (location); + richloc.add_fixit_misspelled_id (location, suggestion); + error_at_rich_loc (&richloc, + "%qE does not name a type; did you mean %qs?", + id, suggestion); + } + else + error_at (location, "%qE does not name a type", id); /* If we're in a template class, it's possible that the user was referring to a type from a base class. For example: |