1183409Snwhitehorn/* Support for suggestions about missing #include directives.
2183409Snwhitehorn   Copyright (C) 2017-2022 Free Software Foundation, Inc.
3183409Snwhitehorn
4183409SnwhitehornThis file is part of GCC.
5183409Snwhitehorn
6183409SnwhitehornGCC is free software; you can redistribute it and/or modify it under
7183409Snwhitehornthe terms of the GNU General Public License as published by the Free
8183409SnwhitehornSoftware Foundation; either version 3, or (at your option) any later
9183409Snwhitehornversion.
10183409Snwhitehorn
11183409SnwhitehornGCC is distributed in the hope that it will be useful, but WITHOUT ANY
12183409SnwhitehornWARRANTY; without even the implied warranty of MERCHANTABILITY or
13183409SnwhitehornFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14183409Snwhitehornfor more details.
15183409Snwhitehorn
16183409SnwhitehornYou should have received a copy of the GNU General Public License
17183409Snwhitehornalong with GCC; see the file COPYING3.  If not see
18183409Snwhitehorn<http://www.gnu.org/licenses/>.  */
19183409Snwhitehorn
20183409Snwhitehorn#include "config.h"
21183409Snwhitehorn#define INCLUDE_MEMORY
22183409Snwhitehorn#include "system.h"
23183409Snwhitehorn#include "coretypes.h"
24183409Snwhitehorn#include "c-family/c-common.h"
25183409Snwhitehorn#include "c-family/name-hint.h"
26183409Snwhitehorn#include "c-family/known-headers.h"
27183409Snwhitehorn#include "gcc-rich-location.h"
28183409Snwhitehorn
29183409Snwhitehorn/* An enum for distinguishing between the C and C++ stdlibs.  */
30183409Snwhitehorn
31183409Snwhitehornenum stdlib
32183409Snwhitehorn{
33183409Snwhitehorn  STDLIB_C,
34183409Snwhitehorn  STDLIB_CPLUSPLUS,
35183409Snwhitehorn
36183409Snwhitehorn  NUM_STDLIBS
37183409Snwhitehorn};
38183409Snwhitehorn
39183409Snwhitehorn/* A struct for associating names in a standard library with the header
40183409Snwhitehorn   that should be included to locate them, for each of the C and C++ stdlibs
41183409Snwhitehorn   (or NULL, for names that aren't in a header for a particular stdlib).  */
42183409Snwhitehorn
43183409Snwhitehornstruct stdlib_hint
44183409Snwhitehorn{
45183409Snwhitehorn  const char *name;
46183409Snwhitehorn  const char *header[NUM_STDLIBS];
47183409Snwhitehorn};
48183409Snwhitehorn
49183409Snwhitehorn/* Given non-NULL NAME, return the header name defining it (as literal
50183409Snwhitehorn   string) within either the standard library (with '<' and '>'), or
51183409Snwhitehorn   NULL.
52183409Snwhitehorn
53183409Snwhitehorn   Only handle string macros, so that this can be used for
54183409Snwhitehorn   get_stdlib_header_for_name and
55183409Snwhitehorn   get_c_stdlib_header_for_string_macro_name.  */
56183409Snwhitehorn
57183409Snwhitehornstatic const char *
58183409Snwhitehornget_string_macro_hint (const char *name, enum stdlib lib)
59183409Snwhitehorn{
60183409Snwhitehorn  /* <inttypes.h> and <cinttypes>.  */
61183409Snwhitehorn  static const char *c99_cxx11_macros[] =
62183409Snwhitehorn    { "PRId8", "PRId16", "PRId32", "PRId64",
63183409Snwhitehorn      "PRIi8", "PRIi16", "PRIi32", "PRIi64",
64183409Snwhitehorn      "PRIo8", "PRIo16", "PRIo32", "PRIo64",
65183409Snwhitehorn      "PRIu8", "PRIu16", "PRIu32", "PRIu64",
66183409Snwhitehorn      "PRIx8", "PRIx16", "PRIx32", "PRIx64",
67183409Snwhitehorn      "PRIX8", "PRIX16", "PRIX32", "PRIX64",
68183409Snwhitehorn
69183409Snwhitehorn      "PRIdPTR", "PRIiPTR", "PRIoPTR", "PRIuPTR", "PRIxPTR", "PRIXPTR",
70183409Snwhitehorn
71183409Snwhitehorn      "SCNd8", "SCNd16", "SCNd32", "SCNd64",
72183409Snwhitehorn      "SCNi8", "SCNi16", "SCNi32", "SCNi64",
73183409Snwhitehorn      "SCNo8", "SCNo16", "SCNo32", "SCNo64",
74183409Snwhitehorn      "SCNu8", "SCNu16", "SCNu32", "SCNu64",
75183409Snwhitehorn      "SCNx8", "SCNx16", "SCNx32", "SCNx64",
76183409Snwhitehorn
77183409Snwhitehorn      "SCNdPTR", "SCNiPTR", "SCNoPTR", "SCNuPTR", "SCNxPTR" };
78183409Snwhitehorn
79183409Snwhitehorn  if ((lib == STDLIB_C && flag_isoc99)
80183409Snwhitehorn      || (lib == STDLIB_CPLUSPLUS && cxx_dialect >= cxx11 ))
81183409Snwhitehorn    {
82183409Snwhitehorn      const size_t num_c99_cxx11_macros
83183409Snwhitehorn	= sizeof (c99_cxx11_macros) / sizeof (c99_cxx11_macros[0]);
84183409Snwhitehorn      for (size_t i = 0; i < num_c99_cxx11_macros; i++)
85183409Snwhitehorn	if (strcmp (name, c99_cxx11_macros[i]) == 0)
86183409Snwhitehorn	  return lib == STDLIB_C ? "<inttypes.h>" : "<cinttypes>";
87183409Snwhitehorn    }
88183409Snwhitehorn
89183409Snwhitehorn  return NULL;
90183409Snwhitehorn}
91183409Snwhitehorn
92183409Snwhitehorn/* Given non-NULL NAME, return the header name defining it within either
93183409Snwhitehorn   the standard library (with '<' and '>'), or NULL.
94183409Snwhitehorn   Only handles a subset of the most common names within the stdlibs.  */
95183409Snwhitehorn
96183409Snwhitehornstatic const char *
97183409Snwhitehornget_stdlib_header_for_name (const char *name, enum stdlib lib)
98183409Snwhitehorn{
99183409Snwhitehorn  gcc_assert (name);
100183409Snwhitehorn  gcc_assert (lib < NUM_STDLIBS);
101183409Snwhitehorn
102183409Snwhitehorn  static const stdlib_hint hints[] = {
103183409Snwhitehorn    /* <assert.h> and <cassert>.  */
104183409Snwhitehorn    {"assert", {"<assert.h>",  "<cassert>"} },
105183409Snwhitehorn
106183409Snwhitehorn    /* <errno.h> and <cerrno>.  */
107183409Snwhitehorn    {"errno", {"<errno.h>", "<cerrno>"} },
108183409Snwhitehorn
109183409Snwhitehorn    /* <limits.h> and <climits>.  */
110183409Snwhitehorn    {"CHAR_BIT", {"<limits.h>", "<climits>"} },
111183409Snwhitehorn    {"CHAR_MAX", {"<limits.h>", "<climits>"} },
112183409Snwhitehorn    {"CHAR_MIN", {"<limits.h>", "<climits>"} },
113183409Snwhitehorn    {"INT_MAX", {"<limits.h>", "<climits>"} },
114183409Snwhitehorn    {"INT_MIN", {"<limits.h>", "<climits>"} },
115183409Snwhitehorn    {"LLONG_MAX", {"<limits.h>", "<climits>"} },
116183409Snwhitehorn    {"LLONG_MIN", {"<limits.h>", "<climits>"} },
117183409Snwhitehorn    {"LONG_MAX", {"<limits.h>", "<climits>"} },
118183409Snwhitehorn    {"LONG_MIN", {"<limits.h>", "<climits>"} },
119183409Snwhitehorn    {"MB_LEN_MAX", {"<limits.h>", "<climits>"} },
120183409Snwhitehorn    {"SCHAR_MAX", {"<limits.h>", "<climits>"} },
121183409Snwhitehorn    {"SCHAR_MIN", {"<limits.h>", "<climits>"} },
122183409Snwhitehorn    {"SHRT_MAX", {"<limits.h>", "<climits>"} },
123183409Snwhitehorn    {"SHRT_MIN", {"<limits.h>", "<climits>"} },
124183409Snwhitehorn    {"UCHAR_MAX", {"<limits.h>", "<climits>"} },
125183409Snwhitehorn    {"UINT_MAX", {"<limits.h>", "<climits>"} },
126183409Snwhitehorn    {"ULLONG_MAX", {"<limits.h>", "<climits>"} },
127183409Snwhitehorn    {"ULONG_MAX", {"<limits.h>", "<climits>"} },
128183409Snwhitehorn    {"USHRT_MAX", {"<limits.h>", "<climits>"} },
129183409Snwhitehorn
130183409Snwhitehorn    /* <float.h> and <cfloat>.  */
131183409Snwhitehorn    {"DBL_MAX", {"<float.h>", "<cfloat>"} },
132183409Snwhitehorn    {"DBL_MIN", {"<float.h>", "<cfloat>"} },
133183409Snwhitehorn    {"FLT_MAX", {"<float.h>", "<cfloat>"} },
134183409Snwhitehorn    {"FLT_MIN", {"<float.h>", "<cfloat>"} },
135183409Snwhitehorn    {"LDBL_MAX", {"<float.h>", "<cfloat>"} },
136183409Snwhitehorn    {"LDBL_MIN", {"<float.h>", "<cfloat>"} },
137183409Snwhitehorn
138183409Snwhitehorn    /* <stdarg.h> and <cstdarg>.  */
139183409Snwhitehorn    {"va_list", {"<stdarg.h>", "<cstdarg>"} },
140183409Snwhitehorn
141183409Snwhitehorn    /* <stddef.h> and <cstddef>.  */
142183409Snwhitehorn    {"NULL", {"<stddef.h>", "<cstddef>"} },
143183409Snwhitehorn    {"nullptr_t", {NULL, "<cstddef>"} },
144183409Snwhitehorn    {"offsetof", {"<stddef.h>", "<cstddef>"} },
145183409Snwhitehorn    {"ptrdiff_t", {"<stddef.h>", "<cstddef>"} },
146183409Snwhitehorn    {"size_t", {"<stddef.h>", "<cstddef>"} },
147183409Snwhitehorn    {"wchar_t", {"<stddef.h>", NULL /* a keyword in C++ */} },
148183409Snwhitehorn
149183409Snwhitehorn    /* <stdio.h> and <cstdio>.  */
150183409Snwhitehorn    {"BUFSIZ", {"<stdio.h>", "<cstdio>"} },
151183409Snwhitehorn    {"EOF", {"<stdio.h>", "<cstdio>"} },
152183409Snwhitehorn    {"FILE", {"<stdio.h>", "<cstdio>"} },
153183409Snwhitehorn    {"FILENAME_MAX", {"<stdio.h>", "<cstdio>"} },
154183409Snwhitehorn    {"fopen", {"<stdio.h>", "<cstdio>"} },
155183409Snwhitehorn    {"fpos_t", {"<stdio.h>", "<cstdio>"} },
156183409Snwhitehorn    {"getchar", {"<stdio.h>", "<cstdio>"} },
157183409Snwhitehorn    {"printf", {"<stdio.h>", "<cstdio>"} },
158183409Snwhitehorn    {"snprintf", {"<stdio.h>", "<cstdio>"} },
159183409Snwhitehorn    {"sprintf", {"<stdio.h>", "<cstdio>"} },
160183409Snwhitehorn    {"stderr", {"<stdio.h>", "<cstdio>"} },
161183409Snwhitehorn    {"stdin", {"<stdio.h>", "<cstdio>"} },
162183409Snwhitehorn    {"stdout", {"<stdio.h>", "<cstdio>"} },
163183409Snwhitehorn
164183409Snwhitehorn    /* <stdlib.h> and <cstdlib>.  */
165183409Snwhitehorn    {"EXIT_FAILURE", {"<stdlib.h>", "<cstdlib>"} },
166183409Snwhitehorn    {"EXIT_SUCCESS", {"<stdlib.h>", "<cstdlib>"} },
167183409Snwhitehorn    {"abort", {"<stdlib.h>", "<cstdlib>"} },
168183409Snwhitehorn    {"atexit", {"<stdlib.h>", "<cstdlib>"} },
169183409Snwhitehorn    {"calloc", {"<stdlib.h>", "<cstdlib>"} },
170183409Snwhitehorn    {"exit", {"<stdlib.h>", "<cstdlib>"} },
171183409Snwhitehorn    {"free", {"<stdlib.h>", "<cstdlib>"} },
172183409Snwhitehorn    {"getenv", {"<stdlib.h>", "<cstdlib>"} },
173183409Snwhitehorn    {"malloc", {"<stdlib.h>", "<cstdlib>"} },
174183409Snwhitehorn    {"realloc", {"<stdlib.h>", "<cstdlib>"} },
175183409Snwhitehorn
176183409Snwhitehorn    /* <string.h> and <cstring>.  */
177183409Snwhitehorn    {"memchr", {"<string.h>", "<cstring>"} },
178183409Snwhitehorn    {"memcmp", {"<string.h>", "<cstring>"} },
179183409Snwhitehorn    {"memcpy", {"<string.h>", "<cstring>"} },
180183409Snwhitehorn    {"memmove", {"<string.h>", "<cstring>"} },
181183409Snwhitehorn    {"memset", {"<string.h>", "<cstring>"} },
182183409Snwhitehorn    {"strcat", {"<string.h>", "<cstring>"} },
183183409Snwhitehorn    {"strchr", {"<string.h>", "<cstring>"} },
184183409Snwhitehorn    {"strcmp", {"<string.h>", "<cstring>"} },
185183409Snwhitehorn    {"strcpy", {"<string.h>", "<cstring>"} },
186183409Snwhitehorn    {"strlen", {"<string.h>", "<cstring>"} },
187183409Snwhitehorn    {"strncat", {"<string.h>", "<cstring>"} },
188183409Snwhitehorn    {"strncmp", {"<string.h>", "<cstring>"} },
189183409Snwhitehorn    {"strncpy", {"<string.h>", "<cstring>"} },
190183409Snwhitehorn    {"strrchr", {"<string.h>", "<cstring>"} },
191183409Snwhitehorn    {"strspn", {"<string.h>", "<cstring>"} },
192183409Snwhitehorn    {"strstr", {"<string.h>", "<cstring>"} },
193183409Snwhitehorn
194183409Snwhitehorn    /* <stdint.h>.  */
195183409Snwhitehorn    {"PTRDIFF_MAX", {"<stdint.h>", "<cstdint>"} },
196183409Snwhitehorn    {"PTRDIFF_MIN", {"<stdint.h>", "<cstdint>"} },
197183409Snwhitehorn    {"SIG_ATOMIC_MAX", {"<stdint.h>", "<cstdint>"} },
198183409Snwhitehorn    {"SIG_ATOMIC_MIN", {"<stdint.h>", "<cstdint>"} },
199183409Snwhitehorn    {"SIZE_MAX", {"<stdint.h>", "<cstdint>"} },
200183409Snwhitehorn    {"WINT_MAX", {"<stdint.h>", "<cstdint>"} },
201183409Snwhitehorn    {"WINT_MIN", {"<stdint.h>", "<cstdint>"} },
202183409Snwhitehorn
203183409Snwhitehorn    /* <time.h>.  */
204183409Snwhitehorn    {"asctime", {"<time.h>", "<ctime>"} },
205183409Snwhitehorn    {"clock", {"<time.h>", "<ctime>"} },
206183409Snwhitehorn    {"clock_t", {"<time.h>", "<ctime>"} },
207183409Snwhitehorn    {"ctime", {"<time.h>", "<ctime>"} },
208183409Snwhitehorn    {"difftime", {"<time.h>", "<ctime>"} },
209183409Snwhitehorn    {"gmtime", {"<time.h>", "<ctime>"} },
210183409Snwhitehorn    {"localtime", {"<time.h>", "<ctime>"} },
211183409Snwhitehorn    {"mktime", {"<time.h>", "<ctime>"} },
212183409Snwhitehorn    {"strftime", {"<time.h>", "<ctime>"} },
213183409Snwhitehorn    {"time", {"<time.h>", "<ctime>"} },
214183409Snwhitehorn    {"time_t", {"<time.h>", "<ctime>"} },
215183409Snwhitehorn    {"tm", {"<time.h>", "<ctime>"} },
216183409Snwhitehorn
217183409Snwhitehorn    /* <wchar.h>.  */
218183409Snwhitehorn    {"WCHAR_MAX", {"<wchar.h>", "<cwchar>"} },
219183409Snwhitehorn    {"WCHAR_MIN", {"<wchar.h>", "<cwchar>"} }
220183409Snwhitehorn  };
221183409Snwhitehorn  const size_t num_hints = sizeof (hints) / sizeof (hints[0]);
222183409Snwhitehorn  for (size_t i = 0; i < num_hints; i++)
223183409Snwhitehorn    if (strcmp (name, hints[i].name) == 0)
224183409Snwhitehorn      return hints[i].header[lib];
225183409Snwhitehorn
226183409Snwhitehorn  static const stdlib_hint c99_cxx11_hints[] = {
227183409Snwhitehorn    /* <stdbool.h>.  Defined natively in C++.  */
228183409Snwhitehorn    {"bool", {"<stdbool.h>", NULL} },
229183409Snwhitehorn    {"true", {"<stdbool.h>", NULL} },
230183409Snwhitehorn    {"false", {"<stdbool.h>", NULL} },
231183409Snwhitehorn
232183409Snwhitehorn    /* <stdint.h> and <cstdint>.  */
233183409Snwhitehorn    {"int8_t", {"<stdint.h>", "<cstdint>"} },
234183409Snwhitehorn    {"uint8_t", {"<stdint.h>", "<cstdint>"} },
235183409Snwhitehorn    {"int16_t", {"<stdint.h>", "<cstdint>"} },
236183409Snwhitehorn    {"uint16_t", {"<stdint.h>", "<cstdint>"} },
237183409Snwhitehorn    {"int32_t", {"<stdint.h>", "<cstdint>"} },
238183409Snwhitehorn    {"uint32_t", {"<stdint.h>", "<cstdint>"} },
239183409Snwhitehorn    {"int64_t", {"<stdint.h>", "<cstdint>"} },
240183409Snwhitehorn    {"uint64_t", {"<stdint.h>", "<cstdint>"} },
241183409Snwhitehorn    {"intptr_t", {"<stdint.h>", "<cstdint>"} },
242183409Snwhitehorn    {"uintptr_t", {"<stdint.h>", "<cstdint>"} },
243183409Snwhitehorn    {"INT8_MAX", {"<stdint.h>", "<cstdint>"} },
244183409Snwhitehorn    {"INT16_MAX", {"<stdint.h>", "<cstdint>"} },
245183409Snwhitehorn    {"INT32_MAX", {"<stdint.h>", "<cstdint>"} },
246183409Snwhitehorn    {"INT64_MAX", {"<stdint.h>", "<cstdint>"} },
247183409Snwhitehorn    {"UINT8_MAX", {"<stdint.h>", "<cstdint>"} },
248183409Snwhitehorn    {"UINT16_MAX", {"<stdint.h>", "<cstdint>"} },
249183409Snwhitehorn    {"UINT32_MAX", {"<stdint.h>", "<cstdint>"} },
250183409Snwhitehorn    {"UINT64_MAX", {"<stdint.h>", "<cstdint>"} },
251183409Snwhitehorn    {"INTPTR_MAX", {"<stdint.h>", "<cstdint>"} },
252183409Snwhitehorn    {"UINTPTR_MAX", {"<stdint.h>", "<cstdint>"} }
253183409Snwhitehorn  };
254183409Snwhitehorn
255183409Snwhitehorn  const size_t num_c99_cxx11_hints = sizeof (c99_cxx11_hints)
256183409Snwhitehorn					     / sizeof (c99_cxx11_hints[0]);
257183409Snwhitehorn  if ((lib == STDLIB_C && flag_isoc99)
258183409Snwhitehorn      || (lib == STDLIB_CPLUSPLUS && cxx_dialect >= cxx11 ))
259183409Snwhitehorn    for (size_t i = 0; i < num_c99_cxx11_hints; i++)
260183409Snwhitehorn      if (strcmp (name, c99_cxx11_hints[i].name) == 0)
261183409Snwhitehorn	return c99_cxx11_hints[i].header[lib];
262183409Snwhitehorn
263183409Snwhitehorn  return get_string_macro_hint (name, lib);
264183409Snwhitehorn}
265183409Snwhitehorn
266183409Snwhitehorn/* Given non-NULL NAME, return the header name defining it within the C
267183409Snwhitehorn   standard library (with '<' and '>'), or NULL.  */
268183409Snwhitehorn
269183409Snwhitehornconst char *
270183409Snwhitehornget_c_stdlib_header_for_name (const char *name)
271183409Snwhitehorn{
272183409Snwhitehorn  return get_stdlib_header_for_name (name, STDLIB_C);
273183409Snwhitehorn}
274183409Snwhitehorn
275183409Snwhitehorn/* Given non-NULL NAME, return the header name defining it within the C++
276183409Snwhitehorn   standard library (with '<' and '>'), or NULL.  */
277183409Snwhitehorn
278183409Snwhitehornconst char *
279183409Snwhitehornget_cp_stdlib_header_for_name (const char *name)
280183409Snwhitehorn{
281183409Snwhitehorn  return get_stdlib_header_for_name (name, STDLIB_CPLUSPLUS);
282183409Snwhitehorn}
283
284/* Given non-NULL NAME, return the header name defining a string macro
285   within the C standard library (with '<' and '>'), or NULL.  */
286const char *
287get_c_stdlib_header_for_string_macro_name (const char *name)
288{
289  return get_string_macro_hint (name, STDLIB_C);
290}
291
292/* Given non-NULL NAME, return the header name defining a string macro
293   within the C++ standard library (with '<' and '>'), or NULL.  */
294const char *
295get_cp_stdlib_header_for_string_macro_name (const char *name)
296{
297  return get_string_macro_hint (name, STDLIB_CPLUSPLUS);
298}
299
300/* Implementation of class suggest_missing_header.  */
301
302/* suggest_missing_header's ctor.  */
303
304suggest_missing_header::suggest_missing_header (location_t loc,
305						const char *name,
306						const char *header_hint)
307: deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint)
308{
309  gcc_assert (name);
310  gcc_assert (header_hint);
311}
312
313/* suggest_missing_header's dtor.  */
314
315suggest_missing_header::~suggest_missing_header ()
316{
317  if (is_suppressed_p ())
318    return;
319
320  gcc_rich_location richloc (get_location ());
321  maybe_add_include_fixit (&richloc, m_header_hint, true);
322  inform (&richloc,
323	  "%qs is defined in header %qs;"
324	  " did you forget to %<#include %s%>?",
325	  m_name_str, m_header_hint, m_header_hint);
326}
327