1 /* Support for suggestions about missing #include directives. 2 Copyright (C) 2017-2020 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 #define INCLUDE_UNIQUE_PTR 22 #include "system.h" 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" 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 within either 50 the standard library (with '<' and '>'), or NULL. 51 Only handles a subset of the most common names within the stdlibs. */ 52 53 static const char * 54 get_stdlib_header_for_name (const char *name, enum stdlib lib) 55 { 56 gcc_assert (name); 57 gcc_assert (lib < NUM_STDLIBS); 58 59 static const stdlib_hint hints[] = { 60 /* <assert.h> and <cassert>. */ 61 {"assert", {"<assert.h>", "<cassert>"} }, 62 63 /* <errno.h> and <cerrno>. */ 64 {"errno", {"<errno.h>", "<cerrno>"} }, 65 66 /* <limits.h> and <climits>. */ 67 {"CHAR_BIT", {"<limits.h>", "<climits>"} }, 68 {"CHAR_MAX", {"<limits.h>", "<climits>"} }, 69 {"CHAR_MIN", {"<limits.h>", "<climits>"} }, 70 {"INT_MAX", {"<limits.h>", "<climits>"} }, 71 {"INT_MIN", {"<limits.h>", "<climits>"} }, 72 {"LLONG_MAX", {"<limits.h>", "<climits>"} }, 73 {"LLONG_MIN", {"<limits.h>", "<climits>"} }, 74 {"LONG_MAX", {"<limits.h>", "<climits>"} }, 75 {"LONG_MIN", {"<limits.h>", "<climits>"} }, 76 {"MB_LEN_MAX", {"<limits.h>", "<climits>"} }, 77 {"SCHAR_MAX", {"<limits.h>", "<climits>"} }, 78 {"SCHAR_MIN", {"<limits.h>", "<climits>"} }, 79 {"SHRT_MAX", {"<limits.h>", "<climits>"} }, 80 {"SHRT_MIN", {"<limits.h>", "<climits>"} }, 81 {"UCHAR_MAX", {"<limits.h>", "<climits>"} }, 82 {"UINT_MAX", {"<limits.h>", "<climits>"} }, 83 {"ULLONG_MAX", {"<limits.h>", "<climits>"} }, 84 {"ULONG_MAX", {"<limits.h>", "<climits>"} }, 85 {"USHRT_MAX", {"<limits.h>", "<climits>"} }, 86 87 /* <float.h> and <cfloat>. */ 88 {"DBL_MAX", {"<float.h>", "<cfloat>"} }, 89 {"DBL_MIN", {"<float.h>", "<cfloat>"} }, 90 {"FLT_MAX", {"<float.h>", "<cfloat>"} }, 91 {"FLT_MIN", {"<float.h>", "<cfloat>"} }, 92 {"LDBL_MAX", {"<float.h>", "<cfloat>"} }, 93 {"LDBL_MIN", {"<float.h>", "<cfloat>"} }, 94 95 /* <stdarg.h> and <cstdarg>. */ 96 {"va_list", {"<stdarg.h>", "<cstdarg>"} }, 97 98 /* <stddef.h> and <cstddef>. */ 99 {"NULL", {"<stddef.h>", "<cstddef>"} }, 100 {"nullptr_t", {NULL, "<cstddef>"} }, 101 {"offsetof", {"<stddef.h>", "<cstddef>"} }, 102 {"ptrdiff_t", {"<stddef.h>", "<cstddef>"} }, 103 {"size_t", {"<stddef.h>", "<cstddef>"} }, 104 {"wchar_t", {"<stddef.h>", NULL /* a keyword in C++ */} }, 105 106 /* <stdio.h> and <cstdio>. */ 107 {"BUFSIZ", {"<stdio.h>", "<cstdio>"} }, 108 {"EOF", {"<stdio.h>", "<cstdio>"} }, 109 {"FILE", {"<stdio.h>", "<cstdio>"} }, 110 {"FILENAME_MAX", {"<stdio.h>", "<cstdio>"} }, 111 {"fopen", {"<stdio.h>", "<cstdio>"} }, 112 {"fpos_t", {"<stdio.h>", "<cstdio>"} }, 113 {"getchar", {"<stdio.h>", "<cstdio>"} }, 114 {"printf", {"<stdio.h>", "<cstdio>"} }, 115 {"snprintf", {"<stdio.h>", "<cstdio>"} }, 116 {"sprintf", {"<stdio.h>", "<cstdio>"} }, 117 {"stderr", {"<stdio.h>", "<cstdio>"} }, 118 {"stdin", {"<stdio.h>", "<cstdio>"} }, 119 {"stdout", {"<stdio.h>", "<cstdio>"} }, 120 121 /* <stdlib.h> and <cstdlib>. */ 122 {"free", {"<stdlib.h>", "<cstdlib>"} }, 123 {"malloc", {"<stdlib.h>", "<cstdlib>"} }, 124 {"realloc", {"<stdlib.h>", "<cstdlib>"} }, 125 126 /* <string.h> and <cstring>. */ 127 {"memchr", {"<string.h>", "<cstring>"} }, 128 {"memcmp", {"<string.h>", "<cstring>"} }, 129 {"memcpy", {"<string.h>", "<cstring>"} }, 130 {"memmove", {"<string.h>", "<cstring>"} }, 131 {"memset", {"<string.h>", "<cstring>"} }, 132 {"strcat", {"<string.h>", "<cstring>"} }, 133 {"strchr", {"<string.h>", "<cstring>"} }, 134 {"strcmp", {"<string.h>", "<cstring>"} }, 135 {"strcpy", {"<string.h>", "<cstring>"} }, 136 {"strlen", {"<string.h>", "<cstring>"} }, 137 {"strncat", {"<string.h>", "<cstring>"} }, 138 {"strncmp", {"<string.h>", "<cstring>"} }, 139 {"strncpy", {"<string.h>", "<cstring>"} }, 140 {"strrchr", {"<string.h>", "<cstring>"} }, 141 {"strspn", {"<string.h>", "<cstring>"} }, 142 {"strstr", {"<string.h>", "<cstring>"} }, 143 144 /* <stdint.h>. */ 145 {"PTRDIFF_MAX", {"<stdint.h>", "<cstdint>"} }, 146 {"PTRDIFF_MIN", {"<stdint.h>", "<cstdint>"} }, 147 {"SIG_ATOMIC_MAX", {"<stdint.h>", "<cstdint>"} }, 148 {"SIG_ATOMIC_MIN", {"<stdint.h>", "<cstdint>"} }, 149 {"SIZE_MAX", {"<stdint.h>", "<cstdint>"} }, 150 {"WINT_MAX", {"<stdint.h>", "<cstdint>"} }, 151 {"WINT_MIN", {"<stdint.h>", "<cstdint>"} }, 152 153 /* <wchar.h>. */ 154 {"WCHAR_MAX", {"<wchar.h>", "<cwchar>"} }, 155 {"WCHAR_MIN", {"<wchar.h>", "<cwchar>"} } 156 }; 157 const size_t num_hints = sizeof (hints) / sizeof (hints[0]); 158 for (size_t i = 0; i < num_hints; i++) 159 if (strcmp (name, hints[i].name) == 0) 160 return hints[i].header[lib]; 161 return NULL; 162 } 163 164 /* Given non-NULL NAME, return the header name defining it within the C 165 standard library (with '<' and '>'), or NULL. */ 166 167 const char * 168 get_c_stdlib_header_for_name (const char *name) 169 { 170 return get_stdlib_header_for_name (name, STDLIB_C); 171 } 172 173 /* Given non-NULL NAME, return the header name defining it within the C++ 174 standard library (with '<' and '>'), or NULL. */ 175 176 const char * 177 get_cp_stdlib_header_for_name (const char *name) 178 { 179 return get_stdlib_header_for_name (name, STDLIB_CPLUSPLUS); 180 } 181 182 /* Implementation of class suggest_missing_header. */ 183 184 /* suggest_missing_header's ctor. */ 185 186 suggest_missing_header::suggest_missing_header (location_t loc, 187 const char *name, 188 const char *header_hint) 189 : deferred_diagnostic (loc), m_name_str (name), m_header_hint (header_hint) 190 { 191 gcc_assert (name); 192 gcc_assert (header_hint); 193 } 194 195 /* suggest_missing_header's dtor. */ 196 197 suggest_missing_header::~suggest_missing_header () 198 { 199 if (is_suppressed_p ()) 200 return; 201 202 gcc_rich_location richloc (get_location ()); 203 maybe_add_include_fixit (&richloc, m_header_hint, true); 204 inform (&richloc, 205 "%qs is defined in header %qs;" 206 " did you forget to %<#include %s%>?", 207 m_name_str, m_header_hint, m_header_hint); 208 } 209