Branch data Line data Source code
1 : : /* Support for suggestions about missing #include directives.
2 : : Copyright (C) 2017-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "c-family/c-common.h"
24 : : #include "c-family/name-hint.h"
25 : : #include "c-family/known-headers.h"
26 : : #include "gcc-rich-location.h"
27 : : #include "opts.h"
28 : :
29 : : /* An enum for distinguishing between the C and C++ stdlibs. */
30 : :
31 : : enum stdlib
32 : : {
33 : : STDLIB_C,
34 : : STDLIB_CPLUSPLUS,
35 : :
36 : : NUM_STDLIBS
37 : : };
38 : :
39 : : /* A struct for associating names in a standard library with the header
40 : : that should be included to locate them, for each of the C and C++ stdlibs
41 : : (or NULL, for names that aren't in a header for a particular stdlib). */
42 : :
43 : : struct stdlib_hint
44 : : {
45 : : const char *name;
46 : : const char *header[NUM_STDLIBS];
47 : : };
48 : :
49 : : /* Given non-NULL NAME, return the header name defining it (as literal
50 : : string) within either the standard library (with '<' and '>'), or
51 : : NULL.
52 : :
53 : : Only handle string macros, so that this can be used for
54 : : get_stdlib_header_for_name and
55 : : get_c_stdlib_header_for_string_macro_name. */
56 : :
57 : : static const char *
58 : 4050 : get_string_macro_hint (const char *name, enum stdlib lib)
59 : : {
60 : : /* <inttypes.h> and <cinttypes>. */
61 : 4050 : static const char *c99_cxx11_macros[] =
62 : : { "PRId8", "PRId16", "PRId32", "PRId64",
63 : : "PRIi8", "PRIi16", "PRIi32", "PRIi64",
64 : : "PRIo8", "PRIo16", "PRIo32", "PRIo64",
65 : : "PRIu8", "PRIu16", "PRIu32", "PRIu64",
66 : : "PRIx8", "PRIx16", "PRIx32", "PRIx64",
67 : : "PRIX8", "PRIX16", "PRIX32", "PRIX64",
68 : :
69 : : "PRIdPTR", "PRIiPTR", "PRIoPTR", "PRIuPTR", "PRIxPTR", "PRIXPTR",
70 : :
71 : : "SCNd8", "SCNd16", "SCNd32", "SCNd64",
72 : : "SCNi8", "SCNi16", "SCNi32", "SCNi64",
73 : : "SCNo8", "SCNo16", "SCNo32", "SCNo64",
74 : : "SCNu8", "SCNu16", "SCNu32", "SCNu64",
75 : : "SCNx8", "SCNx16", "SCNx32", "SCNx64",
76 : :
77 : : "SCNdPTR", "SCNiPTR", "SCNoPTR", "SCNuPTR", "SCNxPTR" };
78 : :
79 : 4050 : if ((lib == STDLIB_C && flag_isoc99)
80 : 1899 : || (lib == STDLIB_CPLUSPLUS && cxx_dialect >= cxx11 ))
81 : : {
82 : : const size_t num_c99_cxx11_macros = ARRAY_SIZE (c99_cxx11_macros);
83 : 194329 : for (size_t i = 0; i < num_c99_cxx11_macros; i++)
84 : 190879 : if (strcmp (name, c99_cxx11_macros[i]) == 0)
85 : 80 : return lib == STDLIB_C ? "<inttypes.h>" : "<cinttypes>";
86 : : }
87 : :
88 : : return NULL;
89 : : }
90 : :
91 : : /* Given non-NULL NAME, return the header name defining it within either
92 : : the standard library (with '<' and '>'), or NULL.
93 : : Only handles a subset of the most common names within the stdlibs. */
94 : :
95 : : static const char *
96 : 4293 : get_stdlib_header_for_name (const char *name, enum stdlib lib)
97 : : {
98 : 4293 : gcc_assert (name);
99 : 4293 : gcc_assert (lib < NUM_STDLIBS);
100 : :
101 : : static const stdlib_hint hints[] = {
102 : : /* <assert.h> and <cassert>. */
103 : : {"assert", {"<assert.h>", "<cassert>"} },
104 : :
105 : : /* <errno.h> and <cerrno>. */
106 : : {"errno", {"<errno.h>", "<cerrno>"} },
107 : :
108 : : /* <limits.h> and <climits>. */
109 : : {"CHAR_BIT", {"<limits.h>", "<climits>"} },
110 : : {"CHAR_MAX", {"<limits.h>", "<climits>"} },
111 : : {"CHAR_MIN", {"<limits.h>", "<climits>"} },
112 : : {"INT_MAX", {"<limits.h>", "<climits>"} },
113 : : {"INT_MIN", {"<limits.h>", "<climits>"} },
114 : : {"LLONG_MAX", {"<limits.h>", "<climits>"} },
115 : : {"LLONG_MIN", {"<limits.h>", "<climits>"} },
116 : : {"LONG_MAX", {"<limits.h>", "<climits>"} },
117 : : {"LONG_MIN", {"<limits.h>", "<climits>"} },
118 : : {"MB_LEN_MAX", {"<limits.h>", "<climits>"} },
119 : : {"SCHAR_MAX", {"<limits.h>", "<climits>"} },
120 : : {"SCHAR_MIN", {"<limits.h>", "<climits>"} },
121 : : {"SHRT_MAX", {"<limits.h>", "<climits>"} },
122 : : {"SHRT_MIN", {"<limits.h>", "<climits>"} },
123 : : {"UCHAR_MAX", {"<limits.h>", "<climits>"} },
124 : : {"UINT_MAX", {"<limits.h>", "<climits>"} },
125 : : {"ULLONG_MAX", {"<limits.h>", "<climits>"} },
126 : : {"ULONG_MAX", {"<limits.h>", "<climits>"} },
127 : : {"USHRT_MAX", {"<limits.h>", "<climits>"} },
128 : :
129 : : /* <float.h> and <cfloat>. */
130 : : {"DBL_MAX", {"<float.h>", "<cfloat>"} },
131 : : {"DBL_MIN", {"<float.h>", "<cfloat>"} },
132 : : {"FLT_MAX", {"<float.h>", "<cfloat>"} },
133 : : {"FLT_MIN", {"<float.h>", "<cfloat>"} },
134 : : {"LDBL_MAX", {"<float.h>", "<cfloat>"} },
135 : : {"LDBL_MIN", {"<float.h>", "<cfloat>"} },
136 : :
137 : : /* <stdarg.h> and <cstdarg>. */
138 : : {"va_list", {"<stdarg.h>", "<cstdarg>"} },
139 : :
140 : : /* <stddef.h> and <cstddef>. */
141 : : {"NULL", {"<stddef.h>", "<cstddef>"} },
142 : : {"nullptr_t", {NULL, "<cstddef>"} },
143 : : {"offsetof", {"<stddef.h>", "<cstddef>"} },
144 : : {"ptrdiff_t", {"<stddef.h>", "<cstddef>"} },
145 : : {"size_t", {"<stddef.h>", "<cstddef>"} },
146 : : {"wchar_t", {"<stddef.h>", NULL /* a keyword in C++ */} },
147 : :
148 : : /* <stdio.h> and <cstdio>. */
149 : : {"BUFSIZ", {"<stdio.h>", "<cstdio>"} },
150 : : {"EOF", {"<stdio.h>", "<cstdio>"} },
151 : : {"FILE", {"<stdio.h>", "<cstdio>"} },
152 : : {"FILENAME_MAX", {"<stdio.h>", "<cstdio>"} },
153 : : {"fopen", {"<stdio.h>", "<cstdio>"} },
154 : : {"fpos_t", {"<stdio.h>", "<cstdio>"} },
155 : : {"getchar", {"<stdio.h>", "<cstdio>"} },
156 : : {"printf", {"<stdio.h>", "<cstdio>"} },
157 : : {"snprintf", {"<stdio.h>", "<cstdio>"} },
158 : : {"sprintf", {"<stdio.h>", "<cstdio>"} },
159 : : {"stderr", {"<stdio.h>", "<cstdio>"} },
160 : : {"stdin", {"<stdio.h>", "<cstdio>"} },
161 : : {"stdout", {"<stdio.h>", "<cstdio>"} },
162 : :
163 : : /* <stdlib.h> and <cstdlib>. */
164 : : {"EXIT_FAILURE", {"<stdlib.h>", "<cstdlib>"} },
165 : : {"EXIT_SUCCESS", {"<stdlib.h>", "<cstdlib>"} },
166 : : {"abort", {"<stdlib.h>", "<cstdlib>"} },
167 : : {"atexit", {"<stdlib.h>", "<cstdlib>"} },
168 : : {"calloc", {"<stdlib.h>", "<cstdlib>"} },
169 : : {"exit", {"<stdlib.h>", "<cstdlib>"} },
170 : : {"free", {"<stdlib.h>", "<cstdlib>"} },
171 : : {"getenv", {"<stdlib.h>", "<cstdlib>"} },
172 : : {"malloc", {"<stdlib.h>", "<cstdlib>"} },
173 : : {"realloc", {"<stdlib.h>", "<cstdlib>"} },
174 : :
175 : : /* <string.h> and <cstring>. */
176 : : {"memchr", {"<string.h>", "<cstring>"} },
177 : : {"memcmp", {"<string.h>", "<cstring>"} },
178 : : {"memcpy", {"<string.h>", "<cstring>"} },
179 : : {"memmove", {"<string.h>", "<cstring>"} },
180 : : {"memset", {"<string.h>", "<cstring>"} },
181 : : {"strcat", {"<string.h>", "<cstring>"} },
182 : : {"strchr", {"<string.h>", "<cstring>"} },
183 : : {"strcmp", {"<string.h>", "<cstring>"} },
184 : : {"strcpy", {"<string.h>", "<cstring>"} },
185 : : {"strerror", {"<string.h>", "<cstring>"} },
186 : : {"strlen", {"<string.h>", "<cstring>"} },
187 : : {"strncat", {"<string.h>", "<cstring>"} },
188 : : {"strncmp", {"<string.h>", "<cstring>"} },
189 : : {"strncpy", {"<string.h>", "<cstring>"} },
190 : : {"strrchr", {"<string.h>", "<cstring>"} },
191 : : {"strspn", {"<string.h>", "<cstring>"} },
192 : : {"strstr", {"<string.h>", "<cstring>"} },
193 : :
194 : : /* <stdint.h>. */
195 : : {"PTRDIFF_MAX", {"<stdint.h>", "<cstdint>"} },
196 : : {"PTRDIFF_MIN", {"<stdint.h>", "<cstdint>"} },
197 : : {"SIG_ATOMIC_MAX", {"<stdint.h>", "<cstdint>"} },
198 : : {"SIG_ATOMIC_MIN", {"<stdint.h>", "<cstdint>"} },
199 : : {"SIZE_MAX", {"<stdint.h>", "<cstdint>"} },
200 : : {"WINT_MAX", {"<stdint.h>", "<cstdint>"} },
201 : : {"WINT_MIN", {"<stdint.h>", "<cstdint>"} },
202 : :
203 : : /* <time.h>. */
204 : : {"asctime", {"<time.h>", "<ctime>"} },
205 : : {"clock", {"<time.h>", "<ctime>"} },
206 : : {"clock_t", {"<time.h>", "<ctime>"} },
207 : : {"ctime", {"<time.h>", "<ctime>"} },
208 : : {"difftime", {"<time.h>", "<ctime>"} },
209 : : {"gmtime", {"<time.h>", "<ctime>"} },
210 : : {"localtime", {"<time.h>", "<ctime>"} },
211 : : {"mktime", {"<time.h>", "<ctime>"} },
212 : : {"strftime", {"<time.h>", "<ctime>"} },
213 : : {"time", {"<time.h>", "<ctime>"} },
214 : : {"time_t", {"<time.h>", "<ctime>"} },
215 : : {"tm", {"<time.h>", "<ctime>"} },
216 : :
217 : : /* <wchar.h>. */
218 : : {"WCHAR_MAX", {"<wchar.h>", "<cwchar>"} },
219 : : {"WCHAR_MIN", {"<wchar.h>", "<cwchar>"} }
220 : : };
221 : : const size_t num_hints = ARRAY_SIZE (hints);
222 : 402356 : for (size_t i = 0; i < num_hints; i++)
223 : 398296 : if (strcmp (name, hints[i].name) == 0)
224 : 233 : return hints[i].header[lib];
225 : :
226 : 4060 : static const stdlib_hint c99_cxx11_hints[] = {
227 : : /* <stdbool.h>. Defined natively in C++. */
228 : : {"bool", {"<stdbool.h>", NULL} },
229 : : {"true", {"<stdbool.h>", NULL} },
230 : : {"false", {"<stdbool.h>", NULL} },
231 : :
232 : : /* <stdint.h> and <cstdint>. */
233 : : {"int8_t", {"<stdint.h>", "<cstdint>"} },
234 : : {"uint8_t", {"<stdint.h>", "<cstdint>"} },
235 : : {"int16_t", {"<stdint.h>", "<cstdint>"} },
236 : : {"uint16_t", {"<stdint.h>", "<cstdint>"} },
237 : : {"int32_t", {"<stdint.h>", "<cstdint>"} },
238 : : {"uint32_t", {"<stdint.h>", "<cstdint>"} },
239 : : {"int64_t", {"<stdint.h>", "<cstdint>"} },
240 : : {"uint64_t", {"<stdint.h>", "<cstdint>"} },
241 : : {"intptr_t", {"<stdint.h>", "<cstdint>"} },
242 : : {"uintptr_t", {"<stdint.h>", "<cstdint>"} },
243 : : {"INT8_MAX", {"<stdint.h>", "<cstdint>"} },
244 : : {"INT16_MAX", {"<stdint.h>", "<cstdint>"} },
245 : : {"INT32_MAX", {"<stdint.h>", "<cstdint>"} },
246 : : {"INT64_MAX", {"<stdint.h>", "<cstdint>"} },
247 : : {"UINT8_MAX", {"<stdint.h>", "<cstdint>"} },
248 : : {"UINT16_MAX", {"<stdint.h>", "<cstdint>"} },
249 : : {"UINT32_MAX", {"<stdint.h>", "<cstdint>"} },
250 : : {"UINT64_MAX", {"<stdint.h>", "<cstdint>"} },
251 : : {"INTPTR_MAX", {"<stdint.h>", "<cstdint>"} },
252 : : {"UINTPTR_MAX", {"<stdint.h>", "<cstdint>"} }
253 : : };
254 : :
255 : 4060 : const size_t num_c99_cxx11_hints = sizeof (c99_cxx11_hints)
256 : : / sizeof (c99_cxx11_hints[0]);
257 : 4060 : if ((lib == STDLIB_C && flag_isoc99)
258 : 1902 : || (lib == STDLIB_CPLUSPLUS && cxx_dialect >= cxx11 ))
259 : 83874 : for (size_t i = 0; i < num_c99_cxx11_hints; i++)
260 : 80403 : if (strcmp (name, c99_cxx11_hints[i].name) == 0)
261 : 45 : return c99_cxx11_hints[i].header[lib];
262 : :
263 : 4015 : return get_string_macro_hint (name, lib);
264 : : }
265 : :
266 : : /* Given non-NULL NAME, return the header name defining it within the C
267 : : standard library (with '<' and '>'), or NULL. */
268 : :
269 : : const char *
270 : 2287 : get_c_stdlib_header_for_name (const char *name)
271 : : {
272 : 2287 : return get_stdlib_header_for_name (name, STDLIB_C);
273 : : }
274 : :
275 : : /* Given non-NULL NAME, return the header name defining it within the C++
276 : : standard library (with '<' and '>'), or NULL. */
277 : :
278 : : const char *
279 : 2006 : get_cp_stdlib_header_for_name (const char *name)
280 : : {
281 : 2006 : return get_stdlib_header_for_name (name, STDLIB_CPLUSPLUS);
282 : : }
283 : :
284 : : /* Given non-NULL NAME, return the header name defining a string macro
285 : : within the C standard library (with '<' and '>'), or NULL. */
286 : : const char *
287 : 16 : get_c_stdlib_header_for_string_macro_name (const char *name)
288 : : {
289 : 16 : 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. */
294 : : const char *
295 : 19 : get_cp_stdlib_header_for_string_macro_name (const char *name)
296 : : {
297 : 19 : 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 : :
304 : 331 : suggest_missing_header::suggest_missing_header (location_t loc,
305 : : const char *name,
306 : 331 : const char *header_hint)
307 : 331 : : deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint)
308 : : {
309 : 331 : gcc_assert (name);
310 : 331 : gcc_assert (header_hint);
311 : 331 : }
312 : :
313 : : /* suggest_missing_header's dtor. */
314 : :
315 : 662 : suggest_missing_header::~suggest_missing_header ()
316 : : {
317 : 331 : if (is_suppressed_p ())
318 : 0 : return;
319 : :
320 : 331 : gcc_rich_location richloc (get_location ());
321 : 331 : maybe_add_include_fixit (&richloc, m_header_hint, true);
322 : 331 : inform (&richloc,
323 : : "%qs is defined in header %qs;"
324 : : " this is probably fixable by adding %<#include %s%>",
325 : : m_name_str, m_header_hint, m_header_hint);
326 : 662 : }
327 : :
328 : : /* Implementation of class suggest_missing_option. */
329 : :
330 : : /* suggest_missing_option's ctor. */
331 : :
332 : 8 : suggest_missing_option::suggest_missing_option (location_t loc,
333 : : const char *macro_name,
334 : 8 : diagnostic_option_id option_id)
335 : 8 : : deferred_diagnostic (loc), m_name_str (macro_name), m_option_id (option_id)
336 : : {
337 : 8 : gcc_assert (macro_name);
338 : 8 : gcc_assert (option_id.m_idx > 0);
339 : 8 : }
340 : :
341 : : /* suggest_missing_option's dtor. */
342 : :
343 : 16 : suggest_missing_option::~suggest_missing_option ()
344 : : {
345 : 8 : if (is_suppressed_p ())
346 : 0 : return;
347 : :
348 : 8 : const char *option_name = cl_options[m_option_id.m_idx].opt_text;
349 : 8 : inform (get_location (),
350 : : "%qs is defined when using option %qs;"
351 : : " this is probably fixable by adding %qs to the command-line options",
352 : : m_name_str, option_name, option_name);
353 : 16 : }
|