diff options
author | Mark Wielaard <mark@klomp.org> | 2020-05-22 01:10:50 +0200 |
---|---|---|
committer | Mark Wielaard <mark@klomp.org> | 2020-06-04 01:22:52 +0200 |
commit | 9eea5d2ddf73037e21b59bcd8084ba969ae10174 (patch) | |
tree | fc247b15b760343e12c8472d91d08634b9340557 /gcc/c | |
parent | 34e4962aed08b38f37e37242234bfbbd1b897f39 (diff) | |
download | gcc-9eea5d2ddf73037e21b59bcd8084ba969ae10174.zip gcc-9eea5d2ddf73037e21b59bcd8084ba969ae10174.tar.gz gcc-9eea5d2ddf73037e21b59bcd8084ba969ae10174.tar.bz2 |
Provide diagnostic hints for missing C inttypes.h string constants.
This adds a flag to c_parser so we know when we were trying to
construct a string literal. If there is a parse error and we were
constructing a string literal, and the next token is an unknown
identifier name, and we know there is a standard header that defines
that name as a string literal, then add a missing header hint to
the error messsage.
The list of macro names are also used when providing a hint for
missing identifiers.
gcc/c-family/ChangeLog:
* known-headers.cc (get_string_macro_hint): New function.
(get_stdlib_header_for_name): Use get_string_macro_hint.
(get_c_stdlib_header_for_string_macro_name): New function.
* known-headers.h (get_c_stdlib_header_for_string_macro_name):
New function declaration.
gcc/c/ChangeLog:
* c-parser.c (struct c_parser): Add seen_string_literal
bitfield.
(c_parser_consume_token): Reset seen_string_literal.
(c_parser_error_richloc): Add name_hint if seen_string_literal
and next token is a CPP_NAME and we have a missing header
suggestion for the name.
(c_parser_string_literal): Set seen_string_literal.
gcc/testsuite/ChangeLog:
* gcc.dg/spellcheck-inttypes.c: New test.
* g++.dg/spellcheck-inttypes.C: Likewise.
Diffstat (limited to 'gcc/c')
-rw-r--r-- | gcc/c/c-parser.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 23d6fa2..df0b59f 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/name-hint.h" #include "tree-iterator.h" #include "memmodel.h" +#include "c-family/known-headers.h" /* We need to walk over decls with incomplete struct/union/enum types after parsing the whole translation unit. @@ -223,6 +224,13 @@ struct GTY(()) c_parser { keywords are valid. */ BOOL_BITFIELD objc_property_attr_context : 1; + /* Whether we have just seen/constructed a string-literal. Set when + returning a string-literal from c_parser_string_literal. Reset + in consume_token. Useful when we get a parse error and see an + unknown token, which could have been a string-literal constant + macro. */ + BOOL_BITFIELD seen_string_literal : 1; + /* Location of the last consumed token. */ location_t last_token_location; }; @@ -853,6 +861,7 @@ c_parser_consume_token (c_parser *parser) } } parser->tokens_avail--; + parser->seen_string_literal = false; } /* Expect the current token to be a #pragma. Consume it and remember @@ -966,6 +975,25 @@ c_parser_error_richloc (c_parser *parser, const char *gmsgid, } } + /* If we were parsing a string-literal and there is an unknown name + token right after, then check to see if that could also have been + a literal string by checking the name against a list of known + standard string literal constants defined in header files. If + there is one, then add that as an hint to the error message. */ + auto_diagnostic_group d; + name_hint h; + if (parser->seen_string_literal && token->type == CPP_NAME) + { + tree name = token->value; + const char *token_name = IDENTIFIER_POINTER (name); + const char *header_hint + = get_c_stdlib_header_for_string_macro_name (token_name); + if (header_hint != NULL) + h = name_hint (NULL, new suggest_missing_header (token->location, + token_name, + header_hint)); + } + c_parse_error (gmsgid, /* Because c_parse_error does not understand CPP_KEYWORD, keywords are treated like @@ -7539,6 +7567,7 @@ c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok) ret.original_code = STRING_CST; ret.original_type = NULL_TREE; set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc)); + parser->seen_string_literal = true; return ret; } |