aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-decl.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-11-21 00:50:39 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-11-21 00:50:39 +0000
commit26edace69b6b909eebddcf18c8844bb4c94d9a35 (patch)
treec414ee9be1fe6e6f9cd8b371e22e609482196e19 /gcc/c/c-decl.c
parentb1212255558f0a4a398c7314f92effe4dbdcfec2 (diff)
downloadgcc-26edace69b6b909eebddcf18c8844bb4c94d9a35.zip
gcc-26edace69b6b909eebddcf18c8844bb4c94d9a35.tar.gz
gcc-26edace69b6b909eebddcf18c8844bb4c94d9a35.tar.bz2
C/C++: more stdlib header hints (PR c/81404)
This patch extends the C frontend's "knowledge" of the C stdlib within get_c_name_hint to cover some more macros and functions, covering a case reported in PR c/81404 ("INT_MAX"), so that rather than printing: t.c:5:12: error: 'INT_MAX' undeclared here (not in a function); did you mean '__INT_MAX__'? int test = INT_MAX; ^~~~~~~ __INT_MAX__ we instead print: t.c:5:12: error: 'INT_MAX' undeclared here (not in a function) int test = INT_MAX; ^~~~~~~ t.c:5:12: note: 'INT_MAX' is defined in header '<limits.h>'; did you forget to '#include <limits.h>'? t.c:1:1: +#include <limits.h> t.c:5:12: int test = INT_MAX; ^~~~~~~ It also adds generalizes some of the code for this (and for the "std::" namespace hints in the C++ frontend), moving it to a new c-family/known-headers.cc and .h, and introducing a class known_headers. This currently just works by scanning a hardcoded array of known name/header associations, but perhaps in the future could be turned into some kind of symbol database so that the compiler could record API uses and use that to offer suggestions e.g. foo.cc: error: 'myapi::foo' was not declared in this scope foo.cc: note: 'myapi::foo" was declared in header 'myapi/private.h' (included via 'myapi/public.h') when compiling 'bar.cc'; did you forget to '#include "myapi/public.h"'? or somesuch. In any case, moving this to a class gives an easier way to locate the hardcoded knowledge about the stdlib. The patch also adds similar code to the C++ frontend covering unqualified names in the standard library, so that rather than just e.g.: t.cc:19:13: error: 'NULL' was not declared in this scope void *ptr = NULL; ^~~~ we can emit: t.cc:19:13: error: 'NULL' was not declared in this scope void *ptr = NULL; ^~~~ t.cc:19:13: note: 'NULL' is defined in header '<cstddef>'; did you forget to '#include <cstddef>'? t.cc:1:1: +#include <cstddef> t.cc:19:13: void *ptr = NULL; ^~~~ (Also XFAIL for PR c++/80567 added for the C++ testcase; this is a separate pre-existing bug exposed by the testcase for PR 81404). gcc/ChangeLog: PR c/81404 * Makefile.in (C_COMMON_OBJS): Add c-family/known-headers.o. gcc/c-family/ChangeLog: PR c/81404 * known-headers.cc: New file, based on material from c/c-decl.c. (suggest_missing_header): Copied as-is. (get_stdlib_header_for_name): New, based on get_c_name_hint but heavily edited to add C++ support. Add some knowledge about <limits.h>, <stdint.h>, and <wchar.h>. * known-headers.h: Likewise. gcc/c/ChangeLog: PR c/81404 * c-decl.c: Include "c-family/known-headers.h". (get_c_name_hint): Rename to get_stdlib_header_for_name and move to known-headers.cc. (class suggest_missing_header): Move to known-header.h. (lookup_name_fuzzy): Call get_c_stdlib_header_for_name rather than get_c_name_hint. gcc/cp/ChangeLog: PR c/81404 * name-lookup.c: Include "c-family/known-headers.h" (lookup_name_fuzzy): Call get_cp_stdlib_header_for_name and potentially return a new suggest_missing_header hint. gcc/testsuite/ChangeLog: PR c/81404 * g++.dg/spellcheck-stdlib.C: New. * gcc.dg/spellcheck-stdlib.c (test_INT_MAX): New. From-SVN: r254980
Diffstat (limited to 'gcc/c/c-decl.c')
-rw-r--r--gcc/c/c-decl.c82
1 files changed, 4 insertions, 78 deletions
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index ae45e9a..e0a4dd1 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see
#include "gcc-rich-location.h"
#include "asan.h"
#include "c-family/name-hint.h"
+#include "c-family/known-headers.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
@@ -3992,83 +3993,6 @@ lookup_name_in_scope (tree name, struct c_scope *scope)
return NULL_TREE;
}
-/* Subroutine of lookup_name_fuzzy for handling unrecognized names
- for some of the most common names within the C standard library.
- Given non-NULL NAME, return the header name defining it within the C
- standard library (with '<' and '>'), or NULL. */
-
-static const char *
-get_c_name_hint (const char *name)
-{
- struct std_name_hint
- {
- const char *name;
- const char *header;
- };
- static const std_name_hint hints[] = {
- /* <errno.h>. */
- {"errno", "<errno.h>"},
-
- /* <stdarg.h>. */
- {"va_list", "<stdarg.h>"},
-
- /* <stddef.h>. */
- {"NULL", "<stddef.h>"},
- {"ptrdiff_t", "<stddef.h>"},
- {"wchar_t", "<stddef.h>"},
- {"size_t", "<stddef.h>"},
-
- /* <stdio.h>. */
- {"BUFSIZ", "<stdio.h>"},
- {"EOF", "<stdio.h>"},
- {"FILE", "<stdio.h>"},
- {"FILENAME_MAX", "<stdio.h>"},
- {"fpos_t", "<stdio.h>"},
- {"stderr", "<stdio.h>"},
- {"stdin", "<stdio.h>"},
- {"stdout", "<stdio.h>"}
- };
- const size_t num_hints = sizeof (hints) / sizeof (hints[0]);
- for (size_t i = 0; i < num_hints; i++)
- {
- if (0 == strcmp (name, hints[i].name))
- return hints[i].header;
- }
- return NULL;
-}
-
-/* Subclass of deferred_diagnostic for suggesting to the user
- that they have missed a #include. */
-
-class suggest_missing_header : public deferred_diagnostic
-{
- public:
- suggest_missing_header (location_t loc, const char *name,
- const char *header_hint)
- : deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint)
- {
- gcc_assert (name);
- gcc_assert (header_hint);
- }
-
- ~suggest_missing_header ()
- {
- if (is_suppressed_p ())
- return;
-
- gcc_rich_location richloc (get_location ());
- maybe_add_include_fixit (&richloc, m_header_hint);
- inform (&richloc,
- "%qs is defined in header %qs;"
- " did you forget to %<#include %s%>?",
- m_name_str, m_header_hint, m_header_hint);
- }
-
- private:
- const char *m_name_str;
- const char *m_header_hint;
-};
-
/* Look for the closest match for NAME within the currently valid
scopes.
@@ -4094,7 +4018,9 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
/* First, try some well-known names in the C standard library, in case
the user forgot a #include. */
- const char *header_hint = get_c_name_hint (IDENTIFIER_POINTER (name));
+ const char *header_hint
+ = get_c_stdlib_header_for_name (IDENTIFIER_POINTER (name));
+
if (header_hint)
return name_hint (NULL,
new suggest_missing_header (loc,