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