iwyu-0.16-u3.patch (92422B)
1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml 2 index 1f06014..dce8632 100644 3 --- a/.github/workflows/ci.yml 4 +++ b/.github/workflows/ci.yml 5 @@ -15,7 +15,7 @@ jobs: 6 fail-fast: false 7 8 env: 9 - LLVM_TAG: -12 10 + LLVM_TAG: 11 12 steps: 13 - name: Install prerequisites 14 @@ -33,6 +33,10 @@ jobs: 15 sudo apt install -y libclang$LLVM_TAG-dev 16 sudo apt install -y clang$LLVM_TAG 17 18 + - name: Broken packaging workaround 19 + run: | 20 + sudo touch /usr/lib/llvm-14/lib/libclang-14.so.14.0.0 21 + 22 - name: Check out default branch 23 uses: actions/checkout@v2 24 25 diff --git a/CMakeLists.txt b/CMakeLists.txt 26 index 923b4d9..0a0d683 100644 27 --- a/CMakeLists.txt 28 +++ b/CMakeLists.txt 29 @@ -68,9 +68,9 @@ endif() 30 set(LLVM_LINK_COMPONENTS 31 Option 32 Support 33 - X86AsmParser 34 - X86Desc 35 - X86Info 36 + AllTargetsAsmParsers 37 + AllTargetsDescs 38 + AllTargetsInfos 39 ) 40 41 add_llvm_executable(include-what-you-use 42 @@ -110,8 +110,8 @@ if (MSVC) 43 -D_HAS_EXCEPTIONS=0 44 ) 45 46 - # Enable bigobj support and sane C++ exception semantics. 47 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /EHsc") 48 + # Enable bigobj support 49 + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") 50 endif() 51 52 # Link dynamically or statically depending on user preference. 53 diff --git a/README.md b/README.md 54 index 58abdc7..0ef3082 100644 55 --- a/README.md 56 +++ b/README.md 57 @@ -40,6 +40,7 @@ We assume you already have compiled LLVM and Clang libraries on your system, eit 58 | 9 | 0.13 | `clang_9.0` | 59 | 10 | 0.14 | `clang_10` | 60 | 11 | 0.15 | `clang_11` | 61 +| 12 | 0.16 | `clang_12` | 62 | ... | ... | ... | 63 | main | | `master` | 64 65 @@ -142,7 +143,7 @@ Note that with Microsoft's Visual C++ compiler, IWYU needs the `--driver-mode=cl 66 67 #### Using with a compilation database #### 68 69 -The `iwyu_tool.py` script predates the native CMake support, and works off the [compilation database format](https://clang.llvm.org/docs/JSONCompilationDatabase.html). For example, CMake generates such a database named `compile_commands.json` with the `CMAKE_EXPORT_COMPILE_COMMANDS` option enabled. 70 +The `iwyu_tool.py` script pre-dates the native CMake support, and works off the [compilation database format](https://clang.llvm.org/docs/JSONCompilationDatabase.html). For example, CMake generates such a database named `compile_commands.json` with the `CMAKE_EXPORT_COMPILE_COMMANDS` option enabled. 71 72 The script's command-line syntax is designed to mimic Clang's LibTooling, but they are otherwise unrelated. It can be used like this: 73 74 diff --git a/fix_includes.py b/fix_includes.py 75 index 7600361..8de5775 100755 76 --- a/fix_includes.py 77 +++ b/fix_includes.py 78 @@ -2309,11 +2309,12 @@ def ProcessIWYUOutput(f, files_to_process, flags, cwd): 79 # seen for them. (We have to wait until we're all done, since a .h 80 # file may have a contentful change when #included from one .cc 81 # file, but not another, and we need to have merged them above.) 82 - for filename in iwyu_output_records: 83 - if not iwyu_output_records[filename].HasContentfulChanges(): 84 - print('(skipping %s: iwyu reports no contentful changes)' % filename) 85 - # Mark that we're skipping this file by setting the record to None 86 - iwyu_output_records[filename] = None 87 + if not flags.update_comments: 88 + for filename in iwyu_output_records: 89 + if not iwyu_output_records[filename].HasContentfulChanges(): 90 + print('(skipping %s: iwyu reports no contentful changes)' % filename) 91 + # Mark that we're skipping this file by setting the record to None 92 + iwyu_output_records[filename] = None 93 94 # Now do all the fixing, and return the number of files modified 95 contentful_records = [ior for ior in iwyu_output_records.values() if ior] 96 @@ -2373,6 +2374,12 @@ def main(argv): 97 help='Put comments after the #include lines') 98 parser.add_option('--nocomments', action='store_false', dest='comments') 99 100 + parser.add_option('--update_comments', action='store_true', default=False, 101 + help=('Update #include comments, even if no #include lines' 102 + ' are added or removed')) 103 + parser.add_option('--noupdate_comments', action='store_false', 104 + dest='update_comments') 105 + 106 parser.add_option('--safe_headers', action='store_true', default=True, 107 help=('Do not remove unused #includes/fwd-declares from' 108 ' header files; just add new ones [default]')) 109 @@ -2440,6 +2447,9 @@ def main(argv): 110 not flags.separate_project_includes.endswith('/')): 111 flags.separate_project_includes += os.path.sep 112 113 + if flags.update_comments: 114 + flags.comments = True 115 + 116 if flags.sort_only: 117 if not files_to_modify: 118 sys.exit('FATAL ERROR: -s flag requires a list of filenames') 119 diff --git a/fix_includes_test.py b/fix_includes_test.py 120 index 380da54..07bd78d 100755 121 --- a/fix_includes_test.py 122 +++ b/fix_includes_test.py 123 @@ -34,6 +34,7 @@ class FakeFlags(object): 124 def __init__(self): 125 self.blank_lines = False 126 self.comments = True 127 + self.update_comments = False 128 self.dry_run = False 129 self.ignore_re = None 130 self.only_re = None 131 @@ -1916,6 +1917,54 @@ The full include-list for subdir/include_comments.cc: 132 self.RegisterFileContents({'subdir/include_comments.cc': infile}) 133 self.ProcessAndTest(iwyu_output) 134 135 + def testUpdateCommentsFlag(self): 136 + """Tests we update comments with --update_comments.""" 137 + self.flags.update_comments = True 138 + infile = """\ 139 +#include "must_keep.h" // IWYU pragma: keep 140 +#include "used.h" // for SomethingElse ///- 141 +///+#include "used.h" // for Used 142 + 143 +Used used; 144 +int main() { return 0; } 145 +""" 146 + iwyu_output = """\ 147 +subdir/include_comments.cc should add these lines: 148 + 149 +subdir/include_comments.cc should remove these lines: 150 + 151 +The full include-list for subdir/include_comments.cc: 152 +#include "must_keep.h" 153 +#include "used.h" // for Used 154 +--- 155 +""" 156 + self.RegisterFileContents({'subdir/include_comments.cc': infile}) 157 + self.ProcessAndTest(iwyu_output) 158 + 159 + def testNoUpdateCommentsFlag(self): 160 + """Tests we don't update comments with --noupdate_comments.""" 161 + self.flags.update_comments = False 162 + infile = """\ 163 +#include "must_keep.h" // IWYU pragma: keep 164 +#include "used.h" // for SomethingElse 165 + 166 +Used used; 167 +int main() { return 0; } 168 +""" 169 + iwyu_output = """\ 170 +subdir/include_comments.cc should add these lines: 171 + 172 +subdir/include_comments.cc should remove these lines: 173 + 174 +The full include-list for subdir/include_comments.cc: 175 +#include "must_keep.h" 176 +#include "used.h" // for Used 177 +--- 178 +""" 179 + self.RegisterFileContents({'subdir/include_comments.cc': infile}) 180 + self.ProcessAndTest(iwyu_output, 181 + unedited_files=['subdir/include_comments.cc']) 182 + 183 def testFixingTwoFiles(self): 184 """Make sure data for one fix doesn't overlap with a second.""" 185 file_a = """\ 186 diff --git a/gcc.symbols.imp b/gcc.symbols.imp 187 index 5ecf219..de38147 100644 188 --- a/gcc.symbols.imp 189 +++ b/gcc.symbols.imp 190 @@ -9,22 +9,36 @@ 191 # equivalents. 192 # In each case, I ordered them so <sys/types.h> was first, if it was 193 # an option for this type. That's the preferred #include all else 194 -# equal. The visibility on the symbol-name is ignored; by convention 195 -# we always set it to private. 196 +# equal. The same goes for <stdint.h>. The visibility on the 197 +# symbol-name is ignored; by convention we always set it to private. 198 [ 199 - { symbol: [ "blksize_t", private, "<sys/types.h>", public ] }, 200 - { symbol: [ "blkcnt_t", private, "<sys/stat.h>", public ] }, 201 + { symbol: [ "aiocb", private, "<aio.h>", public ] }, 202 { symbol: [ "blkcnt_t", private, "<sys/types.h>", public ] }, 203 + { symbol: [ "blkcnt_t", private, "<sys/stat.h>", public ] }, 204 + { symbol: [ "blksize_t", private, "<sys/types.h>", public ] }, 205 { symbol: [ "blksize_t", private, "<sys/stat.h>", public ] }, 206 + { symbol: [ "cc_t", private, "<termios.h>", public ] }, 207 { symbol: [ "clock_t", private, "<sys/types.h>", public ] }, 208 + { symbol: [ "clock_t", private, "<sys/time.h>", public ] }, 209 { symbol: [ "clock_t", private, "<time.h>", public ] }, 210 + { symbol: [ "clockid_t", private, "<sys/types.h>", public ] }, 211 + { symbol: [ "clockid_t", private, "<time.h>", public ] }, 212 { symbol: [ "daddr_t", private, "<sys/types.h>", public ] }, 213 { symbol: [ "daddr_t", private, "<rpc/types.h>", public ] }, 214 { symbol: [ "dev_t", private, "<sys/types.h>", public ] }, 215 { symbol: [ "dev_t", private, "<sys/stat.h>", public ] }, 216 + { symbol: [ "div_t", private, "<stdlib.h>", public ] }, 217 + { symbol: [ "double_t", private, "<math.h>", public ] }, 218 { symbol: [ "error_t", private, "<errno.h>", public ] }, 219 { symbol: [ "error_t", private, "<argp.h>", public ] }, 220 { symbol: [ "error_t", private, "<argz.h>", public ] }, 221 + { symbol: [ "fd_set", private, "<sys/select.h>", public ] }, 222 + { symbol: [ "fd_set", private, "<sys/time.h>", public ] }, 223 + { symbol: [ "fenv_t", private, "<fenv.h>", public ] }, 224 + { symbol: [ "fexcept_t", private, "<fenv.h>", public ] }, 225 + { symbol: [ "FILE", private, "<stdio.h>", public ] }, 226 + { symbol: [ "FILE", private, "<wchar.h>", public ] }, 227 + { symbol: [ "float_t", private, "<math.h>", public ] }, 228 { symbol: [ "fsblkcnt_t", private, "<sys/types.h>", public ] }, 229 { symbol: [ "fsblkcnt_t", private, "<sys/statvfs.h>", public ] }, 230 { symbol: [ "fsfilcnt_t", private, "<sys/types.h>", public ] }, 231 @@ -32,91 +46,173 @@ 232 { symbol: [ "gid_t", private, "<sys/types.h>", public ] }, 233 { symbol: [ "gid_t", private, "<grp.h>", public ] }, 234 { symbol: [ "gid_t", private, "<pwd.h>", public ] }, 235 + { symbol: [ "gid_t", private, "<signal.h>", public ] }, 236 { symbol: [ "gid_t", private, "<stropts.h>", public ] }, 237 { symbol: [ "gid_t", private, "<sys/ipc.h>", public ] }, 238 { symbol: [ "gid_t", private, "<sys/stat.h>", public ] }, 239 { symbol: [ "gid_t", private, "<unistd.h>", public ] }, 240 { symbol: [ "id_t", private, "<sys/types.h>", public ] }, 241 { symbol: [ "id_t", private, "<sys/resource.h>", public ] }, 242 + { symbol: [ "imaxdiv_t", private, "<inttypes.h>", public ] }, 243 + { symbol: [ "intmax_t", private, "<stdint.h>", public ] }, 244 + { symbol: [ "intmax_t", private, "<inttypes.h>", public ] }, 245 + { symbol: [ "uintmax_t", private, "<stdint.h>", public ] }, 246 + { symbol: [ "uintmax_t", private, "<inttypes.h>", public ] }, 247 { symbol: [ "ino64_t", private, "<sys/types.h>", public ] }, 248 { symbol: [ "ino64_t", private, "<dirent.h>", public ] }, 249 { symbol: [ "ino_t", private, "<sys/types.h>", public ] }, 250 { symbol: [ "ino_t", private, "<dirent.h>", public ] }, 251 { symbol: [ "ino_t", private, "<sys/stat.h>", public ] }, 252 - { symbol: [ "int8_t", private, "<sys/types.h>", public ] }, 253 { symbol: [ "int8_t", private, "<stdint.h>", public ] }, 254 + { symbol: [ "int8_t", private, "<inttypes.h>", public ] }, 255 { symbol: [ "int16_t", private, "<stdint.h>", public ] }, 256 + { symbol: [ "int16_t", private, "<inttypes.h>", public ] }, 257 { symbol: [ "int32_t", private, "<stdint.h>", public ] }, 258 + { symbol: [ "int32_t", private, "<inttypes.h>", public ] }, 259 { symbol: [ "int64_t", private, "<stdint.h>", public ] }, 260 + { symbol: [ "int64_t", private, "<inttypes.h>", public ] }, 261 { symbol: [ "uint8_t", private, "<stdint.h>", public ] }, 262 + { symbol: [ "uint8_t", private, "<inttypes.h>", public ] }, 263 { symbol: [ "uint16_t", private, "<stdint.h>", public ] }, 264 + { symbol: [ "uint16_t", private, "<inttypes.h>", public ] }, 265 { symbol: [ "uint32_t", private, "<stdint.h>", public ] }, 266 + { symbol: [ "uint32_t", private, "<inttypes.h>", public ] }, 267 { symbol: [ "uint64_t", private, "<stdint.h>", public ] }, 268 + { symbol: [ "uint64_t", private, "<inttypes.h>", public ] }, 269 { symbol: [ "intptr_t", private, "<stdint.h>", public ] }, 270 + { symbol: [ "intptr_t", private, "<inttypes.h>", public ] }, 271 { symbol: [ "uintptr_t", private, "<stdint.h>", public ] }, 272 - { symbol: [ "intptr_t", private, "<unistd.h>", public ] }, 273 + { symbol: [ "uintptr_t", private, "<inttypes.h>", public ] }, 274 { symbol: [ "key_t", private, "<sys/types.h>", public ] }, 275 { symbol: [ "key_t", private, "<sys/ipc.h>", public ] }, 276 + { symbol: [ "lconv", private, "<locale.h>", public ] }, 277 + { symbol: [ "ldiv_t", private, "<stdlib.h>", public ] }, 278 + { symbol: [ "lldiv_t", private, "<stdlib.h>", public ] }, 279 { symbol: [ "max_align_t", private, "<stddef.h>", public ] }, 280 { symbol: [ "mode_t", private, "<sys/types.h>", public ] }, 281 - { symbol: [ "mode_t", private, "<sys/stat.h>", public ] }, 282 + { symbol: [ "mode_t", private, "<fcntl.h>", public ] }, 283 + { symbol: [ "mode_t", private, "<ndbm.h>", public ] }, 284 + { symbol: [ "mode_t", private, "<spawn.h>", public ] }, 285 { symbol: [ "mode_t", private, "<sys/ipc.h>", public ] }, 286 { symbol: [ "mode_t", private, "<sys/mman.h>", public ] }, 287 + { symbol: [ "mode_t", private, "<sys/stat.h>", public ] }, 288 { symbol: [ "nlink_t", private, "<sys/types.h>", public ] }, 289 { symbol: [ "nlink_t", private, "<sys/stat.h>", public ] }, 290 { symbol: [ "off64_t", private, "<sys/types.h>", public ] }, 291 { symbol: [ "off64_t", private, "<unistd.h>", public ] }, 292 { symbol: [ "off_t", private, "<sys/types.h>", public ] }, 293 - { symbol: [ "off_t", private, "<unistd.h>", public ] }, 294 - { symbol: [ "off_t", private, "<sys/stat.h>", public ] }, 295 + { symbol: [ "off_t", private, "<aio.h>", public ] }, 296 + { symbol: [ "off_t", private, "<fcntl.h>", public ] }, 297 + { symbol: [ "off_t", private, "<stdio.h>", public ] }, 298 { symbol: [ "off_t", private, "<sys/mman.h>", public ] }, 299 + { symbol: [ "off_t", private, "<sys/stat.h>", public ] }, 300 + { symbol: [ "off_t", private, "<unistd.h>", public ] }, 301 { symbol: [ "pid_t", private, "<sys/types.h>", public ] }, 302 - { symbol: [ "pid_t", private, "<unistd.h>", public ] }, 303 + { symbol: [ "pid_t", private, "<fcntl.h>", public ] }, 304 + { symbol: [ "pid_t", private, "<sched.h>", public ] }, 305 { symbol: [ "pid_t", private, "<signal.h>", public ] }, 306 + { symbol: [ "pid_t", private, "<spawn.h>", public ] }, 307 { symbol: [ "pid_t", private, "<sys/msg.h>", public ] }, 308 + { symbol: [ "pid_t", private, "<sys/sem.h>", public ] }, 309 { symbol: [ "pid_t", private, "<sys/shm.h>", public ] }, 310 + { symbol: [ "pid_t", private, "<sys/wait.h>", public ] }, 311 { symbol: [ "pid_t", private, "<termios.h>", public ] }, 312 { symbol: [ "pid_t", private, "<time.h>", public ] }, 313 + { symbol: [ "pid_t", private, "<unistd.h>", public ] }, 314 { symbol: [ "pid_t", private, "<utmpx.h>", public ] }, 315 { symbol: [ "ptrdiff_t", private, "<stddef.h>", public ] }, 316 + { symbol: [ "regex_t", private, "<regex.h>", public ] }, 317 + { symbol: [ "regmatch_t", private, "<regex.h>", public ] }, 318 + { symbol: [ "regoff_t", private, "<regex.h>", public ] }, 319 + { symbol: [ "sigevent", private, "<signal.h>", public ] }, 320 + { symbol: [ "sigevent", private, "<aio.h>", public ] }, 321 + { symbol: [ "sigevent", private, "<mqueue.h>", public ] }, 322 + { symbol: [ "sigevent", private, "<time.h>", public ] }, 323 + { symbol: [ "siginfo_t", private, "<signal.h>", public ] }, 324 + { symbol: [ "siginfo_t", private, "<sys/wait.h>", public ] }, 325 { symbol: [ "sigset_t", private, "<signal.h>", public ] }, 326 - { symbol: [ "sigset_t", private, "<sys/epoll.h>", public ] }, 327 + { symbol: [ "sigset_t", private, "<spawn.h>", public ] }, 328 { symbol: [ "sigset_t", private, "<sys/select.h>", public ] }, 329 - { symbol: [ "socklen_t", private, "<bits/socket.h>", private ] }, 330 - { symbol: [ "socklen_t", private, "<unistd.h>", public ] }, 331 - { symbol: [ "socklen_t", private, "<arpa/inet.h>", public ] }, 332 + { symbol: [ "sigval", private, "<signal.h>", public ] }, 333 + { symbol: [ "sockaddr", private, "<sys/socket.h>", public ] }, 334 + { symbol: [ "socklen_t", private, "<sys/socket.h>", public ] }, 335 + { symbol: [ "socklen_t", private, "<netdb.h>", public ] }, 336 { symbol: [ "ssize_t", private, "<sys/types.h>", public ] }, 337 - { symbol: [ "ssize_t", private, "<unistd.h>", public ] }, 338 + { symbol: [ "ssize_t", private, "<aio.h>", public ] }, 339 { symbol: [ "ssize_t", private, "<monetary.h>", public ] }, 340 + { symbol: [ "ssize_t", private, "<mqueue.h>", public ] }, 341 + { symbol: [ "ssize_t", private, "<stdio.h>", public ] }, 342 { symbol: [ "ssize_t", private, "<sys/msg.h>", public ] }, 343 + { symbol: [ "ssize_t", private, "<sys/socket.h>", public ] }, 344 + { symbol: [ "ssize_t", private, "<sys/uio.h>", public ] }, 345 + { symbol: [ "ssize_t", private, "<unistd.h>", public ] }, 346 { symbol: [ "suseconds_t", private, "<sys/types.h>", public ] }, 347 - { symbol: [ "suseconds_t", private, "<sys/time.h>", public ] }, 348 { symbol: [ "suseconds_t", private, "<sys/select.h>", public ] }, 349 - { symbol: [ "time_t", private, "<sys/types.h>", public ] }, 350 + { symbol: [ "suseconds_t", private, "<sys/time.h>", public ] }, 351 { symbol: [ "time_t", private, "<time.h>", public ] }, 352 + { symbol: [ "time_t", private, "<sched.h>", public ] }, 353 + { symbol: [ "time_t", private, "<sys/msg.h>", public ] }, 354 + { symbol: [ "time_t", private, "<sys/select.h>", public ] }, 355 + { symbol: [ "time_t", private, "<sys/sem.h>", public ] }, 356 + { symbol: [ "time_t", private, "<sys/shm.h>", public ] }, 357 + { symbol: [ "time_t", private, "<sys/stat.h>", public ] }, 358 + { symbol: [ "time_t", private, "<sys/time.h>", public ] }, 359 + { symbol: [ "time_t", private, "<sys/types.h>", public ] }, 360 + { symbol: [ "time_t", private, "<utime.h>", public ] }, 361 + { symbol: [ "timer_t", private, "<sys/types.h>", public ] }, 362 + { symbol: [ "timer_t", private, "<time.h>", public ] }, 363 { symbol: [ "timespec", private, "<time.h>", public ] }, 364 + { symbol: [ "timespec", private, "<aio.h>", public ] }, 365 + { symbol: [ "timespec", private, "<mqueue.h>", public ] }, 366 + { symbol: [ "timespec", private, "<sched.h>", public ] }, 367 + { symbol: [ "timespec", private, "<signal.h>", public ] }, 368 + { symbol: [ "timespec", private, "<sys/select.h>", public ] }, 369 + { symbol: [ "timespec", private, "<sys/stat.h>", public ] }, 370 { symbol: [ "timeval", private, "<sys/time.h>", public ] }, 371 + { symbol: [ "timeval", private, "<sys/resource.h>", public ] }, 372 + { symbol: [ "timeval", private, "<sys/select.h>", public ] }, 373 + { symbol: [ "timeval", private, "<utmpx.h>", public ] }, 374 { symbol: [ "u_char", private, "<sys/types.h>", public ] }, 375 { symbol: [ "u_char", private, "<rpc/types.h>", public ] }, 376 { symbol: [ "uid_t", private, "<sys/types.h>", public ] }, 377 - { symbol: [ "uid_t", private, "<unistd.h>", public ] }, 378 { symbol: [ "uid_t", private, "<pwd.h>", public ] }, 379 { symbol: [ "uid_t", private, "<signal.h>", public ] }, 380 { symbol: [ "uid_t", private, "<stropts.h>", public ] }, 381 { symbol: [ "uid_t", private, "<sys/ipc.h>", public ] }, 382 { symbol: [ "uid_t", private, "<sys/stat.h>", public ] }, 383 + { symbol: [ "uid_t", private, "<unistd.h>", public ] }, 384 { symbol: [ "useconds_t", private, "<sys/types.h>", public ] }, 385 { symbol: [ "useconds_t", private, "<unistd.h>", public ] }, 386 { symbol: [ "wchar_t", private, "<stddef.h>", public ] }, 387 { symbol: [ "wchar_t", private, "<stdlib.h>", public ] }, 388 - # glob.h seems to define size_t if necessary, but it should come from stddef. 389 { symbol: [ "size_t", private, "<stddef.h>", public ] }, 390 + { symbol: [ "size_t", private, "<aio.h>", public ] }, 391 + { symbol: [ "size_t", private, "<glob.h>", public ] }, 392 + { symbol: [ "size_t", private, "<grp.h>", public ] }, 393 + { symbol: [ "size_t", private, "<iconv.h>", public ] }, 394 + { symbol: [ "size_t", private, "<monetary.h>", public ] }, 395 + { symbol: [ "size_t", private, "<mqueue.h>", public ] }, 396 + { symbol: [ "size_t", private, "<ndbm.h>", public ] }, 397 + { symbol: [ "size_t", private, "<pwd.h>", public ] }, 398 + { symbol: [ "size_t", private, "<regex.h>", public ] }, 399 + { symbol: [ "size_t", private, "<search.h>", public ] }, 400 + { symbol: [ "size_t", private, "<signal.h>", public ] }, 401 { symbol: [ "size_t", private, "<stdio.h>", public ] }, 402 { symbol: [ "size_t", private, "<stdlib.h>", public ] }, 403 { symbol: [ "size_t", private, "<string.h>", public ] }, 404 + { symbol: [ "size_t", private, "<strings.h>", public ] }, 405 + { symbol: [ "size_t", private, "<sys/mman.h>", public ] }, 406 + { symbol: [ "size_t", private, "<sys/msg.h>", public ] }, 407 + { symbol: [ "size_t", private, "<sys/sem.h>", public ] }, 408 + { symbol: [ "size_t", private, "<sys/shm.h>", public ] }, 409 + { symbol: [ "size_t", private, "<sys/socket.h>", public ] }, 410 + { symbol: [ "size_t", private, "<sys/types.h>", public ] }, 411 + { symbol: [ "size_t", private, "<sys/uio.h>", public ] }, 412 { symbol: [ "size_t", private, "<time.h>", public ] }, 413 { symbol: [ "size_t", private, "<uchar.h>", public ] }, 414 + { symbol: [ "size_t", private, "<unistd.h>", public ] }, 415 { symbol: [ "size_t", private, "<wchar.h>", public ] }, 416 + { symbol: [ "size_t", private, "<wordexp.h>", public ] }, 417 # Macros that can be defined in more than one file, don't have the 418 # same __foo_defined guard that other types do, so the grep above 419 # doesn't discover them. Until I figure out a better way, I just 420 @@ -125,6 +221,8 @@ 421 { symbol: [ "EOF", private, "<libio.h>", public ] }, 422 { symbol: [ "FILE", private, "<stdio.h>", public ] }, 423 { symbol: [ "va_list", private, "<stdarg.h>", public ] }, 424 + { symbol: [ "va_list", private, "<stdio.h>", public ] }, 425 + { symbol: [ "va_list", private, "<wchar.h>", public ] }, 426 # These are symbols that could be defined in either stdlib.h or 427 # malloc.h, but we always want the stdlib location. 428 { symbol: [ "malloc", private, "<stdlib.h>", public ] }, 429 diff --git a/iwyu.cc b/iwyu.cc 430 index 355e793..61350ca 100644 431 --- a/iwyu.cc 432 +++ b/iwyu.cc 433 @@ -167,6 +167,7 @@ using clang::ConstructorUsingShadowDecl; 434 using clang::Decl; 435 using clang::DeclContext; 436 using clang::DeclRefExpr; 437 +using clang::DeducedTemplateSpecializationType; 438 using clang::EnumType; 439 using clang::Expr; 440 using clang::FileEntry; 441 @@ -191,6 +192,7 @@ using clang::QualifiedTypeLoc; 442 using clang::RecordDecl; 443 using clang::RecursiveASTVisitor; 444 using clang::ReferenceType; 445 +using clang::Sema; 446 using clang::SourceLocation; 447 using clang::Stmt; 448 using clang::SubstTemplateTypeParmType; 449 @@ -532,17 +534,10 @@ class BaseAstVisitor : public RecursiveASTVisitor<Derived> { 450 451 //------------------------------------------------------------ 452 // (4) Add implicit text. 453 - 454 - // When we see an object that has implicit text that iwyu 455 - // wants to look at, we make callbacks as if that text had 456 - // been explicitly written. Here's text we consider: 457 // 458 - // * CXXDestructorDecl: a destructor call for each non-POD field 459 - // in the dtor's class, and each base type of that class. 460 - // * CXXRecordDecl: a CXXConstructorDecl for each implicit 461 - // constructor (zero-arg and copy). A CXXDestructor decl 462 - // if the destructor is implicit. A CXXOperatorCallDecl if 463 - // operator= is explicit. 464 + // This simulates a call to the destructor of every non-POD field and base 465 + // class in all classes with destructors, to mark them as used by virtue of 466 + // being class members. 467 bool TraverseCXXDestructorDecl(clang::CXXDestructorDecl* decl) { 468 if (!Base::TraverseCXXDestructorDecl(decl)) return false; 469 if (CanIgnoreCurrentASTNode()) return true; 470 @@ -575,69 +570,12 @@ class BaseAstVisitor : public RecursiveASTVisitor<Derived> { 471 return true; 472 } 473 474 - // clang lazily constructs the implicit methods of a C++ class (the 475 - // default constructor and destructor, etc) -- it only bothers to 476 - // create a CXXMethodDecl if someone actually calls these classes. 477 - // But we need to be non-lazy: iwyu depends on analyzing what future 478 - // code *may* call in a class, not what current code *does*. So we 479 - // force all the lazy evaluation to happen here. This will 480 - // (possibly) add a bunch of MethodDecls to the AST, as children of 481 - // decl. We're hoping it will always be safe to modify the AST 482 - // while it's being traversed! 483 - void InstantiateImplicitMethods(CXXRecordDecl* decl) { 484 - if (decl->isDependentType()) // only instantiate if class is instantiated 485 - return; 486 - 487 - clang::Sema& sema = compiler()->getSema(); 488 - DeclContext::lookup_result ctors = sema.LookupConstructors(decl); 489 - for (NamedDecl* ctor_lookup : ctors) { 490 - // Ignore templated or inheriting constructors. 491 - if (isa<FunctionTemplateDecl>(ctor_lookup) || 492 - isa<UsingDecl>(ctor_lookup) || 493 - isa<ConstructorUsingShadowDecl>(ctor_lookup)) 494 - continue; 495 - CXXConstructorDecl* ctor = cast<CXXConstructorDecl>(ctor_lookup); 496 - if (!ctor->hasBody() && !ctor->isDeleted() && ctor->isImplicit()) { 497 - if (sema.getSpecialMember(ctor) == clang::Sema::CXXDefaultConstructor) { 498 - sema.DefineImplicitDefaultConstructor(CurrentLoc(), ctor); 499 - } else { 500 - // TODO(nlewycky): enable this! 501 - //sema.DefineImplicitCopyConstructor(CurrentLoc(), ctor); 502 - } 503 - } 504 - // Unreferenced template constructors stay uninstantiated on purpose. 505 - } 506 - 507 - if (CXXDestructorDecl* dtor = sema.LookupDestructor(decl)) { 508 - if (!dtor->isDeleted()) { 509 - if (!dtor->hasBody() && dtor->isImplicit()) 510 - sema.DefineImplicitDestructor(CurrentLoc(), dtor); 511 - if (!dtor->isDefined() && dtor->getTemplateInstantiationPattern()) 512 - sema.PendingInstantiations.emplace_back(dtor, CurrentLoc()); 513 - } 514 - } 515 - 516 - // TODO(nlewycky): copy assignment operator 517 - 518 - // clang queues up method instantiations. We need to process them now. 519 - sema.PerformPendingInstantiations(); 520 - } 521 - 522 - // Handle implicit methods that otherwise wouldn't be seen by RAV. 523 - bool TraverseCXXRecordDecl(clang::CXXRecordDecl* decl) { 524 - if (CanIgnoreCurrentASTNode()) return true; 525 - // We only care about classes that are actually defined. 526 - if (decl && decl->isThisDeclarationADefinition()) { 527 - InstantiateImplicitMethods(decl); 528 - } 529 - 530 - return Base::TraverseCXXRecordDecl(decl); 531 - } 532 - 533 + // Class template specialization are similar to regular C++ classes, 534 + // particularly they need the same custom handling of implicit destructors. 535 bool TraverseClassTemplateSpecializationDecl( 536 clang::ClassTemplateSpecializationDecl* decl) { 537 if (!Base::TraverseClassTemplateSpecializationDecl(decl)) return false; 538 - return TraverseCXXRecordDecl(decl); 539 + return Base::TraverseCXXRecordDecl(decl); 540 } 541 542 //------------------------------------------------------------ 543 @@ -1322,7 +1260,26 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 544 for (const NamedDecl* redecl : GetClassRedecls(decl)) { 545 if (GetFileEntry(redecl) == macro_def_file && IsForwardDecl(redecl)) { 546 fwd_decl = redecl; 547 + break; 548 + } 549 + } 550 551 + if (!fwd_decl) { 552 + if (const auto* func_decl = dyn_cast<FunctionDecl>(decl)) { 553 + if (const FunctionTemplateDecl* ft_decl = 554 + func_decl->getPrimaryTemplate()) { 555 + VERRS(5) << "No fwd-decl found, looking for function template decl\n"; 556 + for (const NamedDecl* redecl : ft_decl->redecls()) { 557 + if (GetFileEntry(redecl) == macro_def_file) { 558 + fwd_decl = redecl; 559 + break; 560 + } 561 + } 562 + } 563 + } 564 + } 565 + 566 + if (fwd_decl) { 567 // Make sure we keep that forward-declaration, even if it's probably 568 // unused in this file. 569 IwyuFileInfo* file_info = 570 @@ -1330,8 +1287,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 571 file_info->ReportForwardDeclareUse( 572 spelling_loc, fwd_decl, 573 ComputeUseFlags(current_ast_node()), nullptr); 574 - break; 575 - } 576 } 577 578 // Resolve the best use location based on our current knowledge. 579 @@ -1460,12 +1415,12 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 580 } 581 582 set<const Type*> GetCallerResponsibleTypesForTypedef( 583 - const TypedefDecl* decl) { 584 + const TypedefNameDecl* decl) { 585 set<const Type*> retval; 586 const Type* underlying_type = decl->getUnderlyingType().getTypePtr(); 587 // If the underlying type is itself a typedef, we recurse. 588 if (const TypedefType* underlying_typedef = DynCastFrom(underlying_type)) { 589 - if (const TypedefDecl* underlying_typedef_decl 590 + if (const TypedefNameDecl* underlying_typedef_decl 591 = DynCastFrom(TypeToDeclAsWritten(underlying_typedef))) { 592 // TODO(csilvers): if one of the intermediate typedefs 593 // #includes the necessary definition of the 'final' 594 @@ -1610,12 +1565,12 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 595 // anywhere. ('autocast' is similar, but is handled in 596 // VisitCastExpr; 'fn-return-type' is also similar and is 597 // handled in HandleFunctionCall.) 598 - if (const TypedefDecl* typedef_decl = DynCastFrom(target_decl)) { 599 + if (const TypedefNameDecl* typedef_decl = DynCastFrom(target_decl)) { 600 // One exception: if this TypedefType is being used in another 601 // typedef (that is, 'typedef MyTypedef OtherTypdef'), then the 602 // user -- the other typedef -- is never responsible for the 603 // underlying type. Instead, users of that typedef are. 604 - if (!current_ast_node()->template ParentIsA<TypedefDecl>()) { 605 + if (!current_ast_node()->template ParentIsA<TypedefNameDecl>()) { 606 const set<const Type*>& underlying_types 607 = GetCallerResponsibleTypesForTypedef(typedef_decl); 608 if (!underlying_types.empty()) { 609 @@ -1757,7 +1712,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 610 // iwyu will demand the full type of pair, but not of its template 611 // arguments. This is handled not here, but below, in 612 // VisitSubstTemplateTypeParmType. 613 - bool VisitTypedefDecl(clang::TypedefDecl* decl) { 614 + bool VisitTypedefNameDecl(clang::TypedefNameDecl* decl) { 615 if (CanIgnoreCurrentASTNode()) return true; 616 const Type* underlying_type = decl->getUnderlyingType().getTypePtr(); 617 const Type* deref_type 618 @@ -1770,7 +1725,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 619 current_ast_node()->set_in_forward_declare_context(false); 620 } 621 622 - return Base::VisitTypedefDecl(decl); 623 + return Base::VisitTypedefNameDecl(decl); 624 } 625 626 // If we're a declared (not defined) function, all our types -- 627 @@ -1977,8 +1932,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 628 case clang::CK_BooleanToSignedIntegral: 629 case clang::CK_FixedPointCast: 630 case clang::CK_FixedPointToBoolean: 631 - case clang::CK_FixedPointToFloating: 632 - case clang::CK_FixedPointToIntegral: 633 case clang::CK_FloatingCast: 634 case clang::CK_FloatingComplexCast: 635 case clang::CK_FloatingComplexToBoolean: 636 @@ -1986,7 +1939,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 637 case clang::CK_FloatingComplexToReal: 638 case clang::CK_FloatingRealToComplex: 639 case clang::CK_FloatingToBoolean: 640 - case clang::CK_FloatingToFixedPoint: 641 case clang::CK_FloatingToIntegral: 642 case clang::CK_FunctionToPointerDecay: 643 case clang::CK_IntegralCast: 644 @@ -1996,7 +1948,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 645 case clang::CK_IntegralComplexToReal: 646 case clang::CK_IntegralRealToComplex: 647 case clang::CK_IntegralToBoolean: 648 - case clang::CK_IntegralToFixedPoint: 649 case clang::CK_IntegralToFloating: 650 case clang::CK_IntegralToPointer: 651 case clang::CK_MemberPointerToBoolean: 652 @@ -2025,7 +1976,6 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 653 // Kinds for reinterpret_cast and const_cast, which need no full types. 654 case clang::CK_BitCast: // used for reinterpret_cast 655 case clang::CK_LValueBitCast: // used for reinterpret_cast 656 - case clang::CK_LValueToRValueBitCast: // used for reinterpret_cast 657 case clang::CK_NoOp: // used for const_cast, etc 658 break; 659 660 @@ -2428,15 +2378,15 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 661 // contents don't matter that much. 662 using clang::Optional; 663 using clang::DirectoryLookup; 664 - using clang::FileEntryRef; 665 + using clang::FileEntry; 666 const FileEntry* use_file = CurrentFileEntry(); 667 const DirectoryLookup* curdir = nullptr; 668 - Optional<FileEntryRef> file = compiler()->getPreprocessor().LookupFile( 669 + auto file = compiler()->getPreprocessor().LookupFile( 670 CurrentLoc(), "new", true, nullptr, use_file, curdir, nullptr, 671 - nullptr, nullptr, nullptr, nullptr, false); 672 + nullptr, nullptr, nullptr, false); 673 if (file) { 674 preprocessor_info().FileInfoFor(use_file)->ReportFullSymbolUse( 675 - CurrentLoc(), *file, "operator new"); 676 + CurrentLoc(), file, "operator new"); 677 } 678 } 679 } 680 @@ -2591,7 +2541,7 @@ class IwyuBaseAstVisitor : public BaseAstVisitor<Derived> { 681 // If we're in a typedef, we don't want to forward-declare even if 682 // we're a pointer. ('typedef Foo* Bar; Bar x; x->a' needs full 683 // type of Foo.) 684 - if (ast_node->ParentIsA<TypedefDecl>()) 685 + if (ast_node->ParentIsA<TypedefNameDecl>()) 686 return false; 687 688 // If we ourselves are a forward-decl -- that is, we're the type 689 @@ -3656,11 +3606,31 @@ class IwyuAstConsumer 690 const_cast<IwyuPreprocessorInfo*>(&preprocessor_info())-> 691 HandlePreprocessingDone(); 692 693 + TranslationUnitDecl* tu_decl = context.getTranslationUnitDecl(); 694 + 695 + // Sema::TUScope is reset after parsing, but Sema::getCurScope still points 696 + // to the translation unit decl scope. TUScope is required for lookup in 697 + // some complex scenarios, so re-wire it before running IWYU AST passes. 698 + // Assert their expected state so we notice if these assumptions change. 699 + Sema& sema = compiler()->getSema(); 700 + CHECK_(sema.TUScope == nullptr); 701 + CHECK_(sema.getCurScope() != nullptr); 702 + sema.TUScope = sema.getCurScope(); 703 + 704 // We run a separate pass to force parsing of late-parsed function 705 // templates. 706 - ParseFunctionTemplates(context.getTranslationUnitDecl()); 707 + ParseFunctionTemplates(sema, tu_decl); 708 709 - TraverseDecl(context.getTranslationUnitDecl()); 710 + // Clang lazily constructs the implicit methods of a C++ class (the 711 + // default constructor and destructor, etc) -- it only bothers to 712 + // create a CXXMethodDecl if someone actually calls these classes. 713 + // But we need to be non-lazy: IWYU depends on analyzing what future 714 + // code *may* call in a class, not what current code *does*. So we 715 + // force all the lazy evaluation to happen here. 716 + InstantiateImplicitMethods(sema, tu_decl); 717 + 718 + // Run IWYU analysis. 719 + TraverseDecl(tu_decl); 720 721 // Check if any unrecoverable errors have occurred. 722 // There is no point in continuing when the AST is in a bad state. 723 @@ -3705,9 +3675,8 @@ class IwyuAstConsumer 724 exit(EXIT_SUCCESS_OFFSET + num_edits); 725 } 726 727 - void ParseFunctionTemplates(TranslationUnitDecl* decl) { 728 - set<FunctionDecl*> late_parsed_decls = GetLateParsedFunctionDecls(decl); 729 - clang::Sema& sema = compiler()->getSema(); 730 + void ParseFunctionTemplates(Sema& sema, TranslationUnitDecl* tu_decl) { 731 + set<FunctionDecl*> late_parsed_decls = GetLateParsedFunctionDecls(tu_decl); 732 733 // If we have any late-parsed functions, make sure the 734 // -fdelayed-template-parsing flag is on. Otherwise we don't know where 735 @@ -3730,6 +3699,55 @@ class IwyuAstConsumer 736 } 737 } 738 739 + void InstantiateImplicitMethods(Sema& sema, TranslationUnitDecl* tu_decl) { 740 + // Collect all implicit ctors/dtors that need to be instantiated. 741 + struct Visitor : public RecursiveASTVisitor<Visitor> { 742 + Visitor(Sema& sema) : sema(sema) { 743 + } 744 + 745 + bool VisitCXXRecordDecl(CXXRecordDecl* decl) { 746 + if (CanIgnoreLocation(GetLocation(decl))) 747 + return true; 748 + 749 + if (!decl->getDefinition() || decl->isDependentContext() || 750 + decl->isBeingDefined()) { 751 + return true; 752 + } 753 + 754 + if (CXXConstructorDecl* ctor = sema.LookupDefaultConstructor(decl)) { 755 + may_need_definition.insert(ctor); 756 + } else if (CXXDestructorDecl* dtor = sema.LookupDestructor(decl)) { 757 + may_need_definition.insert(dtor); 758 + } 759 + 760 + return true; 761 + } 762 + 763 + Sema& sema; 764 + std::set<CXXMethodDecl*> may_need_definition; 765 + }; 766 + 767 + // Run visitor to collect implicit methods. 768 + Visitor v(sema); 769 + v.TraverseDecl(tu_decl); 770 + 771 + // For each method collected, let Sema define them. 772 + for (CXXMethodDecl* method : v.may_need_definition) { 773 + if (!method->isDefaulted() || method->isDeleted() || method->hasBody()) 774 + continue; 775 + 776 + SourceLocation loc = GetLocation(method->getParent()); 777 + if (auto* ctor = dyn_cast<CXXConstructorDecl>(method)) { 778 + sema.DefineImplicitDefaultConstructor(loc, ctor); 779 + } else if (auto* dtor = dyn_cast<CXXDestructorDecl>(method)) { 780 + sema.DefineImplicitDestructor(loc, dtor); 781 + } 782 + } 783 + 784 + // Clang queues up method instantiations. Process them now. 785 + sema.PerformPendingInstantiations(); 786 + } 787 + 788 //------------------------------------------------------------ 789 // AST visitors. We start by adding a visitor callback for 790 // most of the subclasses of Decl/Stmt/Type listed in: 791 @@ -3913,14 +3931,13 @@ class IwyuAstConsumer 792 // TODO(csilvers): we can probably relax this rule in .cc files. 793 // TODO(csilvers): this should really move into IwyuBaseASTVisitor 794 // (that way we'll correctly identify need for hash<> in hash_set). 795 - // This is a Traverse*() because Visit*() can't call HandleFunctionCall(). 796 - bool TraverseTypedefDecl(clang::TypedefDecl* decl) { 797 - // Before we go up the tree, make sure the parents know we don't 798 - // forward-declare the underlying type of a typedef decl. 799 - current_ast_node()->set_in_forward_declare_context(false); 800 - if (!Base::TraverseTypedefDecl(decl)) 801 - return false; 802 - if (CanIgnoreCurrentASTNode()) return true; 803 + // This is called from Traverse*() because Visit*() 804 + // can't call HandleFunctionCall(). 805 + bool HandleAliasedClassMethods(TypedefNameDecl* decl) { 806 + if (CanIgnoreCurrentASTNode()) 807 + return true; 808 + if (current_ast_node()->in_forward_declare_context()) 809 + return true; 810 811 const Type* underlying_type = decl->getUnderlyingType().getTypePtr(); 812 const Decl* underlying_decl = TypeToDeclAsWritten(underlying_type); 813 @@ -3947,6 +3964,20 @@ class IwyuAstConsumer 814 return true; 815 } 816 817 + bool TraverseTypedefDecl(clang::TypedefDecl* decl) { 818 + if (!Base::TraverseTypedefDecl(decl)) 819 + return false; 820 + 821 + return HandleAliasedClassMethods(decl); 822 + } 823 + 824 + bool TraverseTypeAliasDecl(clang::TypeAliasDecl* decl) { 825 + if (!Base::TraverseTypeAliasDecl(decl)) 826 + return false; 827 + 828 + return HandleAliasedClassMethods(decl); 829 + } 830 + 831 // --- Visitors of types derived from clang::Stmt. 832 833 // Called whenever a variable, function, enum, etc is used. 834 @@ -4063,18 +4094,21 @@ class IwyuAstConsumer 835 bool VisitTemplateName(TemplateName template_name) { 836 if (CanIgnoreCurrentASTNode()) return true; 837 if (!Base::VisitTemplateName(template_name)) return false; 838 - // The only time we can see a TemplateName not in the 839 - // context of a TemplateSpecializationType is when it's 840 - // the default argument of a template template arg: 841 + // We can see TemplateName not in the context of aTemplateSpecializationType 842 + // when it's either the default argument of a template template arg: 843 // template<template<class T> class A = TplNameWithoutTST> class Foo ... 844 - // So that's the only case we need to handle here. 845 + // or a deduced template specialization: 846 + // std::pair x(10, 20); // type of x is really std::pair<int, int> 847 + // So that's the only cases we need to handle here. 848 // TODO(csilvers): check if this is really forward-declarable or 849 // not. You *could* do something like: 'template<template<class 850 // T> class A = Foo> class C { A<int>* x; };' and never 851 // dereference x, but that's pretty unlikely. So for now, we just 852 // assume these default template template args always need full 853 // type info. 854 - if (IsDefaultTemplateTemplateArg(current_ast_node())) { 855 + const ASTNode* ast_node = current_ast_node(); 856 + if (ast_node->ParentIsA<DeducedTemplateSpecializationType>() || 857 + IsDefaultTemplateTemplateArg(ast_node)) { 858 current_ast_node()->set_in_forward_declare_context(false); 859 ReportDeclUse(CurrentLoc(), template_name.getAsTemplateDecl()); 860 } 861 @@ -4140,7 +4174,6 @@ class IwyuAction : public ASTFrontendAction { 862 863 #include "iwyu_driver.h" 864 #include "clang/Frontend/FrontendAction.h" 865 -#include "llvm/Support/ManagedStatic.h" 866 #include "llvm/Support/TargetSelect.h" 867 868 using include_what_you_use::OptionsParser; 869 @@ -4148,12 +4181,11 @@ using include_what_you_use::IwyuAction; 870 using include_what_you_use::CreateCompilerInstance; 871 872 int main(int argc, char **argv) { 873 - // Must initialize X86 target to be able to parse Microsoft inline 874 - // assembly. We do this unconditionally, because it allows an IWYU 875 - // built for non-X86 targets to parse MS inline asm without choking. 876 - LLVMInitializeX86TargetInfo(); 877 - LLVMInitializeX86TargetMC(); 878 - LLVMInitializeX86AsmParser(); 879 + // X86 target is required to parse Microsoft inline assembly, so we hope it's 880 + // part of all targets. Clang parser will complain otherwise. 881 + llvm::InitializeAllTargetInfos(); 882 + llvm::InitializeAllTargetMCs(); 883 + llvm::InitializeAllAsmParsers(); 884 885 // The command line should look like 886 // path/to/iwyu -Xiwyu --verbose=4 [-Xiwyu --other_iwyu_flag]... CLANG_FLAGS... foo.cc 887 diff --git a/iwyu_ast_util.cc b/iwyu_ast_util.cc 888 index 9982145..50477eb 100644 889 --- a/iwyu_ast_util.cc 890 +++ b/iwyu_ast_util.cc 891 @@ -25,7 +25,6 @@ 892 #include "llvm/Support/Casting.h" 893 #include "llvm/Support/raw_ostream.h" 894 #include "clang/AST/ASTContext.h" 895 -#include "clang/AST/ASTDumper.h" 896 #include "clang/AST/CanonicalType.h" 897 #include "clang/AST/Decl.h" 898 #include "clang/AST/DeclBase.h" 899 @@ -47,7 +46,6 @@ namespace clang { 900 class FileEntry; 901 } // namespace clang 902 903 -using clang::ASTDumper; 904 using clang::BlockPointerType; 905 using clang::CXXConstructExpr; 906 using clang::CXXConstructorDecl; 907 @@ -446,14 +444,12 @@ string PrintableDecl(const Decl* decl, bool terse/*=true*/) { 908 string PrintableStmt(const Stmt* stmt) { 909 std::string buffer; 910 raw_string_ostream ostream(buffer); 911 - ASTDumper dumper(ostream, /*ShowColors=*/false); 912 - dumper.Visit(stmt); 913 + stmt->dump(ostream, *GlobalSourceManager()); 914 return ostream.str(); 915 } 916 917 void PrintStmt(const Stmt* stmt) { 918 - ASTDumper dumper(llvm::errs(), /*ShowColors=*/false); 919 - dumper.Visit(stmt); 920 + stmt->dump(*GlobalSourceManager()); // This prints to errs(). 921 } 922 923 string PrintableType(const Type* type) { 924 @@ -1095,11 +1091,14 @@ bool DeclsAreInSameClass(const Decl* decl1, const Decl* decl2) { 925 return decl1->getDeclContext()->isRecord(); 926 } 927 928 -bool IsBuiltinFunction(const clang::NamedDecl* decl, 929 - const std::string& symbol_name) { 930 +bool IsBuiltinFunction(const clang::NamedDecl* decl) { 931 if (const clang::IdentifierInfo* iden = decl->getIdentifier()) { 932 - return iden->getBuiltinID() != 0 && 933 - !clang::Builtin::Context::isBuiltinFunc(symbol_name.c_str()); 934 + unsigned builtin_id = iden->getBuiltinID(); 935 + if (builtin_id != 0) { 936 + const clang::Builtin::Context& ctx = decl->getASTContext().BuiltinInfo; 937 + return !ctx.isPredefinedLibFunction(builtin_id) && 938 + !ctx.isHeaderDependentFunction(builtin_id); 939 + } 940 } 941 return false; 942 } 943 diff --git a/iwyu_ast_util.h b/iwyu_ast_util.h 944 index 18ddf2d..28668f7 100644 945 --- a/iwyu_ast_util.h 946 +++ b/iwyu_ast_util.h 947 @@ -652,8 +652,7 @@ const clang::NamedDecl* GetNonfriendClassRedecl(const clang::NamedDecl* decl); 948 bool DeclsAreInSameClass(const clang::Decl* decl1, const clang::Decl* decl2); 949 950 // Returns true if the given decl/name is a builtin function 951 -bool IsBuiltinFunction(const clang::NamedDecl* decl, 952 - const std::string& symbol_name); 953 +bool IsBuiltinFunction(const clang::NamedDecl* decl); 954 955 // --- Utilities for Type. 956 957 diff --git a/iwyu_driver.cc b/iwyu_driver.cc 958 index 42fea35..d9b96b7 100644 959 --- a/iwyu_driver.cc 960 +++ b/iwyu_driver.cc 961 @@ -205,8 +205,11 @@ CompilerInstance* CreateCompilerInstance(int argc, const char **argv) { 962 963 // Initialize a compiler invocation object from the clang (-cc1) arguments. 964 const ArgStringList &cc_arguments = command.getArguments(); 965 + const char** args_start = const_cast<const char**>(cc_arguments.data()); 966 + const char** args_end = args_start + cc_arguments.size(); 967 std::shared_ptr<CompilerInvocation> invocation(new CompilerInvocation); 968 - CompilerInvocation::CreateFromArgs(*invocation, cc_arguments, diagnostics); 969 + CompilerInvocation::CreateFromArgs(*invocation, 970 + args_start, args_end, diagnostics); 971 invocation->getFrontendOpts().DisableFree = false; 972 973 // Use libc++ headers bundled with Xcode.app on macOS. 974 diff --git a/iwyu_globals.cc b/iwyu_globals.cc 975 index 36ac3ae..96b728c 100644 976 --- a/iwyu_globals.cc 977 +++ b/iwyu_globals.cc 978 @@ -91,6 +91,8 @@ static void PrintHelp(const char* extra_msg) { 979 " the maximum line length can still be exceeded with long\n" 980 " file names (default: 80).\n" 981 " --no_comments: do not add 'why' comments.\n" 982 + " --update_comments: always add 'why' comments, even if no\n" 983 + " #include lines need to be added or removed.\n" 984 " --no_fwd_decls: do not use forward declarations.\n" 985 " --verbose=<level>: the higher the level, the more output.\n" 986 " --quoted_includes_first: when sorting includes, place quoted\n" 987 @@ -163,6 +165,7 @@ CommandlineFlags::CommandlineFlags() 988 prefix_header_include_policy(CommandlineFlags::kAdd), 989 pch_in_code(false), 990 no_comments(false), 991 + update_comments(false), 992 no_fwd_decls(false), 993 quoted_includes_first(false), 994 cxx17ns(false) { 995 @@ -182,6 +185,7 @@ int CommandlineFlags::ParseArgv(int argc, char** argv) { 996 {"pch_in_code", no_argument, nullptr, 'h'}, 997 {"max_line_length", required_argument, nullptr, 'l'}, 998 {"no_comments", no_argument, nullptr, 'o'}, 999 + {"update_comments", no_argument, nullptr, 'u'}, 1000 {"no_fwd_decls", no_argument, nullptr, 'f'}, 1001 {"quoted_includes_first", no_argument, nullptr, 'q' }, 1002 {"cxx17ns", no_argument, nullptr, 'C'}, 1003 @@ -197,6 +201,7 @@ int CommandlineFlags::ParseArgv(int argc, char** argv) { 1004 case 'm': mapping_files.push_back(optarg); break; 1005 case 'n': no_default_mappings = true; break; 1006 case 'o': no_comments = true; break; 1007 + case 'u': update_comments = true; break; 1008 case 'f': no_fwd_decls = true; break; 1009 case 'x': 1010 if (strcmp(optarg, "add") == 0) { 1011 diff --git a/iwyu_globals.h b/iwyu_globals.h 1012 index 242cdf6..eefb8ce 100644 1013 --- a/iwyu_globals.h 1014 +++ b/iwyu_globals.h 1015 @@ -98,6 +98,7 @@ struct CommandlineFlags { 1016 PrefixHeaderIncludePolicy prefix_header_include_policy; 1017 bool pch_in_code; // Treat the first seen include as a PCH. No short option. 1018 bool no_comments; // Disable 'why' comments. No short option. 1019 + bool update_comments; // Force 'why' comments. No short option. 1020 bool no_fwd_decls; // Disable forward declarations. 1021 bool quoted_includes_first; // Place quoted includes first in sort order. 1022 bool cxx17ns; // -C: C++17 nested namespace syntax 1023 diff --git a/iwyu_include_picker.cc b/iwyu_include_picker.cc 1024 index f5d2dbc..77928fa 100644 1025 --- a/iwyu_include_picker.cc 1026 +++ b/iwyu_include_picker.cc 1027 @@ -16,6 +16,7 @@ 1028 // not hash_map: it's not as portable and needs hash<string>. 1029 #include <map> // for map, map<>::mapped_type, etc 1030 #include <memory> 1031 +#include <regex> 1032 #include <string> // for string, basic_string, etc 1033 #include <system_error> // for error_code 1034 #include <utility> // for pair, make_pair 1035 @@ -33,7 +34,6 @@ 1036 #include "llvm/Support/ErrorOr.h" 1037 #include "llvm/Support/FileSystem.h" 1038 #include "llvm/Support/MemoryBuffer.h" 1039 -#include "llvm/Support/Regex.h" 1040 #include "llvm/Support/SourceMgr.h" 1041 #include "llvm/Support/YAMLParser.h" 1042 #include "clang/Basic/FileManager.h" 1043 @@ -89,19 +89,33 @@ const IncludeMapEntry libc_symbol_map[] = { 1044 // an option for this type. That's the preferred #include all else 1045 // equal. The visibility on the symbol-name is ignored; by convention 1046 // we always set it to kPrivate. 1047 - { "blksize_t", kPrivate, "<sys/types.h>", kPublic }, 1048 - { "blkcnt_t", kPrivate, "<sys/stat.h>", kPublic }, 1049 + { "aiocb", kPrivate, "<aio.h>", kPublic }, 1050 { "blkcnt_t", kPrivate, "<sys/types.h>", kPublic }, 1051 + { "blkcnt_t", kPrivate, "<sys/stat.h>", kPublic }, 1052 + { "blksize_t", kPrivate, "<sys/types.h>", kPublic }, 1053 { "blksize_t", kPrivate, "<sys/stat.h>", kPublic }, 1054 + { "cc_t", kPrivate, "<termios.h>", kPublic }, 1055 { "clock_t", kPrivate, "<sys/types.h>", kPublic }, 1056 + { "clock_t", kPrivate, "<sys/time.h>", kPublic }, 1057 { "clock_t", kPrivate, "<time.h>", kPublic }, 1058 + { "clockid_t", kPrivate, "<sys/types.h>", kPublic }, 1059 + { "clockid_t", kPrivate, "<time.h>", kPublic }, 1060 { "daddr_t", kPrivate, "<sys/types.h>", kPublic }, 1061 { "daddr_t", kPrivate, "<rpc/types.h>", kPublic }, 1062 { "dev_t", kPrivate, "<sys/types.h>", kPublic }, 1063 { "dev_t", kPrivate, "<sys/stat.h>", kPublic }, 1064 + { "div_t", kPrivate, "<stdlib.h>", kPublic }, 1065 + { "double_t", kPrivate, "<math.h>", kPublic }, 1066 { "error_t", kPrivate, "<errno.h>", kPublic }, 1067 { "error_t", kPrivate, "<argp.h>", kPublic }, 1068 { "error_t", kPrivate, "<argz.h>", kPublic }, 1069 + { "fd_set", kPrivate, "<sys/select.h>", kPublic }, 1070 + { "fd_set", kPrivate, "<sys/time.h>", kPublic }, 1071 + { "fenv_t", kPrivate, "<fenv.h>", kPublic }, 1072 + { "fexcept_t", kPrivate, "<fenv.h>", kPublic }, 1073 + { "FILE", kPrivate, "<stdio.h>", kPublic }, 1074 + { "FILE", kPrivate, "<wchar.h>", kPublic }, 1075 + { "float_t", kPrivate, "<math.h>", kPublic }, 1076 { "fsblkcnt_t", kPrivate, "<sys/types.h>", kPublic }, 1077 { "fsblkcnt_t", kPrivate, "<sys/statvfs.h>", kPublic }, 1078 { "fsfilcnt_t", kPrivate, "<sys/types.h>", kPublic }, 1079 @@ -109,93 +123,175 @@ const IncludeMapEntry libc_symbol_map[] = { 1080 { "gid_t", kPrivate, "<sys/types.h>", kPublic }, 1081 { "gid_t", kPrivate, "<grp.h>", kPublic }, 1082 { "gid_t", kPrivate, "<pwd.h>", kPublic }, 1083 + { "gid_t", kPrivate, "<signal.h>", kPublic }, 1084 { "gid_t", kPrivate, "<stropts.h>", kPublic }, 1085 { "gid_t", kPrivate, "<sys/ipc.h>", kPublic }, 1086 { "gid_t", kPrivate, "<sys/stat.h>", kPublic }, 1087 { "gid_t", kPrivate, "<unistd.h>", kPublic }, 1088 { "id_t", kPrivate, "<sys/types.h>", kPublic }, 1089 { "id_t", kPrivate, "<sys/resource.h>", kPublic }, 1090 + { "imaxdiv_t", kPrivate, "<inttypes.h>", kPublic }, 1091 + { "intmax_t", kPrivate, "<stdint.h>", kPublic }, 1092 + { "intmax_t", kPrivate, "<inttypes.h>", kPublic }, 1093 + { "uintmax_t", kPrivate, "<stdint.h>", kPublic }, 1094 + { "uintmax_t", kPrivate, "<inttypes.h>", kPublic }, 1095 { "ino64_t", kPrivate, "<sys/types.h>", kPublic }, 1096 { "ino64_t", kPrivate, "<dirent.h>", kPublic }, 1097 { "ino_t", kPrivate, "<sys/types.h>", kPublic }, 1098 { "ino_t", kPrivate, "<dirent.h>", kPublic }, 1099 { "ino_t", kPrivate, "<sys/stat.h>", kPublic }, 1100 - { "int8_t", kPrivate, "<sys/types.h>", kPublic }, 1101 { "int8_t", kPrivate, "<stdint.h>", kPublic }, 1102 + { "int8_t", kPrivate, "<inttypes.h>", kPublic }, 1103 { "int16_t", kPrivate, "<stdint.h>", kPublic }, 1104 + { "int16_t", kPrivate, "<inttypes.h>", kPublic }, 1105 { "int32_t", kPrivate, "<stdint.h>", kPublic }, 1106 + { "int32_t", kPrivate, "<inttypes.h>", kPublic }, 1107 { "int64_t", kPrivate, "<stdint.h>", kPublic }, 1108 + { "int64_t", kPrivate, "<inttypes.h>", kPublic }, 1109 { "uint8_t", kPrivate, "<stdint.h>", kPublic }, 1110 + { "uint8_t", kPrivate, "<inttypes.h>", kPublic }, 1111 { "uint16_t", kPrivate, "<stdint.h>", kPublic }, 1112 + { "uint16_t", kPrivate, "<inttypes.h>", kPublic }, 1113 { "uint32_t", kPrivate, "<stdint.h>", kPublic }, 1114 + { "uint32_t", kPrivate, "<inttypes.h>", kPublic }, 1115 { "uint64_t", kPrivate, "<stdint.h>", kPublic }, 1116 + { "uint64_t", kPrivate, "<inttypes.h>", kPublic }, 1117 { "intptr_t", kPrivate, "<stdint.h>", kPublic }, 1118 + { "intptr_t", kPrivate, "<inttypes.h>", kPublic }, 1119 { "uintptr_t", kPrivate, "<stdint.h>", kPublic }, 1120 - { "intptr_t", kPrivate, "<unistd.h>", kPublic }, 1121 + { "uintptr_t", kPrivate, "<inttypes.h>", kPublic }, 1122 { "key_t", kPrivate, "<sys/types.h>", kPublic }, 1123 { "key_t", kPrivate, "<sys/ipc.h>", kPublic }, 1124 + { "lconv", kPrivate, "<locale.h>", kPublic }, 1125 + { "ldiv_t", kPrivate, "<stdlib.h>", kPublic }, 1126 + { "lldiv_t", kPrivate, "<stdlib.h>", kPublic }, 1127 { "max_align_t", kPrivate, "<stddef.h>", kPublic }, 1128 { "mode_t", kPrivate, "<sys/types.h>", kPublic }, 1129 - { "mode_t", kPrivate, "<sys/stat.h>", kPublic }, 1130 + { "mode_t", kPrivate, "<fcntl.h>", kPublic }, 1131 + { "mode_t", kPrivate, "<ndbm.h>", kPublic }, 1132 + { "mode_t", kPrivate, "<spawn.h>", kPublic }, 1133 { "mode_t", kPrivate, "<sys/ipc.h>", kPublic }, 1134 { "mode_t", kPrivate, "<sys/mman.h>", kPublic }, 1135 + { "mode_t", kPrivate, "<sys/stat.h>", kPublic }, 1136 { "nlink_t", kPrivate, "<sys/types.h>", kPublic }, 1137 { "nlink_t", kPrivate, "<sys/stat.h>", kPublic }, 1138 { "off64_t", kPrivate, "<sys/types.h>", kPublic }, 1139 { "off64_t", kPrivate, "<unistd.h>", kPublic }, 1140 { "off_t", kPrivate, "<sys/types.h>", kPublic }, 1141 - { "off_t", kPrivate, "<unistd.h>", kPublic }, 1142 - { "off_t", kPrivate, "<sys/stat.h>", kPublic }, 1143 + { "off_t", kPrivate, "<aio.h>", kPublic }, 1144 + { "off_t", kPrivate, "<fcntl.h>", kPublic }, 1145 + { "off_t", kPrivate, "<stdio.h>", kPublic }, 1146 { "off_t", kPrivate, "<sys/mman.h>", kPublic }, 1147 + { "off_t", kPrivate, "<sys/stat.h>", kPublic }, 1148 + { "off_t", kPrivate, "<unistd.h>", kPublic }, 1149 { "pid_t", kPrivate, "<sys/types.h>", kPublic }, 1150 - { "pid_t", kPrivate, "<unistd.h>", kPublic }, 1151 + { "pid_t", kPrivate, "<fcntl.h>", kPublic }, 1152 + { "pid_t", kPrivate, "<sched.h>", kPublic }, 1153 { "pid_t", kPrivate, "<signal.h>", kPublic }, 1154 + { "pid_t", kPrivate, "<spawn.h>", kPublic }, 1155 { "pid_t", kPrivate, "<sys/msg.h>", kPublic }, 1156 + { "pid_t", kPrivate, "<sys/sem.h>", kPublic }, 1157 { "pid_t", kPrivate, "<sys/shm.h>", kPublic }, 1158 + { "pid_t", kPrivate, "<sys/wait.h>", kPublic }, 1159 { "pid_t", kPrivate, "<termios.h>", kPublic }, 1160 { "pid_t", kPrivate, "<time.h>", kPublic }, 1161 + { "pid_t", kPrivate, "<unistd.h>", kPublic }, 1162 { "pid_t", kPrivate, "<utmpx.h>", kPublic }, 1163 { "ptrdiff_t", kPrivate, "<stddef.h>", kPublic }, 1164 + { "regex_t", kPrivate, "<regex.h>", kPublic }, 1165 + { "regmatch_t", kPrivate, "<regex.h>", kPublic }, 1166 + { "regoff_t", kPrivate, "<regex.h>", kPublic }, 1167 + { "sigevent", kPrivate, "<signal.h>", kPublic }, 1168 + { "sigevent", kPrivate, "<aio.h>", kPublic }, 1169 + { "sigevent", kPrivate, "<mqueue.h>", kPublic }, 1170 + { "sigevent", kPrivate, "<time.h>", kPublic }, 1171 + { "siginfo_t", kPrivate, "<signal.h>", kPublic }, 1172 + { "siginfo_t", kPrivate, "<sys/wait.h>", kPublic }, 1173 { "sigset_t", kPrivate, "<signal.h>", kPublic }, 1174 - { "sigset_t", kPrivate, "<sys/epoll.h>", kPublic }, 1175 + { "sigset_t", kPrivate, "<spawn.h>", kPublic }, 1176 { "sigset_t", kPrivate, "<sys/select.h>", kPublic }, 1177 - { "socklen_t", kPrivate, "<bits/socket.h>", kPrivate }, 1178 - { "socklen_t", kPrivate, "<unistd.h>", kPublic }, 1179 - { "socklen_t", kPrivate, "<arpa/inet.h>", kPublic }, 1180 + { "sigval", kPrivate, "<signal.h>", kPublic }, 1181 + { "sockaddr", kPrivate, "<sys/socket.h>", kPublic }, 1182 + { "socklen_t", kPrivate, "<sys/socket.h>", kPublic }, 1183 + { "socklen_t", kPrivate, "<netdb.h>", kPublic }, 1184 { "ssize_t", kPrivate, "<sys/types.h>", kPublic }, 1185 - { "ssize_t", kPrivate, "<unistd.h>", kPublic }, 1186 + { "ssize_t", kPrivate, "<aio.h>", kPublic }, 1187 { "ssize_t", kPrivate, "<monetary.h>", kPublic }, 1188 + { "ssize_t", kPrivate, "<mqueue.h>", kPublic }, 1189 + { "ssize_t", kPrivate, "<stdio.h>", kPublic }, 1190 { "ssize_t", kPrivate, "<sys/msg.h>", kPublic }, 1191 + { "ssize_t", kPrivate, "<sys/socket.h>", kPublic }, 1192 + { "ssize_t", kPrivate, "<sys/uio.h>", kPublic }, 1193 + { "ssize_t", kPrivate, "<unistd.h>", kPublic }, 1194 { "suseconds_t", kPrivate, "<sys/types.h>", kPublic }, 1195 - { "suseconds_t", kPrivate, "<sys/time.h>", kPublic }, 1196 { "suseconds_t", kPrivate, "<sys/select.h>", kPublic }, 1197 - { "time_t", kPrivate, "<sys/types.h>", kPublic }, 1198 + { "suseconds_t", kPrivate, "<sys/time.h>", kPublic }, 1199 { "time_t", kPrivate, "<time.h>", kPublic }, 1200 + { "time_t", kPrivate, "<sched.h>", kPublic }, 1201 + { "time_t", kPrivate, "<sys/msg.h>", kPublic }, 1202 + { "time_t", kPrivate, "<sys/select.h>", kPublic }, 1203 + { "time_t", kPrivate, "<sys/sem.h>", kPublic }, 1204 + { "time_t", kPrivate, "<sys/shm.h>", kPublic }, 1205 + { "time_t", kPrivate, "<sys/stat.h>", kPublic }, 1206 + { "time_t", kPrivate, "<sys/time.h>", kPublic }, 1207 + { "time_t", kPrivate, "<sys/types.h>", kPublic }, 1208 + { "time_t", kPrivate, "<utime.h>", kPublic }, 1209 + { "timer_t", kPrivate, "<sys/types.h>", kPublic }, 1210 + { "timer_t", kPrivate, "<time.h>", kPublic }, 1211 { "timespec", kPrivate, "<time.h>", kPublic }, 1212 + { "timespec", kPrivate, "<aio.h>", kPublic }, 1213 + { "timespec", kPrivate, "<mqueue.h>", kPublic }, 1214 + { "timespec", kPrivate, "<sched.h>", kPublic }, 1215 + { "timespec", kPrivate, "<signal.h>", kPublic }, 1216 + { "timespec", kPrivate, "<sys/select.h>", kPublic }, 1217 + { "timespec", kPrivate, "<sys/stat.h>", kPublic }, 1218 { "timeval", kPrivate, "<sys/time.h>", kPublic }, 1219 + { "timeval", kPrivate, "<sys/resource.h>", kPublic }, 1220 + { "timeval", kPrivate, "<sys/select.h>", kPublic }, 1221 + { "timeval", kPrivate, "<utmpx.h>", kPublic }, 1222 { "u_char", kPrivate, "<sys/types.h>", kPublic }, 1223 { "u_char", kPrivate, "<rpc/types.h>", kPublic }, 1224 { "uid_t", kPrivate, "<sys/types.h>", kPublic }, 1225 - { "uid_t", kPrivate, "<unistd.h>", kPublic }, 1226 { "uid_t", kPrivate, "<pwd.h>", kPublic }, 1227 { "uid_t", kPrivate, "<signal.h>", kPublic }, 1228 { "uid_t", kPrivate, "<stropts.h>", kPublic }, 1229 { "uid_t", kPrivate, "<sys/ipc.h>", kPublic }, 1230 { "uid_t", kPrivate, "<sys/stat.h>", kPublic }, 1231 + { "uid_t", kPrivate, "<unistd.h>", kPublic }, 1232 { "useconds_t", kPrivate, "<sys/types.h>", kPublic }, 1233 { "useconds_t", kPrivate, "<unistd.h>", kPublic }, 1234 { "wchar_t", kPrivate, "<stddef.h>", kPublic }, 1235 { "wchar_t", kPrivate, "<stdlib.h>", kPublic }, 1236 - // glob.h seems to define size_t if necessary, but it should come from stddef. 1237 // It is unspecified if the cname headers provide ::size_t. 1238 // <locale.h> is the one header which defines NULL but not size_t. 1239 { "size_t", kPrivate, "<stddef.h>", kPublic }, // 'canonical' location for size_t 1240 + { "size_t", kPrivate, "<aio.h>", kPublic }, 1241 + { "size_t", kPrivate, "<glob.h>", kPublic }, 1242 + { "size_t", kPrivate, "<grp.h>", kPublic }, 1243 + { "size_t", kPrivate, "<iconv.h>", kPublic }, 1244 + { "size_t", kPrivate, "<monetary.h>", kPublic }, 1245 + { "size_t", kPrivate, "<mqueue.h>", kPublic }, 1246 + { "size_t", kPrivate, "<ndbm.h>", kPublic }, 1247 + { "size_t", kPrivate, "<pwd.h>", kPublic }, 1248 + { "size_t", kPrivate, "<regex.h>", kPublic }, 1249 + { "size_t", kPrivate, "<search.h>", kPublic }, 1250 + { "size_t", kPrivate, "<signal.h>", kPublic }, 1251 { "size_t", kPrivate, "<stdio.h>", kPublic }, 1252 { "size_t", kPrivate, "<stdlib.h>", kPublic }, 1253 { "size_t", kPrivate, "<string.h>", kPublic }, 1254 + { "size_t", kPrivate, "<strings.h>", kPublic }, 1255 + { "size_t", kPrivate, "<sys/mman.h>", kPublic }, 1256 + { "size_t", kPrivate, "<sys/msg.h>", kPublic }, 1257 + { "size_t", kPrivate, "<sys/sem.h>", kPublic }, 1258 + { "size_t", kPrivate, "<sys/shm.h>", kPublic }, 1259 + { "size_t", kPrivate, "<sys/socket.h>", kPublic }, 1260 + { "size_t", kPrivate, "<sys/types.h>", kPublic }, 1261 + { "size_t", kPrivate, "<sys/uio.h>", kPublic }, 1262 { "size_t", kPrivate, "<time.h>", kPublic }, 1263 { "size_t", kPrivate, "<uchar.h>", kPublic }, 1264 + { "size_t", kPrivate, "<unistd.h>", kPublic }, 1265 { "size_t", kPrivate, "<wchar.h>", kPublic }, 1266 + { "size_t", kPrivate, "<wordexp.h>", kPublic }, 1267 // Macros that can be defined in more than one file, don't have the 1268 // same __foo_defined guard that other types do, so the grep above 1269 // doesn't discover them. Until I figure out a better way, I just 1270 @@ -204,6 +300,8 @@ const IncludeMapEntry libc_symbol_map[] = { 1271 { "EOF", kPrivate, "<libio.h>", kPublic }, 1272 { "FILE", kPrivate, "<stdio.h>", kPublic }, 1273 { "va_list", kPrivate, "<stdarg.h>", kPublic }, 1274 + { "va_list", kPrivate, "<stdio.h>", kPublic }, 1275 + { "va_list", kPrivate, "<wchar.h>", kPublic }, 1276 // These are symbols that could be defined in either stdlib.h or 1277 // malloc.h, but we always want the stdlib location. 1278 { "malloc", kPrivate, "<stdlib.h>", kPublic }, 1279 @@ -1315,16 +1413,17 @@ void IncludePicker::ExpandRegexes() { 1280 for (const string& regex_key : filepath_include_map_regex_keys) { 1281 const vector<MappedInclude>& map_to = filepath_include_map_[regex_key]; 1282 // Enclose the regex in ^(...)$ for full match. 1283 - llvm::Regex regex(std::string("^(" + regex_key.substr(1) + ")$")); 1284 - if (regex.match(hdr, nullptr) && !ContainsQuotedInclude(map_to, hdr)) { 1285 + std::regex regex(std::string("^(" + regex_key.substr(1) + ")$")); 1286 + if (std::regex_match(hdr, regex) && 1287 + !ContainsQuotedInclude(map_to, hdr)) { 1288 Extend(&filepath_include_map_[hdr], filepath_include_map_[regex_key]); 1289 MarkVisibility(&include_visibility_map_, hdr, 1290 include_visibility_map_[regex_key]); 1291 } 1292 } 1293 for (const string& regex_key : friend_to_headers_map_regex_keys) { 1294 - llvm::Regex regex(std::string("^(" + regex_key.substr(1) + ")$")); 1295 - if (regex.match(hdr, nullptr)) { 1296 + std::regex regex(std::string("^(" + regex_key.substr(1) + ")$")); 1297 + if (std::regex_match(hdr, regex)) { 1298 InsertAllInto(friend_to_headers_map_[regex_key], 1299 &friend_to_headers_map_[hdr]); 1300 } 1301 diff --git a/iwyu_output.cc b/iwyu_output.cc 1302 index e6bb851..d805242 100644 1303 --- a/iwyu_output.cc 1304 +++ b/iwyu_output.cc 1305 @@ -1161,7 +1161,7 @@ void ProcessFullUse(OneUse* use, 1306 // We normally ignore uses for builtins, but when there is a mapping defined 1307 // for the symbol, we should respect that. So, we need to determine whether 1308 // the symbol has any mappings. 1309 - bool is_builtin_function = IsBuiltinFunction(use->decl(), use->symbol_name()); 1310 + bool is_builtin_function = IsBuiltinFunction(use->decl()); 1311 1312 bool is_builtin_function_with_mappings = 1313 is_builtin_function && HasMapping(use->symbol_name()); 1314 @@ -1987,7 +1987,7 @@ size_t PrintableDiffs(const string& filename, 1315 break; 1316 } 1317 } 1318 - if (no_adds_or_deletes) { 1319 + if (no_adds_or_deletes && !GlobalFlags().update_comments) { 1320 output = "\n(" + filename + " has correct #includes/fwd-decls)\n"; 1321 return 0; 1322 } 1323 diff --git a/iwyu_port.h b/iwyu_port.h 1324 index d890575..e1fabb3 100644 1325 --- a/iwyu_port.h 1326 +++ b/iwyu_port.h 1327 @@ -26,7 +26,7 @@ class FatalMessageEmitter { 1328 FatalMessageEmitter(const char* file, int line, const char* message) { 1329 stream() << file << ":" << line << ": Assertion failed: " << message; 1330 } 1331 - LLVM_ATTRIBUTE_NORETURN ~FatalMessageEmitter() { 1332 + [[noreturn]] ~FatalMessageEmitter() { 1333 stream() << "\n"; 1334 ::abort(); 1335 #ifdef LLVM_BUILTIN_UNREACHABLE 1336 diff --git a/iwyu_preprocessor.cc b/iwyu_preprocessor.cc 1337 index 6dc70bf..dc72b2b 100644 1338 --- a/iwyu_preprocessor.cc 1339 +++ b/iwyu_preprocessor.cc 1340 @@ -34,7 +34,6 @@ 1341 #include "clang/Lex/MacroInfo.h" 1342 1343 using clang::FileEntry; 1344 -using clang::FileEntryRef; 1345 using clang::FileID; 1346 using clang::MacroDefinition; 1347 using clang::MacroDirective; 1348 @@ -704,7 +703,7 @@ void IwyuPreprocessorInfo::FileChanged(SourceLocation loc, 1349 // Called when we see an #include, but decide we don't need to 1350 // actually read it because it's already been #included (and is 1351 // protected by a header guard). 1352 -void IwyuPreprocessorInfo::FileSkipped(const FileEntryRef& file, 1353 +void IwyuPreprocessorInfo::FileSkipped(const FileEntry& file, 1354 const Token &filename, 1355 SrcMgr::CharacteristicKind file_type) { 1356 CHECK_(include_filename_loc_.isValid() && 1357 @@ -715,11 +714,11 @@ void IwyuPreprocessorInfo::FileSkipped(const FileEntryRef& file, 1358 GetInstantiationLoc(filename.getLocation()); 1359 ERRSYM(GetFileEntry(include_loc)) 1360 << "[ (#include) ] " << include_name_as_written 1361 - << " (" << GetFilePath(&file.getFileEntry()) << ")\n"; 1362 + << " (" << GetFilePath(&file) << ")\n"; 1363 1364 - AddDirectInclude(include_loc, &file.getFileEntry(), include_name_as_written); 1365 - if (ShouldReportIWYUViolationsFor(&file.getFileEntry())) { 1366 - files_to_report_iwyu_violations_for_.insert(&file.getFileEntry()); 1367 + AddDirectInclude(include_loc, &file, include_name_as_written); 1368 + if (ShouldReportIWYUViolationsFor(&file)) { 1369 + files_to_report_iwyu_violations_for_.insert(&file); 1370 } 1371 } 1372 1373 diff --git a/iwyu_preprocessor.h b/iwyu_preprocessor.h 1374 index c46dbc9..00073ce 100644 1375 --- a/iwyu_preprocessor.h 1376 +++ b/iwyu_preprocessor.h 1377 @@ -203,7 +203,7 @@ class IwyuPreprocessorInfo : public clang::PPCallbacks, 1378 void FileChanged(clang::SourceLocation loc, FileChangeReason reason, 1379 clang::SrcMgr::CharacteristicKind file_type, 1380 clang::FileID exiting_from_id) override; 1381 - void FileSkipped(const clang::FileEntryRef& file, const clang::Token &filename, 1382 + void FileSkipped(const clang::FileEntry& file, const clang::Token &filename, 1383 clang::SrcMgr::CharacteristicKind file_type) override; 1384 // FileChanged is actually a multi-plexer for 4 different callbacks. 1385 void FileChanged_EnterFile(clang::SourceLocation file_beginning); 1386 diff --git a/iwyu_tool.py b/iwyu_tool.py 1387 index eaf0abc..45b2a4a 100755 1388 --- a/iwyu_tool.py 1389 +++ b/iwyu_tool.py 1390 @@ -42,6 +42,7 @@ import subprocess 1391 1392 CORRECT_RE = re.compile(r'^\((.*?) has correct #includes/fwd-decls\)$') 1393 SHOULD_ADD_RE = re.compile(r'^(.*?) should add these lines:$') 1394 +ADD_RE = re.compile('^(.*?) +// (.*)$') 1395 SHOULD_REMOVE_RE = re.compile(r'^(.*?) should remove these lines:$') 1396 FULL_LIST_RE = re.compile(r'The full include-list for (.*?):$') 1397 END_RE = re.compile(r'^---$') 1398 @@ -80,14 +81,17 @@ def clang_formatter(output): 1399 elif state[0] == GENERAL: 1400 formatted.append(line) 1401 elif state[0] == ADD: 1402 - formatted.append('%s:1:1: error: add the following line' % state[1]) 1403 - formatted.append(line) 1404 + match = ADD_RE.match(line) 1405 + if match: 1406 + formatted.append("%s:1:1: error: add '%s' (%s)" % 1407 + (state[1], match.group(1), match.group(2))) 1408 + else: 1409 + formatted.append("%s:1:1: error: add '%s'" % (state[1], line)) 1410 elif state[0] == REMOVE: 1411 match = LINES_RE.match(line) 1412 line_no = match.group(2) if match else '1' 1413 - formatted.append('%s:%s:1: error: remove the following line' % 1414 - (state[1], line_no)) 1415 - formatted.append(match.group(1)) 1416 + formatted.append("%s:%s:1: error: superfluous '%s'" % 1417 + (state[1], line_no, match.group(1))) 1418 1419 return os.linesep.join(formatted) 1420 1421 diff --git a/iwyu_version.h b/iwyu_version.h 1422 index 12a451f..7c3b41c 100644 1423 --- a/iwyu_version.h 1424 +++ b/iwyu_version.h 1425 @@ -10,6 +10,6 @@ 1426 #ifndef INCLUDE_WHAT_YOU_USE_IWYU_VERSION_H_ 1427 #define INCLUDE_WHAT_YOU_USE_IWYU_VERSION_H_ 1428 1429 -#define IWYU_VERSION_STRING "0.16" 1430 +#define IWYU_VERSION_STRING "0.17" 1431 1432 #endif // INCLUDE_WHAT_YOU_USE_IWYU_VERSION_H_ 1433 diff --git a/tests/c/libbuiltins-direct.h b/tests/c/libbuiltins-direct.h 1434 new file mode 100644 1435 index 0000000..eef6b58 1436 --- /dev/null 1437 +++ b/tests/c/libbuiltins-direct.h 1438 @@ -0,0 +1,10 @@ 1439 +//===--- libbuiltins-direct.h - test input file for iwyu ------------------===// 1440 +// 1441 +// The LLVM Compiler Infrastructure 1442 +// 1443 +// This file is distributed under the University of Illinois Open Source 1444 +// License. See LICENSE.TXT for details. 1445 +// 1446 +//===----------------------------------------------------------------------===// 1447 + 1448 +#include <math.h> 1449 diff --git a/tests/c/libbuiltins.c b/tests/c/libbuiltins.c 1450 new file mode 100644 1451 index 0000000..4ba3033 1452 --- /dev/null 1453 +++ b/tests/c/libbuiltins.c 1454 @@ -0,0 +1,34 @@ 1455 +//===--- libbuiltins.c - test input file for iwyu -------------------------===// 1456 +// 1457 +// The LLVM Compiler Infrastructure 1458 +// 1459 +// This file is distributed under the University of Illinois Open Source 1460 +// License. See LICENSE.TXT for details. 1461 +// 1462 +//===----------------------------------------------------------------------===// 1463 + 1464 +// Library builtins are, like normal builtins, compiled down to an intrinsic, 1465 +// but a header still needs to be included for the program to be valid. The math 1466 +// library (pow, round, etc) is a typical example. 1467 + 1468 +// IWYU_ARGS: -I . 1469 + 1470 +#include "tests/c/libbuiltins-direct.h" 1471 + 1472 +float kapow(float x) { 1473 + // IWYU: pow is...*math.h 1474 + return pow(x, 2.0F); 1475 +} 1476 + 1477 +/**** IWYU_SUMMARY 1478 + 1479 +tests/c/libbuiltins.c should add these lines: 1480 +#include <math.h> 1481 + 1482 +tests/c/libbuiltins.c should remove these lines: 1483 +- #include "tests/c/libbuiltins-direct.h" // lines XX-XX 1484 + 1485 +The full include-list for tests/c/libbuiltins.c: 1486 +#include <math.h> // for pow 1487 + 1488 +***** IWYU_SUMMARY */ 1489 diff --git a/tests/cxx/badinc.cc b/tests/cxx/badinc.cc 1490 index e58a98f..3c3c3aa 100644 1491 --- a/tests/cxx/badinc.cc 1492 +++ b/tests/cxx/badinc.cc 1493 @@ -1094,8 +1094,10 @@ int main() { 1494 // IWYU: I1_PtrDereferenceClass needs a declaration 1495 I1_PtrDereferenceClass* local_i1_ptrdereference_class = 0; 1496 int x; 1497 - // IWYU: va_list is...*<stdarg.h> 1498 - va_list vl; // in gcc, va_list is an internal type, so this tests <built-in> 1499 + // va_list is normally in <stdarg.h>, but we already have <stdio.h> 1500 + // available, so mappings will source it from there. 1501 + // IWYU: va_list is...*<stdio.h> 1502 + va_list vl; 1503 D1_I1_Typedef d1_i1_typedef; 1504 // IWYU: i1_int is...*badinc-i1.h 1505 int vararray[i1_int]; 1506 @@ -1859,7 +1861,6 @@ int main() { 1507 1508 tests/cxx/badinc.cc should add these lines: 1509 #include <ctype.h> 1510 -#include <stdarg.h> 1511 #include <stddef.h> 1512 #include <list> 1513 #include "tests/cxx/badinc-i1.h" 1514 @@ -1889,7 +1890,6 @@ The full include-list for tests/cxx/badinc.cc: 1515 #include "tests/cxx/badinc-inl.h" 1516 #include <ctype.h> // for isascii 1517 #include <setjmp.h> 1518 -#include <stdarg.h> // for va_list 1519 #include <stddef.h> // for offsetof 1520 #include <algorithm> // for find 1521 #include <fstream> // for fstream 1522 diff --git a/tests/cxx/ctad-d1.h b/tests/cxx/ctad-d1.h 1523 new file mode 100644 1524 index 0000000..c492fde 1525 --- /dev/null 1526 +++ b/tests/cxx/ctad-d1.h 1527 @@ -0,0 +1,10 @@ 1528 +//===--- ctad-d1.h - test input file for iwyu -----------------------------===// 1529 +// 1530 +// The LLVM Compiler Infrastructure 1531 +// 1532 +// This file is distributed under the University of Illinois Open Source 1533 +// License. See LICENSE.TXT for details. 1534 +// 1535 +//===----------------------------------------------------------------------===// 1536 + 1537 +#include "tests/cxx/ctad-i1.h" 1538 diff --git a/tests/cxx/ctad-i1.h b/tests/cxx/ctad-i1.h 1539 new file mode 100644 1540 index 0000000..defd3f0 1541 --- /dev/null 1542 +++ b/tests/cxx/ctad-i1.h 1543 @@ -0,0 +1,20 @@ 1544 +//===--- ctad-i1.h - test input file for iwyu -----------------------------===// 1545 +// 1546 +// The LLVM Compiler Infrastructure 1547 +// 1548 +// This file is distributed under the University of Illinois Open Source 1549 +// License. See LICENSE.TXT for details. 1550 +// 1551 +//===----------------------------------------------------------------------===// 1552 + 1553 +template <class Func> 1554 +struct Deduced { 1555 + Deduced(Func&& deferred) : deferred(deferred) { 1556 + } 1557 + 1558 + ~Deduced() { 1559 + deferred(); 1560 + } 1561 + 1562 + Func deferred; 1563 +}; 1564 diff --git a/tests/cxx/ctad.cc b/tests/cxx/ctad.cc 1565 new file mode 100644 1566 index 0000000..792343b 1567 --- /dev/null 1568 +++ b/tests/cxx/ctad.cc 1569 @@ -0,0 +1,33 @@ 1570 +//===--- ctad.cc - test input file for iwyu -------------------------------===// 1571 +// 1572 +// The LLVM Compiler Infrastructure 1573 +// 1574 +// This file is distributed under the University of Illinois Open Source 1575 +// License. See LICENSE.TXT for details. 1576 +// 1577 +//===----------------------------------------------------------------------===// 1578 + 1579 +// IWYU_ARGS: -I . -std=c++17 1580 + 1581 +// Test that C++17 CTAD (Class Template Argument Deduction) is recognized as 1582 +// pointing back to a template, even if it's not explicitly specialized. 1583 + 1584 +#include "tests/cxx/ctad-d1.h" 1585 + 1586 +void f() { 1587 + // IWYU: Deduced is...*ctad-i1.h 1588 + Deduced d([] {}); 1589 +} 1590 + 1591 +/**** IWYU_SUMMARY 1592 + 1593 +tests/cxx/ctad.cc should add these lines: 1594 +#include "tests/cxx/ctad-i1.h" 1595 + 1596 +tests/cxx/ctad.cc should remove these lines: 1597 +- #include "tests/cxx/ctad-d1.h" // lines XX-XX 1598 + 1599 +The full include-list for tests/cxx/ctad.cc: 1600 +#include "tests/cxx/ctad-i1.h" // for Deduced 1601 + 1602 +***** IWYU_SUMMARY */ 1603 diff --git a/tests/cxx/iwyu_stricter_than_cpp-type_alias.h b/tests/cxx/iwyu_stricter_than_cpp-type_alias.h 1604 new file mode 100644 1605 index 0000000..3256f55 1606 --- /dev/null 1607 +++ b/tests/cxx/iwyu_stricter_than_cpp-type_alias.h 1608 @@ -0,0 +1,76 @@ 1609 +//===--- iwyu_stricter_than_cpp-type_alias.h - test input file for iwyu ---===// 1610 +// 1611 +// The LLVM Compiler Infrastructure 1612 +// 1613 +// This file is distributed under the University of Illinois Open Source 1614 +// License. See LICENSE.TXT for details. 1615 +// 1616 +//===----------------------------------------------------------------------===// 1617 + 1618 +// The two rules the author has to follow to disable iwyu's 1619 +// stricter-than-C++ rule and force it to fall back on the c++ 1620 +// requirement (forward-declare ok): 1621 +// (1) forward-declare the relevant type 1622 +// (2) do not directly #include the definition of the relevant type. 1623 + 1624 +#include "tests/cxx/iwyu_stricter_than_cpp-d1.h" 1625 + 1626 +// --- Type aliases. 1627 + 1628 +// Requires the full type because it does not obey rule (1) 1629 +// IWYU: IndirectStruct1 is...*iwyu_stricter_than_cpp-i1.h 1630 +using DoesNotForwardDeclareAl = IndirectStruct1; 1631 + 1632 +// This also does not obey rule (1): it's -d1 that does the fwd-declaring. 1633 +// IWYU: IndirectStructForwardDeclaredInD1 is...*iwyu_stricter_than_cpp-i1.h 1634 +using DoesNotForwardDeclareProperlyAl = IndirectStructForwardDeclaredInD1; 1635 + 1636 +// Requires the full type because it does not obey rule (2) 1637 +struct DirectStruct1; 1638 +using IncludesAl = DirectStruct1; 1639 + 1640 +// Requires the full type because it does not obey rules (1) *or* (2) 1641 +using DoesNotForwardDeclareAndIncludesAl = DirectStruct2; 1642 + 1643 +// Does not require full type because it obeys all the rules. 1644 +struct IndirectStruct2; 1645 +using DoesEverythingRightAl = IndirectStruct2; 1646 + 1647 +// --- Now do it all again, with templates! 1648 + 1649 +// IWYU: TplIndirectStruct1 is...*iwyu_stricter_than_cpp-i1.h 1650 +using TplDoesNotForwardDeclareAl = TplIndirectStruct1<int>; 1651 + 1652 +using TplDoesNotForwardDeclareProperlyAl 1653 +// IWYU: TplIndirectStructForwardDeclaredInD1 is...*iwyu_stricter_than_cpp-i1.h 1654 + = TplIndirectStructForwardDeclaredInD1<int>; 1655 + 1656 +template <typename T> struct TplDirectStruct1; 1657 +using TplIncludesAl = TplDirectStruct1<int>; 1658 + 1659 +using TplDoesNotForwardDeclareAndIncludesAl = TplDirectStruct2<int>; 1660 + 1661 +template <typename T> struct TplIndirectStruct2; 1662 +using TplDoesEverythingRightAl = TplIndirectStruct2<int>; 1663 + 1664 +// Another way to forward-declare a class template. 1665 +template <> struct TplIndirectStruct2<float>; 1666 +using TplDoesEverythingRightAgainAl = TplIndirectStruct2<float>; 1667 + 1668 + 1669 +/**** IWYU_SUMMARY 1670 + 1671 +tests/cxx/iwyu_stricter_than_cpp-type_alias.h should add these lines: 1672 +#include "tests/cxx/iwyu_stricter_than_cpp-i1.h" 1673 + 1674 +tests/cxx/iwyu_stricter_than_cpp-type_alias.h should remove these lines: 1675 +- struct DirectStruct1; // lines XX-XX 1676 +- template <typename T> struct TplDirectStruct1; // lines XX-XX 1677 + 1678 +The full include-list for tests/cxx/iwyu_stricter_than_cpp-type_alias.h: 1679 +#include "tests/cxx/iwyu_stricter_than_cpp-d1.h" // for DirectStruct1, DirectStruct2, TplDirectStruct1, TplDirectStruct2 1680 +#include "tests/cxx/iwyu_stricter_than_cpp-i1.h" // for IndirectStruct1, IndirectStructForwardDeclaredInD1, TplIndirectStruct1, TplIndirectStructForwardDeclaredInD1 1681 +struct IndirectStruct2; // lines XX-XX 1682 +template <typename T> struct TplIndirectStruct2; // lines XX-XX 1683 + 1684 +***** IWYU_SUMMARY */ 1685 diff --git a/tests/cxx/iwyu_stricter_than_cpp.cc b/tests/cxx/iwyu_stricter_than_cpp.cc 1686 index d6f70d8..2bfa1c1 100644 1687 --- a/tests/cxx/iwyu_stricter_than_cpp.cc 1688 +++ b/tests/cxx/iwyu_stricter_than_cpp.cc 1689 @@ -10,6 +10,7 @@ 1690 // IWYU_ARGS: -Xiwyu --check_also="tests/cxx/*-autocast.h" \ 1691 // -Xiwyu --check_also="tests/cxx/*-fnreturn.h" \ 1692 // -Xiwyu --check_also="tests/cxx/*-typedefs.h" \ 1693 +// -Xiwyu --check_also="tests/cxx/*-type_alias.h" \ 1694 // -Xiwyu --check_also="tests/cxx/*-d2.h" \ 1695 // -I . 1696 1697 @@ -36,6 +37,7 @@ 1698 // when these two conditions are met, and not otherwise. 1699 1700 #include "tests/cxx/iwyu_stricter_than_cpp-typedefs.h" 1701 +#include "tests/cxx/iwyu_stricter_than_cpp-type_alias.h" 1702 #include "tests/cxx/iwyu_stricter_than_cpp-autocast.h" 1703 #include "tests/cxx/iwyu_stricter_than_cpp-fnreturn.h" 1704 // We include this so the second declaration of TwiceDeclaredFunction 1705 @@ -81,6 +83,39 @@ void TestTypedefs() { 1706 // all) of the template args as well. 1707 } 1708 1709 +using DoubleTypedefAl = DoesEverythingRightAl; 1710 + 1711 +void TestTypeAliases() { 1712 + DoesNotForwardDeclareAl dnfd(1); 1713 + DoesNotForwardDeclareProperlyAl dnfdp(2); 1714 + IncludesAl i(3); 1715 + DoesNotForwardDeclareAndIncludesAl dnfdai(4); 1716 + // IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1717 + DoesEverythingRightAl dor(5); 1718 + // Because DoubleTypedefAl resolves to DoesEverythingRightAl, we need the 1719 + // same things DoesEverythingRightAl does. 1720 + // IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1721 + DoubleTypedefAl dt(6); 1722 + 1723 + // ...and with templates. 1724 + TplDoesNotForwardDeclareAl tdnfd(7); 1725 + TplDoesNotForwardDeclareProperlyAl tdnfdp(8); 1726 + TplIncludesAl ti(9); 1727 + TplDoesNotForwardDeclareAndIncludesAl tdnfdai(10); 1728 + // IWYU: TplIndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1729 + TplDoesEverythingRightAl tdor(11); 1730 + // IWYU: TplIndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1731 + TplDoesEverythingRightAgainAl tdora(12); 1732 + 1733 + // But if we're in a forward-declare context, we don't require the 1734 + // underlying type! 1735 + DoesEverythingRightAl* dor_ptr = 0; 1736 + TplDoesEverythingRightAgainAl* tdora_ptr = 0; 1737 + // ...at least until we dereference the pointer 1738 + // IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1739 + (void) dor_ptr->a; 1740 +} 1741 + 1742 void TestAutocast() { 1743 // We need full type of is2 because the declarer of Fn didn't 1744 // IWYU: IndirectStruct2 is...*iwyu_stricter_than_cpp-i2.h 1745 @@ -159,6 +194,7 @@ The full include-list for tests/cxx/iwyu_stricter_than_cpp.cc: 1746 #include "tests/cxx/iwyu_stricter_than_cpp-autocast.h" // for Fn, TplFn 1747 #include "tests/cxx/iwyu_stricter_than_cpp-fnreturn.h" // for DoesEverythingRightFn, DoesNotForwardDeclareAndIncludesFn, DoesNotForwardDeclareFn, DoesNotForwardDeclareProperlyFn, IncludesFn, TplDoesEverythingRightAgainFn, TplDoesEverythingRightFn, TplDoesNotForwardDeclareAndIncludesFn, TplDoesNotForwardDeclareFn, TplDoesNotForwardDeclareProperlyFn, TplIncludesFn 1748 #include "tests/cxx/iwyu_stricter_than_cpp-i2.h" // for IndirectStruct2, TplIndirectStruct2 1749 +#include "tests/cxx/iwyu_stricter_than_cpp-type_alias.h" // for DoesEverythingRightAl, DoesNotForwardDeclareAl, DoesNotForwardDeclareAndIncludesAl, DoesNotForwardDeclareProperlyAl, IncludesAl, TplDoesEverythingRightAgainAl, TplDoesEverythingRightAl, TplDoesNotForwardDeclareAl, TplDoesNotForwardDeclareAndIncludesAl, TplDoesNotForwardDeclareProperlyAl, TplIncludesAl 1750 #include "tests/cxx/iwyu_stricter_than_cpp-typedefs.h" // for DoesEverythingRight, DoesNotForwardDeclare, DoesNotForwardDeclareAndIncludes, DoesNotForwardDeclareProperly, Includes, TplDoesEverythingRight, TplDoesEverythingRightAgain, TplDoesNotForwardDeclare, TplDoesNotForwardDeclareAndIncludes, TplDoesNotForwardDeclareProperly, TplIncludes 1751 struct DirectStruct1; 1752 struct DirectStruct2; 1753 diff --git a/tests/cxx/libbuiltins-direct.h b/tests/cxx/libbuiltins-direct.h 1754 new file mode 100644 1755 index 0000000..47afdf6 1756 --- /dev/null 1757 +++ b/tests/cxx/libbuiltins-direct.h 1758 @@ -0,0 +1,10 @@ 1759 +//===--- libbuiltins-direct.h - test input file for iwyu ------------------===// 1760 +// 1761 +// The LLVM Compiler Infrastructure 1762 +// 1763 +// This file is distributed under the University of Illinois Open Source 1764 +// License. See LICENSE.TXT for details. 1765 +// 1766 +//===----------------------------------------------------------------------===// 1767 + 1768 +#include <cmath> 1769 diff --git a/tests/cxx/libbuiltins.cc b/tests/cxx/libbuiltins.cc 1770 new file mode 100644 1771 index 0000000..d2cdd3e 1772 --- /dev/null 1773 +++ b/tests/cxx/libbuiltins.cc 1774 @@ -0,0 +1,34 @@ 1775 +//===--- libbuiltins.cc - test input file for iwyu ------------------------===// 1776 +// 1777 +// The LLVM Compiler Infrastructure 1778 +// 1779 +// This file is distributed under the University of Illinois Open Source 1780 +// License. See LICENSE.TXT for details. 1781 +// 1782 +//===----------------------------------------------------------------------===// 1783 + 1784 +// Library builtins are, like normal builtins, compiled down to an intrinsic, 1785 +// but a header still needs to be included for the program to be valid. The math 1786 +// library (std::pow, std::round, etc) is a typical example. 1787 + 1788 +// IWYU_ARGS: -I . 1789 + 1790 +#include "tests/cxx/libbuiltins-direct.h" 1791 + 1792 +float kapow(float x) { 1793 + // IWYU: std::pow is...*cmath 1794 + return std::pow(x, 2.0F); 1795 +} 1796 + 1797 +/**** IWYU_SUMMARY 1798 + 1799 +tests/cxx/libbuiltins.cc should add these lines: 1800 +#include <cmath> 1801 + 1802 +tests/cxx/libbuiltins.cc should remove these lines: 1803 +- #include "tests/cxx/libbuiltins-direct.h" // lines XX-XX 1804 + 1805 +The full include-list for tests/cxx/libbuiltins.cc: 1806 +#include <cmath> // for pow 1807 + 1808 +***** IWYU_SUMMARY */ 1809 diff --git a/tests/cxx/macro_location_tpl-d1.h b/tests/cxx/macro_location_tpl-d1.h 1810 new file mode 100644 1811 index 0000000..cf7712f 1812 --- /dev/null 1813 +++ b/tests/cxx/macro_location_tpl-d1.h 1814 @@ -0,0 +1,10 @@ 1815 +//===--- macro_location_tpl-d1.h - test input file for iwyu ---------------===// 1816 +// 1817 +// The LLVM Compiler Infrastructure 1818 +// 1819 +// This file is distributed under the University of Illinois Open Source 1820 +// License. See LICENSE.TXT for details. 1821 +// 1822 +//===----------------------------------------------------------------------===// 1823 + 1824 +#include "tests/cxx/macro_location_tpl-i1.h" 1825 diff --git a/tests/cxx/macro_location_tpl-d2.h b/tests/cxx/macro_location_tpl-d2.h 1826 new file mode 100644 1827 index 0000000..33da0bb 1828 --- /dev/null 1829 +++ b/tests/cxx/macro_location_tpl-d2.h 1830 @@ -0,0 +1,33 @@ 1831 +//===--- macro_location_tpl-d2.h - test input file for iwyu ---------------===// 1832 +// 1833 +// The LLVM Compiler Infrastructure 1834 +// 1835 +// This file is distributed under the University of Illinois Open Source 1836 +// License. See LICENSE.TXT for details. 1837 +// 1838 +//===----------------------------------------------------------------------===// 1839 + 1840 +// Declare a couple of function templates whose specializations are used in a 1841 +// macro, to check that author intent hints attribute uses to the right place. 1842 +template <typename> 1843 +void expansion_template() = delete; 1844 +template <> 1845 +void expansion_template<int>(); 1846 + 1847 +template <typename> 1848 +void spelling_template() = delete; 1849 +template <> 1850 +void spelling_template<int>(); 1851 + 1852 +// As above, but for class templates. 1853 +template <typename> 1854 +struct ExpansionTemplate { 1855 + void method() { 1856 + } 1857 +}; 1858 + 1859 +template <typename> 1860 +struct SpellingTemplate { 1861 + void method() { 1862 + } 1863 +}; 1864 diff --git a/tests/cxx/macro_location_tpl-i1.h b/tests/cxx/macro_location_tpl-i1.h 1865 new file mode 100644 1866 index 0000000..460e2a5 1867 --- /dev/null 1868 +++ b/tests/cxx/macro_location_tpl-i1.h 1869 @@ -0,0 +1,30 @@ 1870 +//===--- macro_location_tpl-i1.h - test input file for iwyu ---------------===// 1871 +// 1872 +// The LLVM Compiler Infrastructure 1873 +// 1874 +// This file is distributed under the University of Illinois Open Source 1875 +// License. See LICENSE.TXT for details. 1876 +// 1877 +//===----------------------------------------------------------------------===// 1878 + 1879 +// Forward-declare the primary templates as a signal that specialization uses 1880 +// belong in the expansion location. 1881 +template <typename> 1882 +void expansion_template(); 1883 + 1884 +template <typename> 1885 +class ExpansionTemplate; 1886 + 1887 +// expansion_template should be attributed to expansion loc. 1888 +#define FUNC_TEMPLATE_SPEC_EXPANSION expansion_template<int>() 1889 + 1890 +// spelling_template should be attributed to this file, because there's no 1891 +// forward-declare hint. 1892 +#define FUNC_TEMPLATE_SPEC_SPELLING spelling_template<int>(); 1893 + 1894 +// ExpansionTemplate should be attributed to expansion loc. 1895 +#define CLASS_TEMPLATE_SPEC_EXPANSION ExpansionTemplate<int>().method(); 1896 + 1897 +// SpellingTemplate should be attributed to this file, because there's no 1898 +// forward-declare hint. 1899 +#define CLASS_TEMPLATE_SPEC_SPELLING SpellingTemplate<int>().method(); 1900 diff --git a/tests/cxx/macro_location_tpl.cc b/tests/cxx/macro_location_tpl.cc 1901 new file mode 100644 1902 index 0000000..01a0a00 1903 --- /dev/null 1904 +++ b/tests/cxx/macro_location_tpl.cc 1905 @@ -0,0 +1,46 @@ 1906 +//===--- macro_location_tpl.cc - test input file for iwyu -----------------===// 1907 +// 1908 +// The LLVM Compiler Infrastructure 1909 +// 1910 +// This file is distributed under the University of Illinois Open Source 1911 +// License. See LICENSE.TXT for details. 1912 +// 1913 +//===----------------------------------------------------------------------===// 1914 + 1915 +// Expands on macro_location test case to also cover template scenarios. Macro 1916 +// uses are attributed to spelling location, but forward-declarations of primary 1917 +// templates also work as author intent hints for template specializations used 1918 +// inside the macro. 1919 + 1920 +// IWYU_ARGS: -I . 1921 + 1922 +#include "tests/cxx/macro_location_tpl-d2.h" 1923 +#include "tests/cxx/macro_location_tpl-d1.h" 1924 + 1925 +void use_macro_with_template_spec() { 1926 + // IWYU: FUNC_TEMPLATE_SPEC_EXPANSION is defined...*macro_location_tpl-i1.h 1927 + FUNC_TEMPLATE_SPEC_EXPANSION; 1928 + 1929 + // IWYU: FUNC_TEMPLATE_SPEC_SPELLING is defined...*macro_location_tpl-i1.h 1930 + FUNC_TEMPLATE_SPEC_SPELLING; 1931 + 1932 + // IWYU: CLASS_TEMPLATE_SPEC_EXPANSION is defined...*macro_location_tpl-i1.h 1933 + CLASS_TEMPLATE_SPEC_EXPANSION; 1934 + 1935 + // IWYU: CLASS_TEMPLATE_SPEC_SPELLING is defined...*macro_location_tpl-i1.h 1936 + CLASS_TEMPLATE_SPEC_SPELLING; 1937 +} 1938 + 1939 +/**** IWYU_SUMMARY 1940 + 1941 +tests/cxx/macro_location_tpl.cc should add these lines: 1942 +#include "tests/cxx/macro_location_tpl-i1.h" 1943 + 1944 +tests/cxx/macro_location_tpl.cc should remove these lines: 1945 +- #include "tests/cxx/macro_location_tpl-d1.h" // lines XX-XX 1946 + 1947 +The full include-list for tests/cxx/macro_location_tpl.cc: 1948 +#include "tests/cxx/macro_location_tpl-d2.h" // for ExpansionTemplate, expansion_template 1949 +#include "tests/cxx/macro_location_tpl-i1.h" // for CLASS_TEMPLATE_SPEC_EXPANSION, CLASS_TEMPLATE_SPEC_SPELLING, FUNC_TEMPLATE_SPEC_EXPANSION, FUNC_TEMPLATE_SPEC_SPELLING 1950 + 1951 +***** IWYU_SUMMARY */ 1952 diff --git a/tests/cxx/no_forced_alias_callability-d1.h b/tests/cxx/no_forced_alias_callability-d1.h 1953 new file mode 100644 1954 index 0000000..895a73f 1955 --- /dev/null 1956 +++ b/tests/cxx/no_forced_alias_callability-d1.h 1957 @@ -0,0 +1,14 @@ 1958 +//===--- no_forced_alias_callability-d1.h - test input file for iwyu ------===// 1959 +// 1960 +// The LLVM Compiler Infrastructure 1961 +// 1962 +// This file is distributed under the University of Illinois Open Source 1963 +// License. See LICENSE.TXT for details. 1964 +// 1965 +//===----------------------------------------------------------------------===// 1966 + 1967 +struct ReturnType; 1968 + 1969 +struct Aliased { 1970 + ReturnType doSomething(); 1971 +}; 1972 diff --git a/tests/cxx/no_forced_alias_callability-d2.h b/tests/cxx/no_forced_alias_callability-d2.h 1973 new file mode 100644 1974 index 0000000..7be9a1b 1975 --- /dev/null 1976 +++ b/tests/cxx/no_forced_alias_callability-d2.h 1977 @@ -0,0 +1,18 @@ 1978 +//===--- no_forced_alias_callability-d2.h - test input file for iwyu ------===// 1979 +// 1980 +// The LLVM Compiler Infrastructure 1981 +// 1982 +// This file is distributed under the University of Illinois Open Source 1983 +// License. See LICENSE.TXT for details. 1984 +// 1985 +//===----------------------------------------------------------------------===// 1986 + 1987 +struct Aliased; 1988 + 1989 +typedef Aliased Alias; 1990 + 1991 +/**** IWYU_SUMMARY 1992 + 1993 +(tests/cxx/no_forced_alias_callability-d2.h has correct #includes/fwd-decls) 1994 + 1995 +***** IWYU_SUMMARY */ 1996 diff --git a/tests/cxx/no_forced_alias_callability.cc b/tests/cxx/no_forced_alias_callability.cc 1997 new file mode 100644 1998 index 0000000..6d4ce0a 1999 --- /dev/null 2000 +++ b/tests/cxx/no_forced_alias_callability.cc 2001 @@ -0,0 +1,29 @@ 2002 +//===--- no_forced_alias_callability.cc - test input file for iwyu --------===// 2003 +// 2004 +// The LLVM Compiler Infrastructure 2005 +// 2006 +// This file is distributed under the University of Illinois Open Source 2007 +// License. See LICENSE.TXT for details. 2008 +// 2009 +//===----------------------------------------------------------------------===// 2010 + 2011 +// IWYU_ARGS: -Xiwyu --check_also="tests/cxx/no_forced_alias_callability-d2.h" \ 2012 +// -I . 2013 + 2014 +// Tests that IWYU doesn't require inclusion of an aliased class header 2015 +// (...-d1.h) into a header with the alias to provide callability of methods 2016 +// of the aliased class if the aliased class is explicitly made forward declared 2017 +// in accordance with the IWYU policy 2018 + 2019 +#include "tests/cxx/no_forced_alias_callability-d1.h" 2020 +#include "tests/cxx/no_forced_alias_callability-d2.h" 2021 + 2022 +int main() { 2023 + Alias a; 2024 +} 2025 + 2026 +/**** IWYU_SUMMARY 2027 + 2028 +(tests/cxx/no_forced_alias_callability.cc has correct #includes/fwd-decls) 2029 + 2030 +***** IWYU_SUMMARY */ 2031 diff --git a/tests/cxx/scope_crash.cc b/tests/cxx/scope_crash.cc 2032 new file mode 100644 2033 index 0000000..1659e08 2034 --- /dev/null 2035 +++ b/tests/cxx/scope_crash.cc 2036 @@ -0,0 +1,45 @@ 2037 +//===--- scope_crash.cc - test input file for iwyu ------------------------===// 2038 +// 2039 +// The LLVM Compiler Infrastructure 2040 +// 2041 +// This file is distributed under the University of Illinois Open Source 2042 +// License. See LICENSE.TXT for details. 2043 +// 2044 +//===----------------------------------------------------------------------===// 2045 + 2046 +// This is a weak testcase, but it's the smallest example we've found to 2047 +// reproduce an IWYU crash where Sema::TUScope was unexpectedly null. 2048 +// 2049 +// For some reason libstdc++9's std::map with a value with explicit default 2050 +// constructor triggers some path in Sema's constructor lookup that needs a 2051 +// non-null TUScope. 2052 +// 2053 +// Clang or libstdc++ might change so that this can no longer trigger the 2054 +// original bug, or so that the bug manifests some other way. But testers can't 2055 +// be choosers. 2056 + 2057 +#include <string> 2058 +#include <map> 2059 + 2060 +struct A {}; 2061 + 2062 +bool operator<(const A& lhs, const A& rhs) { 2063 + return false; 2064 +} 2065 + 2066 +struct B { 2067 + // Used to crash with libstdc++ 9, worked without 'explicit' 2068 + explicit B() = default; 2069 + std::string data; 2070 +}; 2071 + 2072 +void foo(const A& a) { 2073 + std::map<A, B> m; 2074 + m.erase(a); 2075 +} 2076 + 2077 +/**** IWYU_SUMMARY 2078 + 2079 +(tests/cxx/scope_crash.cc has correct #includes/fwd-decls) 2080 + 2081 +***** IWYU_SUMMARY */ 2082 diff --git a/tests/cxx/update_comments.cc b/tests/cxx/update_comments.cc 2083 new file mode 100644 2084 index 0000000..bf0eccb 2085 --- /dev/null 2086 +++ b/tests/cxx/update_comments.cc 2087 @@ -0,0 +1,28 @@ 2088 +//===--- update_comments.cc - test input file for iwyu --------------------===// 2089 +// 2090 +// The LLVM Compiler Infrastructure 2091 +// 2092 +// This file is distributed under the University of Illinois Open Source 2093 +// License. See LICENSE.TXT for details. 2094 +// 2095 +//===----------------------------------------------------------------------===// 2096 + 2097 +// IWYU_ARGS: -Xiwyu --update_comments -I . 2098 + 2099 +// Test that passing the --update_comments switch to IWYU makes it always print 2100 +// the full include-list, with up to date "// for XYZ" comments. 2101 + 2102 +#include "tests/cxx/indirect.h" // for SomethingElse 2103 + 2104 +IndirectClass indirect; 2105 + 2106 +/**** IWYU_SUMMARY 2107 + 2108 +tests/cxx/update_comments.cc should add these lines: 2109 + 2110 +tests/cxx/update_comments.cc should remove these lines: 2111 + 2112 +The full include-list for tests/cxx/update_comments.cc: 2113 +#include "tests/cxx/indirect.h" // for IndirectClass 2114 + 2115 +***** IWYU_SUMMARY */