1 /* Support for suggestions about missing #include directives.
2 Copyright (C) 2017-2024 Free Software Foundation, Inc.
4 This file is part of GCC.
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
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
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/>. */
21 #define INCLUDE_MEMORY
23 #include "coretypes.h"
24 #include "c-family/c-common.h"
25 #include "c-family/name-hint.h"
26 #include "c-family/known-headers.h"
27 #include "gcc-rich-location.h"
29 /* An enum for distinguishing between the C and C++ stdlibs. */
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). */
46 const char *header
[NUM_STDLIBS
];
49 /* Given non-NULL NAME, return the header name defining it (as literal
50 string) within either the standard library (with '<' and '>'), or
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. */
58 get_string_macro_hint (const char *name
, enum stdlib lib
)
60 /* <inttypes.h> and <cinttypes>. */
61 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",
69 "PRIdPTR", "PRIiPTR", "PRIoPTR", "PRIuPTR", "PRIxPTR", "PRIXPTR",
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",
77 "SCNdPTR", "SCNiPTR", "SCNoPTR", "SCNuPTR", "SCNxPTR" };
79 if ((lib
== STDLIB_C
&& flag_isoc99
)
80 || (lib
== STDLIB_CPLUSPLUS
&& cxx_dialect
>= cxx11
))
82 const size_t num_c99_cxx11_macros
= ARRAY_SIZE (c99_cxx11_macros
);
83 for (size_t i
= 0; i
< num_c99_cxx11_macros
; i
++)
84 if (strcmp (name
, c99_cxx11_macros
[i
]) == 0)
85 return lib
== STDLIB_C
? "<inttypes.h>" : "<cinttypes>";
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. */
96 get_stdlib_header_for_name (const char *name
, enum stdlib lib
)
99 gcc_assert (lib
< NUM_STDLIBS
);
101 static const stdlib_hint hints
[] = {
102 /* <assert.h> and <cassert>. */
103 {"assert", {"<assert.h>", "<cassert>"} },
105 /* <errno.h> and <cerrno>. */
106 {"errno", {"<errno.h>", "<cerrno>"} },
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>"} },
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>"} },
137 /* <stdarg.h> and <cstdarg>. */
138 {"va_list", {"<stdarg.h>", "<cstdarg>"} },
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++ */} },
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>"} },
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>"} },
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>"} },
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>"} },
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>"} },
218 {"WCHAR_MAX", {"<wchar.h>", "<cwchar>"} },
219 {"WCHAR_MIN", {"<wchar.h>", "<cwchar>"} }
221 const size_t num_hints
= ARRAY_SIZE (hints
);
222 for (size_t i
= 0; i
< num_hints
; i
++)
223 if (strcmp (name
, hints
[i
].name
) == 0)
224 return hints
[i
].header
[lib
];
226 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
} },
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>"} }
255 const size_t num_c99_cxx11_hints
= sizeof (c99_cxx11_hints
)
256 / sizeof (c99_cxx11_hints
[0]);
257 if ((lib
== STDLIB_C
&& flag_isoc99
)
258 || (lib
== STDLIB_CPLUSPLUS
&& cxx_dialect
>= cxx11
))
259 for (size_t i
= 0; i
< num_c99_cxx11_hints
; i
++)
260 if (strcmp (name
, c99_cxx11_hints
[i
].name
) == 0)
261 return c99_cxx11_hints
[i
].header
[lib
];
263 return get_string_macro_hint (name
, lib
);
266 /* Given non-NULL NAME, return the header name defining it within the C
267 standard library (with '<' and '>'), or NULL. */
270 get_c_stdlib_header_for_name (const char *name
)
272 return get_stdlib_header_for_name (name
, STDLIB_C
);
275 /* Given non-NULL NAME, return the header name defining it within the C++
276 standard library (with '<' and '>'), or NULL. */
279 get_cp_stdlib_header_for_name (const char *name
)
281 return get_stdlib_header_for_name (name
, STDLIB_CPLUSPLUS
);
284 /* Given non-NULL NAME, return the header name defining a string macro
285 within the C standard library (with '<' and '>'), or NULL. */
287 get_c_stdlib_header_for_string_macro_name (const char *name
)
289 return get_string_macro_hint (name
, STDLIB_C
);
292 /* Given non-NULL NAME, return the header name defining a string macro
293 within the C++ standard library (with '<' and '>'), or NULL. */
295 get_cp_stdlib_header_for_string_macro_name (const char *name
)
297 return get_string_macro_hint (name
, STDLIB_CPLUSPLUS
);
300 /* Implementation of class suggest_missing_header. */
302 /* suggest_missing_header's ctor. */
304 suggest_missing_header::suggest_missing_header (location_t loc
,
306 const char *header_hint
)
307 : deferred_diagnostic (loc
), m_name_str (name
), m_header_hint (header_hint
)
310 gcc_assert (header_hint
);
313 /* suggest_missing_header's dtor. */
315 suggest_missing_header::~suggest_missing_header ()
317 if (is_suppressed_p ())
320 gcc_rich_location
richloc (get_location ());
321 maybe_add_include_fixit (&richloc
, m_header_hint
, true);
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
);