@zigc/lib 0.16.0-test.1 → 0.17.0-dev.131

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (352) hide show
  1. package/LICENSE +19 -0
  2. package/c/fcntl.zig +6 -1
  3. package/c/inttypes.zig +0 -10
  4. package/c/math.zig +138 -114
  5. package/c/pthread.zig +57 -0
  6. package/c/search.zig +1 -27
  7. package/c/stdlib/drand48.zig +0 -57
  8. package/c/stdlib.zig +0 -100
  9. package/c/string.zig +20 -7
  10. package/c/strings.zig +0 -38
  11. package/c/stropts.zig +17 -0
  12. package/c/unistd.zig +27 -26
  13. package/c/wchar.zig +10 -0
  14. package/c.zig +3 -2
  15. package/compiler/aro/aro/Attribute/names.zig +604 -589
  16. package/compiler/aro/aro/Attribute.zig +202 -116
  17. package/compiler/aro/aro/Builtins/common.zig +874 -863
  18. package/compiler/aro/aro/Builtins/eval.zig +15 -7
  19. package/compiler/aro/aro/Builtins.zig +0 -1
  20. package/compiler/aro/aro/CodeGen.zig +8 -7
  21. package/compiler/aro/aro/Compilation.zig +137 -111
  22. package/compiler/aro/aro/Diagnostics.zig +21 -17
  23. package/compiler/aro/aro/Driver/GCCDetector.zig +635 -0
  24. package/compiler/aro/aro/Driver.zig +138 -63
  25. package/compiler/aro/aro/LangOpts.zig +12 -2
  26. package/compiler/aro/aro/Parser/Diagnostic.zig +79 -19
  27. package/compiler/aro/aro/Parser.zig +352 -153
  28. package/compiler/aro/aro/Pragma.zig +3 -2
  29. package/compiler/aro/aro/Preprocessor/Diagnostic.zig +21 -0
  30. package/compiler/aro/aro/Preprocessor.zig +136 -62
  31. package/compiler/aro/aro/Target.zig +17 -12
  32. package/compiler/aro/aro/Tokenizer.zig +31 -14
  33. package/compiler/aro/aro/Toolchain.zig +4 -7
  34. package/compiler/aro/aro/Tree.zig +178 -148
  35. package/compiler/aro/aro/TypeStore.zig +82 -24
  36. package/compiler/aro/aro/Value.zig +13 -17
  37. package/compiler/aro/aro/features.zig +1 -0
  38. package/compiler/aro/aro/pragmas/message.zig +3 -2
  39. package/compiler/aro/aro/pragmas/once.zig +0 -1
  40. package/compiler/aro/aro/record_layout.zig +3 -3
  41. package/compiler/aro/aro/text_literal.zig +3 -2
  42. package/compiler/aro/assembly_backend/x86_64.zig +7 -8
  43. package/compiler/aro/backend/Assembly.zig +1 -2
  44. package/compiler/aro/backend/Interner.zig +2 -2
  45. package/compiler/aro/backend/Ir.zig +100 -92
  46. package/compiler/aro/include/ptrcheck.h +49 -0
  47. package/compiler/aro/main.zig +26 -10
  48. package/compiler/build_runner.zig +1 -2
  49. package/compiler/objdump.zig +93 -0
  50. package/compiler/reduce/Walk.zig +7 -7
  51. package/compiler/reduce.zig +5 -1
  52. package/compiler/resinator/compile.zig +2 -2
  53. package/compiler/resinator/main.zig +7 -1
  54. package/compiler/resinator/preprocess.zig +1 -3
  55. package/compiler/std-docs.zig +8 -1
  56. package/compiler/test_runner.zig +194 -62
  57. package/compiler/translate-c/MacroTranslator.zig +80 -11
  58. package/compiler/translate-c/PatternList.zig +1 -9
  59. package/compiler/translate-c/Scope.zig +43 -6
  60. package/compiler/translate-c/Translator.zig +369 -127
  61. package/compiler/translate-c/ast.zig +19 -11
  62. package/compiler/translate-c/main.zig +76 -17
  63. package/compiler_rt/cos.zig +140 -53
  64. package/compiler_rt/divmodei4.zig +40 -17
  65. package/compiler_rt/exp.zig +1 -6
  66. package/compiler_rt/exp2.zig +1 -6
  67. package/compiler_rt/exp_f128.zig +377 -0
  68. package/compiler_rt/fabs.zig +0 -2
  69. package/compiler_rt/fma.zig +0 -2
  70. package/compiler_rt/fmax.zig +0 -2
  71. package/compiler_rt/fmin.zig +0 -2
  72. package/compiler_rt/fmod.zig +0 -2
  73. package/compiler_rt/limb64.zig +1127 -0
  74. package/compiler_rt/log.zig +0 -2
  75. package/compiler_rt/log10.zig +0 -2
  76. package/compiler_rt/log2.zig +0 -2
  77. package/compiler_rt/long_double.zig +37 -0
  78. package/compiler_rt/mulXi3.zig +1 -1
  79. package/compiler_rt/mulo.zig +6 -1
  80. package/compiler_rt/rem_pio2l.zig +173 -0
  81. package/compiler_rt/round.zig +0 -2
  82. package/compiler_rt/sin.zig +139 -56
  83. package/compiler_rt/sincos.zig +277 -72
  84. package/compiler_rt/sqrt.zig +0 -2
  85. package/compiler_rt/ssp.zig +1 -1
  86. package/compiler_rt/tan.zig +117 -48
  87. package/compiler_rt/trig.zig +256 -6
  88. package/compiler_rt/trunc.zig +0 -2
  89. package/compiler_rt/udivmodei4.zig +28 -0
  90. package/compiler_rt.zig +2 -0
  91. package/fuzzer.zig +857 -307
  92. package/libc/musl/arch/mipsn32/syscall_arch.h +35 -32
  93. package/libc/musl/src/math/pow.c +343 -0
  94. package/package.json +1 -1
  95. package/std/Build/Cache.zig +6 -6
  96. package/std/Build/Fuzz.zig +6 -19
  97. package/std/Build/Module.zig +1 -1
  98. package/std/Build/Step/CheckObject.zig +3 -3
  99. package/std/Build/Step/Compile.zig +18 -1
  100. package/std/Build/Step/ConfigHeader.zig +49 -33
  101. package/std/Build/Step/InstallArtifact.zig +18 -0
  102. package/std/Build/Step/Run.zig +538 -89
  103. package/std/Build/Step/TranslateC.zig +0 -6
  104. package/std/Build/Step.zig +10 -19
  105. package/std/Build/WebServer.zig +31 -19
  106. package/std/Build/abi.zig +47 -11
  107. package/std/Build.zig +17 -17
  108. package/std/Io/Dir.zig +7 -2
  109. package/std/Io/Dispatch.zig +5 -13
  110. package/std/Io/File/Reader.zig +3 -1
  111. package/std/Io/File/Writer.zig +8 -6
  112. package/std/Io/File.zig +1 -0
  113. package/std/Io/Kqueue.zig +2 -2
  114. package/std/Io/Reader.zig +8 -9
  115. package/std/Io/Semaphore.zig +112 -17
  116. package/std/Io/Terminal.zig +1 -1
  117. package/std/Io/Threaded.zig +352 -180
  118. package/std/Io/Uring.zig +15 -16
  119. package/std/Io/Writer.zig +46 -42
  120. package/std/Io/net.zig +11 -11
  121. package/std/Io.zig +1052 -20
  122. package/std/SemanticVersion.zig +1 -1
  123. package/std/Target/Query.zig +2 -2
  124. package/std/Target.zig +53 -7
  125. package/std/Thread.zig +8 -3
  126. package/std/array_hash_map.zig +105 -573
  127. package/std/array_list.zig +22 -31
  128. package/std/bit_set.zig +22 -6
  129. package/std/builtin/assembly.zig +68 -0
  130. package/std/builtin.zig +4 -0
  131. package/std/c/haiku.zig +3 -0
  132. package/std/c/serenity.zig +1 -6
  133. package/std/c.zig +106 -24
  134. package/std/compress/flate/Compress.zig +3 -3
  135. package/std/compress/flate/Decompress.zig +2 -3
  136. package/std/compress/zstd/Decompress.zig +2 -4
  137. package/std/crypto/Certificate/Bundle.zig +15 -1
  138. package/std/crypto/Certificate.zig +13 -1
  139. package/std/crypto/ascon.zig +75 -33
  140. package/std/crypto/codecs/asn1/Oid.zig +12 -1
  141. package/std/crypto/codecs/asn1.zig +33 -18
  142. package/std/crypto/codecs/base64_hex_ct.zig +16 -8
  143. package/std/crypto/ml_kem.zig +2 -9
  144. package/std/crypto/tls/Client.zig +79 -4
  145. package/std/crypto/tls.zig +1 -1
  146. package/std/crypto.zig +1 -0
  147. package/std/debug/Dwarf.zig +29 -9
  148. package/std/debug/Info.zig +4 -0
  149. package/std/debug/MachOFile.zig +46 -8
  150. package/std/debug/Pdb.zig +540 -37
  151. package/std/debug/SelfInfo/Elf.zig +19 -18
  152. package/std/debug/SelfInfo/MachO.zig +18 -7
  153. package/std/debug/SelfInfo/Windows.zig +138 -36
  154. package/std/debug.zig +181 -66
  155. package/std/enums.zig +25 -19
  156. package/std/fmt.zig +8 -3
  157. package/std/fs/path.zig +6 -4
  158. package/std/heap/ArenaAllocator.zig +145 -154
  159. package/std/heap/BufferFirstAllocator.zig +165 -0
  160. package/std/heap/debug_allocator.zig +7 -7
  161. package/std/heap.zig +2 -126
  162. package/std/http/Client.zig +31 -30
  163. package/std/http.zig +14 -13
  164. package/std/json/Scanner.zig +2 -2
  165. package/std/json/Stringify.zig +3 -3
  166. package/std/json/dynamic.zig +4 -4
  167. package/std/math/big/int.zig +16 -17
  168. package/std/mem/Allocator.zig +4 -5
  169. package/std/mem.zig +48 -0
  170. package/std/os/emscripten.zig +2 -18
  171. package/std/os/linux/IoUring.zig +2 -0
  172. package/std/os/linux/aarch64.zig +41 -12
  173. package/std/os/linux/arc.zig +173 -0
  174. package/std/os/linux/arm.zig +41 -12
  175. package/std/os/linux/hexagon.zig +33 -11
  176. package/std/os/linux/loongarch32.zig +41 -13
  177. package/std/os/linux/loongarch64.zig +41 -12
  178. package/std/os/linux/m68k.zig +41 -13
  179. package/std/os/linux/mips.zig +67 -36
  180. package/std/os/linux/mips64.zig +60 -29
  181. package/std/os/linux/mipsn32.zig +60 -29
  182. package/std/os/linux/or1k.zig +41 -12
  183. package/std/os/linux/powerpc.zig +41 -12
  184. package/std/os/linux/powerpc64.zig +41 -12
  185. package/std/os/linux/riscv32.zig +41 -12
  186. package/std/os/linux/riscv64.zig +41 -12
  187. package/std/os/linux/s390x.zig +44 -7
  188. package/std/os/linux/sparc64.zig +83 -52
  189. package/std/os/linux/thumb.zig +52 -36
  190. package/std/os/linux/x32.zig +41 -12
  191. package/std/os/linux/x86.zig +42 -13
  192. package/std/os/linux/x86_64.zig +41 -12
  193. package/std/os/linux.zig +419 -438
  194. package/std/os/uefi/tables/boot_services.zig +9 -8
  195. package/std/os/windows.zig +2 -2
  196. package/std/os.zig +41 -0
  197. package/std/pdb.zig +143 -4
  198. package/std/posix.zig +6 -12
  199. package/std/priority_dequeue.zig +13 -12
  200. package/std/priority_queue.zig +5 -4
  201. package/std/process/Child.zig +1 -1
  202. package/std/process/Environ.zig +1 -1
  203. package/std/process.zig +1 -1
  204. package/std/sort.zig +3 -3
  205. package/std/start.zig +17 -4
  206. package/std/std.zig +19 -6
  207. package/std/testing/FailingAllocator.zig +4 -4
  208. package/std/testing/Smith.zig +37 -2
  209. package/std/zig/Ast/Render.zig +187 -459
  210. package/std/zig/Ast.zig +0 -4
  211. package/std/zig/AstGen.zig +86 -103
  212. package/std/zig/AstRlAnnotate.zig +0 -11
  213. package/std/zig/AstSmith.zig +2602 -0
  214. package/std/zig/BuiltinFn.zig +0 -32
  215. package/std/zig/Client.zig +8 -3
  216. package/std/zig/LibCInstallation.zig +4 -3
  217. package/std/zig/Parse.zig +90 -81
  218. package/std/zig/Server.zig +26 -0
  219. package/std/zig/WindowsSdk.zig +13 -13
  220. package/std/zig/Zir.zig +66 -62
  221. package/std/zig/ZonGen.zig +6 -5
  222. package/std/zig/c_translation/helpers.zig +14 -9
  223. package/std/zig/llvm/Builder.zig +119 -60
  224. package/std/zig/system.zig +20 -4
  225. package/std/zig/tokenizer.zig +2 -1
  226. package/std/zig.zig +7 -10
  227. package/std/zip.zig +5 -5
  228. package/zig.h +340 -1
  229. package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
  230. package/libc/mingw/complex/cabs.c +0 -48
  231. package/libc/mingw/complex/cabsf.c +0 -48
  232. package/libc/mingw/complex/cacos.c +0 -50
  233. package/libc/mingw/complex/cacosf.c +0 -50
  234. package/libc/mingw/complex/carg.c +0 -48
  235. package/libc/mingw/complex/cargf.c +0 -48
  236. package/libc/mingw/complex/casin.c +0 -50
  237. package/libc/mingw/complex/casinf.c +0 -50
  238. package/libc/mingw/complex/catan.c +0 -50
  239. package/libc/mingw/complex/catanf.c +0 -50
  240. package/libc/mingw/complex/ccos.c +0 -50
  241. package/libc/mingw/complex/ccosf.c +0 -50
  242. package/libc/mingw/complex/cexp.c +0 -48
  243. package/libc/mingw/complex/cexpf.c +0 -48
  244. package/libc/mingw/complex/cimag.c +0 -48
  245. package/libc/mingw/complex/cimagf.c +0 -48
  246. package/libc/mingw/complex/clog.c +0 -48
  247. package/libc/mingw/complex/clog10.c +0 -49
  248. package/libc/mingw/complex/clog10f.c +0 -49
  249. package/libc/mingw/complex/clogf.c +0 -48
  250. package/libc/mingw/complex/conj.c +0 -48
  251. package/libc/mingw/complex/conjf.c +0 -48
  252. package/libc/mingw/complex/cpow.c +0 -48
  253. package/libc/mingw/complex/cpowf.c +0 -48
  254. package/libc/mingw/complex/cproj.c +0 -48
  255. package/libc/mingw/complex/cprojf.c +0 -48
  256. package/libc/mingw/complex/creal.c +0 -48
  257. package/libc/mingw/complex/crealf.c +0 -48
  258. package/libc/mingw/complex/csin.c +0 -50
  259. package/libc/mingw/complex/csinf.c +0 -50
  260. package/libc/mingw/complex/csqrt.c +0 -48
  261. package/libc/mingw/complex/csqrtf.c +0 -48
  262. package/libc/mingw/complex/ctan.c +0 -50
  263. package/libc/mingw/complex/ctanf.c +0 -50
  264. package/libc/mingw/math/arm/s_rint.c +0 -86
  265. package/libc/mingw/math/arm/s_rintf.c +0 -51
  266. package/libc/mingw/math/arm/sincos.S +0 -30
  267. package/libc/mingw/math/arm-common/sincosl.c +0 -13
  268. package/libc/mingw/math/arm64/rint.c +0 -12
  269. package/libc/mingw/math/arm64/rintf.c +0 -12
  270. package/libc/mingw/math/arm64/sincos.S +0 -32
  271. package/libc/mingw/math/bsd_private_base.h +0 -148
  272. package/libc/mingw/math/fdiml.c +0 -24
  273. package/libc/mingw/math/frexpf.c +0 -13
  274. package/libc/mingw/math/frexpl.c +0 -71
  275. package/libc/mingw/math/x86/acosf.c +0 -29
  276. package/libc/mingw/math/x86/atanf.c +0 -23
  277. package/libc/mingw/math/x86/atanl.c +0 -18
  278. package/libc/mingw/math/x86/cos.def.h +0 -65
  279. package/libc/mingw/math/x86/cosl.c +0 -46
  280. package/libc/mingw/math/x86/cosl_internal.S +0 -55
  281. package/libc/mingw/math/x86/ldexp.c +0 -23
  282. package/libc/mingw/math/x86/scalbn.S +0 -41
  283. package/libc/mingw/math/x86/scalbnf.S +0 -40
  284. package/libc/mingw/math/x86/sin.def.h +0 -65
  285. package/libc/mingw/math/x86/sinl.c +0 -46
  286. package/libc/mingw/math/x86/sinl_internal.S +0 -58
  287. package/libc/mingw/math/x86/tanl.S +0 -62
  288. package/libc/mingw/misc/btowc.c +0 -28
  289. package/libc/mingw/misc/wcstof.c +0 -66
  290. package/libc/mingw/misc/wcstoimax.c +0 -132
  291. package/libc/mingw/misc/wcstoumax.c +0 -126
  292. package/libc/mingw/misc/wctob.c +0 -29
  293. package/libc/mingw/misc/winbs_uint64.c +0 -6
  294. package/libc/mingw/misc/winbs_ulong.c +0 -6
  295. package/libc/mingw/misc/winbs_ushort.c +0 -6
  296. package/libc/mingw/stdio/_Exit.c +0 -10
  297. package/libc/mingw/stdio/_findfirst64i32.c +0 -21
  298. package/libc/mingw/stdio/_findnext64i32.c +0 -21
  299. package/libc/mingw/stdio/_fstat64i32.c +0 -37
  300. package/libc/mingw/stdio/_stat64i32.c +0 -37
  301. package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
  302. package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
  303. package/libc/mingw/stdio/_wstat64i32.c +0 -37
  304. package/libc/mingw/winpthreads/spinlock.c +0 -82
  305. package/libc/musl/src/legacy/isastream.c +0 -7
  306. package/libc/musl/src/legacy/valloc.c +0 -8
  307. package/libc/musl/src/linux/tee.c +0 -8
  308. package/libc/musl/src/math/__cosl.c +0 -96
  309. package/libc/musl/src/math/__sinl.c +0 -78
  310. package/libc/musl/src/math/__tanl.c +0 -143
  311. package/libc/musl/src/math/aarch64/lrint.c +0 -10
  312. package/libc/musl/src/math/aarch64/lrintf.c +0 -10
  313. package/libc/musl/src/math/aarch64/rintf.c +0 -7
  314. package/libc/musl/src/math/cosl.c +0 -39
  315. package/libc/musl/src/math/fdim.c +0 -10
  316. package/libc/musl/src/math/fdimf.c +0 -10
  317. package/libc/musl/src/math/fdiml.c +0 -18
  318. package/libc/musl/src/math/finite.c +0 -7
  319. package/libc/musl/src/math/finitef.c +0 -7
  320. package/libc/musl/src/math/frexp.c +0 -23
  321. package/libc/musl/src/math/frexpf.c +0 -23
  322. package/libc/musl/src/math/frexpl.c +0 -29
  323. package/libc/musl/src/math/i386/lrint.c +0 -8
  324. package/libc/musl/src/math/i386/lrintf.c +0 -8
  325. package/libc/musl/src/math/i386/rintf.c +0 -7
  326. package/libc/musl/src/math/lrint.c +0 -72
  327. package/libc/musl/src/math/lrintf.c +0 -8
  328. package/libc/musl/src/math/powerpc64/lrint.c +0 -16
  329. package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
  330. package/libc/musl/src/math/rintf.c +0 -30
  331. package/libc/musl/src/math/s390x/rintf.c +0 -15
  332. package/libc/musl/src/math/sincosl.c +0 -60
  333. package/libc/musl/src/math/sinl.c +0 -41
  334. package/libc/musl/src/math/tanl.c +0 -29
  335. package/libc/musl/src/math/x32/lrint.s +0 -5
  336. package/libc/musl/src/math/x32/lrintf.s +0 -5
  337. package/libc/musl/src/math/x86_64/lrint.c +0 -8
  338. package/libc/musl/src/math/x86_64/lrintf.c +0 -8
  339. package/libc/musl/src/string/strdup.c +0 -10
  340. package/libc/musl/src/string/strndup.c +0 -12
  341. package/libc/musl/src/string/wcsdup.c +0 -10
  342. package/libc/musl/src/thread/pthread_spin_destroy.c +0 -6
  343. package/libc/musl/src/thread/pthread_spin_init.c +0 -6
  344. package/libc/musl/src/thread/pthread_spin_lock.c +0 -8
  345. package/libc/musl/src/thread/pthread_spin_trylock.c +0 -7
  346. package/libc/musl/src/thread/pthread_spin_unlock.c +0 -7
  347. package/libc/musl/src/unistd/dup2.c +0 -20
  348. package/libc/musl/src/unistd/dup3.c +0 -26
  349. package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
  350. package/libc/wasi/thread-stub/pthread_spin_lock.c +0 -8
  351. package/libc/wasi/thread-stub/pthread_spin_trylock.c +0 -8
  352. package/libc/wasi/thread-stub/pthread_spin_unlock.c +0 -7
@@ -1,5 +1,4 @@
1
1
  const std = @import("std");
2
- const Io = std.Io;
3
2
  const mem = std.mem;
4
3
  const Allocator = mem.Allocator;
5
4
  const assert = std.debug.assert;
@@ -204,6 +203,11 @@ string_ids: struct {
204
203
  sigjmp_buf: StringId,
205
204
  ucontext_t: StringId,
206
205
  },
206
+ va_arg_pack_ctx: packed struct {
207
+ valid: bool = false,
208
+ variadic: bool = false,
209
+ typed: bool = false,
210
+ } = .{},
207
211
 
208
212
  /// Checks codepoint for various pedantic warnings
209
213
  /// Returns true if diagnostic issued
@@ -211,8 +215,9 @@ fn checkIdentifierCodepointWarnings(p: *Parser, codepoint: u21, loc: Source.Loca
211
215
  assert(codepoint >= 0x80);
212
216
 
213
217
  const prev_total = p.diagnostics.total;
214
- var sf = std.heap.stackFallback(1024, p.comp.gpa);
215
- var allocating: Io.Writer.Allocating = .init(sf.get());
218
+ var bfa_buf: [1024]u8 = undefined;
219
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, p.comp.gpa);
220
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
216
221
  defer allocating.deinit();
217
222
 
218
223
  if (!char_info.isC99IdChar(codepoint)) {
@@ -425,8 +430,9 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
425
430
  if (diagnostic.suppress_unless_version) |some| if (!p.comp.langopts.standard.atLeast(some)) return;
426
431
  if (p.diagnostics.effectiveKind(diagnostic) == .off) return;
427
432
 
428
- var sf = std.heap.stackFallback(1024, p.comp.gpa);
429
- var allocating: Io.Writer.Allocating = .init(sf.get());
433
+ var bfa_buf: [1024]u8 = undefined;
434
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, p.comp.gpa);
435
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
430
436
  defer allocating.deinit();
431
437
 
432
438
  p.formatArgs(&allocating.writer, diagnostic.fmt, args) catch return error.OutOfMemory;
@@ -448,7 +454,7 @@ pub fn err(p: *Parser, tok_i: TokenIndex, diagnostic: Diagnostic, args: anytype)
448
454
  }, p.pp.expansionSlice(tok_i), true);
449
455
  }
450
456
 
451
- fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void {
457
+ fn formatArgs(p: *Parser, w: *std.Io.Writer, fmt: []const u8, args: anytype) !void {
452
458
  var i: usize = 0;
453
459
  inline for (std.meta.fields(@TypeOf(args))) |arg_info| {
454
460
  const arg = @field(args, arg_info.name);
@@ -477,13 +483,13 @@ fn formatArgs(p: *Parser, w: *Io.Writer, fmt: []const u8, args: anytype) !void {
477
483
  try w.writeAll(fmt[i..]);
478
484
  }
479
485
 
480
- fn formatTokenId(w: *Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize {
486
+ fn formatTokenId(w: *std.Io.Writer, fmt: []const u8, tok_id: Tree.Token.Id) !usize {
481
487
  const i = Diagnostics.templateIndex(w, fmt, "{tok_id}");
482
488
  try w.writeAll(tok_id.symbol());
483
489
  return i;
484
490
  }
485
491
 
486
- fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usize {
492
+ fn formatQualType(p: *Parser, w: *std.Io.Writer, fmt: []const u8, qt: QualType) !usize {
487
493
  const i = Diagnostics.templateIndex(w, fmt, "{qt}");
488
494
  try w.writeByte('\'');
489
495
  try qt.print(p.comp, w);
@@ -502,7 +508,7 @@ fn formatQualType(p: *Parser, w: *Io.Writer, fmt: []const u8, qt: QualType) !usi
502
508
  return i;
503
509
  }
504
510
 
505
- fn formatResult(p: *Parser, w: *Io.Writer, fmt: []const u8, res: Result) !usize {
511
+ fn formatResult(p: *Parser, w: *std.Io.Writer, fmt: []const u8, res: Result) !usize {
506
512
  const i = Diagnostics.templateIndex(w, fmt, "{value}");
507
513
  switch (res.val.opt_ref) {
508
514
  .none => try w.writeAll("(none)"),
@@ -525,7 +531,7 @@ const Normalized = struct {
525
531
  return .{ .str = str };
526
532
  }
527
533
 
528
- pub fn format(ctx: Normalized, w: *Io.Writer, fmt: []const u8) !usize {
534
+ pub fn format(ctx: Normalized, w: *std.Io.Writer, fmt: []const u8) !usize {
529
535
  const i = Diagnostics.templateIndex(w, fmt, "{normalized}");
530
536
  var it: std.unicode.Utf8Iterator = .{
531
537
  .bytes = ctx.str,
@@ -559,7 +565,7 @@ const Codepoint = struct {
559
565
  return .{ .codepoint = codepoint };
560
566
  }
561
567
 
562
- pub fn format(ctx: Codepoint, w: *Io.Writer, fmt: []const u8) !usize {
568
+ pub fn format(ctx: Codepoint, w: *std.Io.Writer, fmt: []const u8) !usize {
563
569
  const i = Diagnostics.templateIndex(w, fmt, "{codepoint}");
564
570
  try w.print("{X:0>4}", .{ctx.codepoint});
565
571
  return i;
@@ -573,7 +579,7 @@ const Escaped = struct {
573
579
  return .{ .str = str };
574
580
  }
575
581
 
576
- pub fn format(ctx: Escaped, w: *Io.Writer, fmt: []const u8) !usize {
582
+ pub fn format(ctx: Escaped, w: *std.Io.Writer, fmt: []const u8) !usize {
577
583
  const i = Diagnostics.templateIndex(w, fmt, "{s}");
578
584
  try std.zig.stringEscape(ctx.str, w);
579
585
  return i;
@@ -740,6 +746,11 @@ fn getNode(p: *Parser, node: Node.Index, comptime tag: std.meta.Tag(Tree.Node))
740
746
  }
741
747
  }
742
748
 
749
+ pub fn isAddressOfStringLiteral(p: *Parser, node: Node.Index) bool {
750
+ const addr_of = p.getNode(node, .addr_of_expr) orelse return false;
751
+ return p.nodeIs(addr_of.operand, .string_literal_expr);
752
+ }
753
+
743
754
  fn pragma(p: *Parser) Compilation.Error!bool {
744
755
  var found_pragma = false;
745
756
  while (p.eatToken(.keyword_pragma)) |_| {
@@ -1070,14 +1081,15 @@ fn decl(p: *Parser) Error!bool {
1070
1081
 
1071
1082
  try p.attributeSpecifier();
1072
1083
 
1084
+ const decl_spec_start = p.tok_i;
1073
1085
  var decl_spec = (try p.declSpec()) orelse blk: {
1074
1086
  if (p.func.qt != null) {
1075
1087
  p.tok_i = first_tok;
1076
1088
  return false;
1077
1089
  }
1078
- switch (p.tok_ids[first_tok]) {
1090
+ switch (p.tok_ids[decl_spec_start]) {
1079
1091
  .asterisk, .l_paren => {},
1080
- .identifier, .extended_identifier => switch (p.tok_ids[first_tok + 1]) {
1092
+ .identifier, .extended_identifier => switch (p.tok_ids[decl_spec_start + 1]) {
1081
1093
  .identifier, .extended_identifier => {
1082
1094
  // The most likely reason for `identifier identifier` is
1083
1095
  // an unknown type name.
@@ -1087,7 +1099,7 @@ fn decl(p: *Parser) Error!bool {
1087
1099
  },
1088
1100
  else => {},
1089
1101
  },
1090
- else => if (p.tok_i != first_tok) {
1102
+ else => if (p.tok_i != decl_spec_start) {
1091
1103
  try p.err(p.tok_i, .expected_ident_or_l_paren, .{});
1092
1104
  return error.ParsingFailed;
1093
1105
  } else return false,
@@ -1167,6 +1179,7 @@ fn decl(p: *Parser) Error!bool {
1167
1179
 
1168
1180
  // Collect old style parameter declarations.
1169
1181
  if (init_d.d.old_style_func != null) {
1182
+ try p.err(init_d.d.name, .def_no_proto_deprecated, .{});
1170
1183
  const param_buf_top = p.param_buf.items.len;
1171
1184
  defer p.param_buf.items.len = param_buf_top;
1172
1185
 
@@ -1340,7 +1353,7 @@ fn decl(p: *Parser) Error!bool {
1340
1353
  if (init_d.d.old_style_func) |tok_i| try p.err(tok_i, .invalid_old_style_params, .{});
1341
1354
 
1342
1355
  if (decl_spec.storage_class == .typedef) {
1343
- try decl_spec.validateDecl(p);
1356
+ try decl_spec.validateDecl(p, init_d.asm_label);
1344
1357
  try p.tree.setNode(.{ .typedef = .{
1345
1358
  .name_tok = init_d.d.name,
1346
1359
  .qt = init_d.d.qt,
@@ -1357,7 +1370,7 @@ fn decl(p: *Parser) Error!bool {
1357
1370
  .definition = null,
1358
1371
  } }, @intFromEnum(decl_node));
1359
1372
  } else {
1360
- try decl_spec.validateDecl(p);
1373
+ try decl_spec.validateDecl(p, init_d.asm_label);
1361
1374
  var node_qt = init_d.d.qt;
1362
1375
  if (p.func.qt == null and decl_spec.storage_class != .@"extern") {
1363
1376
  if (node_qt.get(p.comp, .array)) |array_ty| {
@@ -1454,7 +1467,7 @@ fn decl(p: *Parser) Error!bool {
1454
1467
  return true;
1455
1468
  }
1456
1469
 
1457
- fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *Io.Writer.Allocating) !?[]const u8 {
1470
+ fn staticAssertMessage(p: *Parser, cond_node: Node.Index, maybe_message: ?Result, allocating: *std.Io.Writer.Allocating) !?[]const u8 {
1458
1471
  const w = &allocating.writer;
1459
1472
 
1460
1473
  const cond = cond_node.get(&p.tree);
@@ -1526,8 +1539,9 @@ fn staticAssert(p: *Parser) Error!bool {
1526
1539
  }
1527
1540
  } else {
1528
1541
  if (!res.val.toBool(p.comp)) {
1529
- var sf = std.heap.stackFallback(1024, gpa);
1530
- var allocating: Io.Writer.Allocating = .init(sf.get());
1542
+ var bfa_buf: [1024]u8 = undefined;
1543
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
1544
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
1531
1545
  defer allocating.deinit();
1532
1546
 
1533
1547
  if (p.staticAssertMessage(res_node, str, &allocating) catch return error.OutOfMemory) |message| {
@@ -1597,13 +1611,16 @@ pub const DeclSpec = struct {
1597
1611
  if (d.constexpr) |tok_i| try p.err(tok_i, .illegal_storage_on_func, .{});
1598
1612
  }
1599
1613
 
1600
- fn validateDecl(d: DeclSpec, p: *Parser) Error!void {
1614
+ fn validateDecl(d: DeclSpec, p: *Parser, asm_label: ?Node.Index) Error!void {
1601
1615
  if (d.@"inline") |tok_i| try p.err(tok_i, .func_spec_non_func, .{"inline"});
1602
1616
  // TODO move to attribute validation
1603
1617
  if (d.noreturn) |tok_i| try p.err(tok_i, .func_spec_non_func, .{"_Noreturn"});
1604
1618
  switch (d.storage_class) {
1605
- .auto => std.debug.assert(!p.comp.langopts.standard.atLeast(.c23)),
1606
- .register => if (p.func.qt == null) try p.err(p.tok_i, .illegal_storage_on_global, .{}),
1619
+ .auto => {
1620
+ std.debug.assert(!p.comp.langopts.standard.atLeast(.c23));
1621
+ try p.err(p.tok_i, .auto_on_global, .{});
1622
+ },
1623
+ .register => if (p.func.qt == null and asm_label == null) try p.err(p.tok_i, .register_on_global, .{}),
1607
1624
  else => {},
1608
1625
  }
1609
1626
  }
@@ -1787,7 +1804,11 @@ fn storageClassSpec(p: *Parser, d: *DeclSpec) Error!bool {
1787
1804
  return p.tok_i != start;
1788
1805
  }
1789
1806
 
1790
- const InitDeclarator = struct { d: Declarator, initializer: ?Result = null };
1807
+ const InitDeclarator = struct {
1808
+ d: Declarator,
1809
+ initializer: ?Result = null,
1810
+ asm_label: ?Node.Index = null,
1811
+ };
1791
1812
 
1792
1813
  /// attribute
1793
1814
  /// : attrIdentifier
@@ -1829,18 +1850,18 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
1829
1850
  if (try p.eatIdentifier()) |ident| {
1830
1851
  if (try Attribute.diagnoseIdent(attr, &arguments, ident, p)) {
1831
1852
  p.skipTo(.r_paren);
1832
- return error.ParsingFailed;
1853
+ return null;
1833
1854
  }
1834
1855
  } else {
1835
1856
  try p.err(name_tok, .attribute_requires_identifier, .{name});
1836
- return error.ParsingFailed;
1857
+ return null;
1837
1858
  }
1838
1859
  } else {
1839
1860
  const arg_start = p.tok_i;
1840
1861
  const first_expr = try p.expect(assignExpr);
1841
1862
  if (try p.diagnose(attr, &arguments, arg_idx, first_expr, arg_start)) {
1842
1863
  p.skipTo(.r_paren);
1843
- return error.ParsingFailed;
1864
+ return null;
1844
1865
  }
1845
1866
  }
1846
1867
  arg_idx += 1;
@@ -1851,7 +1872,7 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
1851
1872
  const arg_expr = try p.expect(assignExpr);
1852
1873
  if (try p.diagnose(attr, &arguments, arg_idx, arg_expr, arg_start)) {
1853
1874
  p.skipTo(.r_paren);
1854
- return error.ParsingFailed;
1875
+ return null;
1855
1876
  }
1856
1877
  }
1857
1878
  },
@@ -1861,9 +1882,9 @@ fn attribute(p: *Parser, kind: Attribute.Kind, namespace: ?[]const u8) Error!?Te
1861
1882
  try p.err(name_tok, .attribute_not_enough_args, .{
1862
1883
  @tagName(attr), required_count,
1863
1884
  });
1864
- return error.ParsingFailed;
1885
+ return null;
1865
1886
  }
1866
- return TentativeAttribute{ .attr = .{ .tag = attr, .args = arguments, .syntax = kind.toSyntax() }, .tok = name_tok };
1887
+ return .{ .attr = .{ .tag = attr, .args = arguments, .syntax = kind.toSyntax() }, .tok = name_tok };
1867
1888
  }
1868
1889
 
1869
1890
  fn diagnose(p: *Parser, attr: Attribute.Tag, arguments: *Attribute.Arguments, arg_idx: u32, res: Result, arg_start: TokenIndex) !bool {
@@ -1995,12 +2016,12 @@ fn initDeclarator(p: *Parser, decl_spec: *DeclSpec, attr_buf_top: usize, decl_no
1995
2016
  defer p.attr_buf.len = this_attr_buf_top;
1996
2017
  const gpa = p.comp.gpa;
1997
2018
 
1998
- var init_d = InitDeclarator{
2019
+ var init_d: InitDeclarator = .{
1999
2020
  .d = (try p.declarator(decl_spec.qt, .normal)) orelse return null,
2000
2021
  };
2001
2022
 
2002
2023
  try p.attributeSpecifierExtra(init_d.d.name);
2003
- _ = try p.assembly(.decl_label);
2024
+ init_d.asm_label = try p.assembly(.decl_label);
2004
2025
  try p.attributeSpecifierExtra(init_d.d.name);
2005
2026
 
2006
2027
  switch (init_d.d.declarator_type) {
@@ -2276,14 +2297,13 @@ fn typeSpec(p: *Parser, builder: *TypeStore.Builder) Error!bool {
2276
2297
  }, .syntax = .keyword },
2277
2298
  .tok = align_tok,
2278
2299
  });
2279
- } else {
2300
+ } else check: {
2280
2301
  const arg_start = p.tok_i;
2281
2302
  const res = try p.integerConstExpr(.no_const_decl_folding);
2282
2303
  if (!res.val.isZero(p.comp)) {
2283
2304
  var args = Attribute.initArguments(.aligned, align_tok);
2284
2305
  if (try p.diagnose(.aligned, &args, 0, res, arg_start)) {
2285
- p.skipTo(.r_paren);
2286
- return error.ParsingFailed;
2306
+ break :check;
2287
2307
  }
2288
2308
  args.aligned.alignment.?.node = .pack(res.node);
2289
2309
  try p.attr_buf.append(gpa, .{
@@ -2562,7 +2582,7 @@ fn recordSpec(p: *Parser) Error!QualType {
2562
2582
 
2563
2583
  if (!any_incomplete) {
2564
2584
  const pragma_pack_value = switch (p.comp.langopts.emulate) {
2565
- .clang => starting_pragma_pack,
2585
+ .clang, .no => starting_pragma_pack,
2566
2586
  .gcc => p.pragma_pack,
2567
2587
  // TODO: msvc considers `#pragma pack` on a per-field basis
2568
2588
  .msvc => p.pragma_pack,
@@ -3542,7 +3562,6 @@ fn declarator(
3542
3562
 
3543
3563
  const pointer_qt = try p.comp.type_store.put(p.comp.gpa, .{ .pointer = .{
3544
3564
  .child = d.qt,
3545
- .decayed = null,
3546
3565
  } });
3547
3566
  d.qt = try builder.finishQuals(pointer_qt);
3548
3567
  }
@@ -4141,7 +4160,10 @@ fn designation(p: *Parser, il: *InitList, init_qt: QualType, index_list: *IndexL
4141
4160
  const field = record_ty.fields[field_index];
4142
4161
  if (field.name_tok == 0) if (field.qt.getRecord(p.comp)) |field_record_ty| {
4143
4162
  // Recurse into anonymous field if it has a field by the name.
4144
- if (!field_record_ty.hasField(p.comp, target_name)) continue;
4163
+ if (!field_record_ty.hasField(p.comp, target_name)) {
4164
+ field_index += 1;
4165
+ continue;
4166
+ }
4145
4167
  try index_list.append(gpa, field_index);
4146
4168
  cur_il = try il.find(gpa, field_index);
4147
4169
  record_ty = field_record_ty;
@@ -4818,8 +4840,9 @@ fn gnuAsmStmt(p: *Parser, quals: Tree.GNUAssemblyQualifiers, asm_tok: TokenIndex
4818
4840
  const expected_items = 8; // arbitrarily chosen, most assembly will have fewer than 8 inputs/outputs/constraints/names
4819
4841
  const bytes_needed = expected_items * @sizeOf(Tree.Node.AsmStmt.Operand) + expected_items * 2 * @sizeOf(Node.Index);
4820
4842
 
4821
- var stack_fallback = std.heap.stackFallback(bytes_needed, gpa);
4822
- const allocator = stack_fallback.get();
4843
+ var bfa_buf: [bytes_needed]u8 = undefined;
4844
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
4845
+ const allocator = bfa.allocator();
4823
4846
 
4824
4847
  var operands: std.ArrayList(Tree.Node.AsmStmt.Operand) = .empty;
4825
4848
  defer operands.deinit(allocator);
@@ -4983,31 +5006,31 @@ fn assembly(p: *Parser, kind: enum { global, decl_label, stmt }) Error!?Node.Ind
4983
5006
  };
4984
5007
 
4985
5008
  const l_paren = try p.expectToken(.l_paren);
4986
- var result_node: ?Node.Index = null;
4987
- switch (kind) {
4988
- .decl_label => {
5009
+ const res = switch (kind) {
5010
+ .decl_label => blk: {
4989
5011
  const asm_str = try p.asmStr();
4990
5012
  const str = try p.removeNull(asm_str.val);
4991
5013
 
4992
5014
  const attr = Attribute{ .tag = .asm_label, .args = .{ .asm_label = .{ .name = str } }, .syntax = .keyword };
4993
5015
  try p.attr_buf.append(p.comp.gpa, .{ .attr = attr, .tok = asm_tok });
5016
+ break :blk asm_str.node;
4994
5017
  },
4995
- .global => {
5018
+ .global => blk: {
4996
5019
  const asm_str = try p.asmStr();
4997
5020
  try p.checkAsmStr(asm_str.val, l_paren);
4998
- result_node = try p.addNode(.{
5021
+ break :blk try p.addNode(.{
4999
5022
  .global_asm = .{
5000
5023
  .asm_tok = asm_tok,
5001
5024
  .asm_str = asm_str.node,
5002
5025
  },
5003
5026
  });
5004
5027
  },
5005
- .stmt => result_node = try p.gnuAsmStmt(quals, asm_tok, l_paren),
5006
- }
5028
+ .stmt => try p.gnuAsmStmt(quals, asm_tok, l_paren),
5029
+ };
5007
5030
  try p.expectClosing(l_paren, .r_paren);
5008
5031
 
5009
5032
  if (kind != .decl_label) _ = try p.expectToken(.semicolon);
5010
- return result_node;
5033
+ return res;
5011
5034
  }
5012
5035
 
5013
5036
  /// Same as stringLiteral but errors on unicode and wide string literals
@@ -5253,7 +5276,6 @@ fn stmt(p: *Parser) Error!Node.Index {
5253
5276
  if (!goto_expr.qt.isInvalid() and !goto_expr.qt.isPointer(p.comp)) {
5254
5277
  const result_qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
5255
5278
  .child = .{ .@"const" = true, ._index = .void },
5256
- .decayed = null,
5257
5279
  } });
5258
5280
  if (!goto_expr.qt.isRealInt(p.comp)) {
5259
5281
  try p.err(expr_tok, .incompatible_arg, .{ goto_expr.qt, result_qt });
@@ -5703,9 +5725,8 @@ fn returnStmt(p: *Parser) Error!?Node.Index {
5703
5725
  // ====== expressions ======
5704
5726
 
5705
5727
  pub fn macroExpr(p: *Parser) Compilation.Error!bool {
5706
- const res = p.expect(condExpr) catch |e| switch (e) {
5707
- error.OutOfMemory => return error.OutOfMemory,
5708
- error.FatalError => return error.FatalError,
5728
+ const res = p.expect(condExpr) catch |er| switch (er) {
5729
+ error.OutOfMemory, error.FatalError => |e| return e,
5709
5730
  error.ParsingFailed => return false,
5710
5731
  };
5711
5732
  return res.val.toBool(p.comp);
@@ -5905,6 +5926,7 @@ const CallExpr = union(enum) {
5905
5926
  .__builtin_reduce_xor,
5906
5927
  .__builtin_reduce_max,
5907
5928
  .__builtin_reduce_min,
5929
+ .__builtin_constant_p,
5908
5930
  => 1,
5909
5931
 
5910
5932
  .__builtin_complex,
@@ -5922,13 +5944,15 @@ const CallExpr = union(enum) {
5922
5944
 
5923
5945
  .__c11_atomic_store,
5924
5946
  .__atomic_store,
5947
+ .__atomic_store_n,
5948
+ .__atomic_load,
5925
5949
  .__c11_atomic_exchange,
5926
- .__atomic_exchange,
5927
5950
  .__c11_atomic_fetch_add,
5928
5951
  .__c11_atomic_fetch_sub,
5929
5952
  .__c11_atomic_fetch_or,
5930
5953
  .__c11_atomic_fetch_xor,
5931
5954
  .__c11_atomic_fetch_and,
5955
+ .__c11_atomic_fetch_nand,
5932
5956
  .__atomic_fetch_add,
5933
5957
  .__atomic_fetch_sub,
5934
5958
  .__atomic_fetch_and,
@@ -5948,6 +5972,9 @@ const CallExpr = union(enum) {
5948
5972
  .__atomic_exchange_n,
5949
5973
  => 3,
5950
5974
 
5975
+ .__atomic_exchange,
5976
+ => 4,
5977
+
5951
5978
  .__c11_atomic_compare_exchange_strong,
5952
5979
  .__c11_atomic_compare_exchange_weak,
5953
5980
  => 5,
@@ -5964,25 +5991,13 @@ const CallExpr = union(enum) {
5964
5991
 
5965
5992
  fn returnType(self: CallExpr, p: *Parser, args: []const Node.Index, func_qt: QualType) !QualType {
5966
5993
  if (self == .standard) {
5994
+ if (func_qt.isInvalid()) return .invalid;
5967
5995
  return if (func_qt.get(p.comp, .func)) |func_ty| func_ty.return_type else .invalid;
5968
5996
  }
5969
5997
  const builtin = self.builtin;
5970
5998
  const func_ty = func_qt.get(p.comp, .func).?;
5971
5999
  return switch (builtin.expanded.tag) {
5972
6000
  .common => |tag| switch (tag) {
5973
- .__c11_atomic_exchange => {
5974
- if (args.len != 4) return .invalid; // wrong number of arguments; already an error
5975
- const second_param = args[2];
5976
- return second_param.qt(&p.tree);
5977
- },
5978
- .__c11_atomic_load => {
5979
- if (args.len != 3) return .invalid; // wrong number of arguments; already an error
5980
- const first_param = args[1];
5981
- const qt = first_param.qt(&p.tree);
5982
- if (!qt.isPointer(p.comp)) return .invalid;
5983
- return qt.childType(p.comp);
5984
- },
5985
-
5986
6001
  .__atomic_fetch_add,
5987
6002
  .__atomic_add_fetch,
5988
6003
  .__c11_atomic_fetch_add,
@@ -6008,15 +6023,38 @@ const CallExpr = union(enum) {
6008
6023
  .__c11_atomic_fetch_nand,
6009
6024
 
6010
6025
  .__atomic_exchange_n,
6026
+ .__c11_atomic_exchange,
6027
+ => {
6028
+ const second_param = args[1].qt(&p.tree);
6029
+ return second_param;
6030
+ },
6031
+
6032
+ .__sync_fetch_and_add,
6033
+ .__sync_fetch_and_and,
6034
+ .__sync_fetch_and_nand,
6035
+ .__sync_fetch_and_or,
6036
+ .__sync_fetch_and_sub,
6037
+ .__sync_fetch_and_xor,
6038
+
6039
+ .__sync_add_and_fetch,
6040
+ .__sync_and_and_fetch,
6041
+ .__sync_nand_and_fetch,
6042
+ .__sync_or_and_fetch,
6043
+ .__sync_sub_and_fetch,
6044
+ .__sync_xor_and_fetch,
6045
+
6046
+ .__sync_swap,
6047
+ .__sync_lock_test_and_set,
6048
+ .__sync_val_compare_and_swap,
6011
6049
  => {
6012
- if (args.len != 3) return .invalid; // wrong number of arguments; already an error
6013
- const second_param = args[2];
6014
- return second_param.qt(&p.tree);
6050
+ if (args.len < 2) return .invalid;
6051
+ const second_param = args[1].qt(&p.tree);
6052
+ return second_param;
6015
6053
  },
6016
6054
  .__builtin_complex => {
6017
- if (args.len < 1) return .invalid; // not enough arguments; already an error
6018
- const last_param = args[args.len - 1];
6019
- return try last_param.qt(&p.tree).toComplex(p.comp);
6055
+ const last_param = args[args.len - 1].qt(&p.tree);
6056
+ if (last_param.isInvalid()) return .invalid;
6057
+ return try last_param.toComplex(p.comp);
6020
6058
  },
6021
6059
  .__atomic_compare_exchange,
6022
6060
  .__atomic_compare_exchange_n,
@@ -6027,9 +6065,8 @@ const CallExpr = union(enum) {
6027
6065
  .__c11_atomic_compare_exchange_strong,
6028
6066
  .__c11_atomic_compare_exchange_weak,
6029
6067
  => {
6030
- if (args.len != 6) return .invalid; // wrong number of arguments
6031
- const third_param = args[3];
6032
- return third_param.qt(&p.tree);
6068
+ const third_param = args[2].qt(&p.tree);
6069
+ return third_param;
6033
6070
  },
6034
6071
 
6035
6072
  .__builtin_elementwise_abs,
@@ -6058,13 +6095,12 @@ const CallExpr = union(enum) {
6058
6095
  .__builtin_elementwise_sub_sat,
6059
6096
  .__builtin_elementwise_fma,
6060
6097
  .__builtin_elementwise_popcount,
6098
+
6061
6099
  .__builtin_nondeterministic_value,
6062
6100
  => {
6063
- if (args.len < 1) return .invalid; // not enough arguments; already an error
6064
- const last_param = args[args.len - 1];
6065
- return last_param.qt(&p.tree);
6101
+ const first_param = args[0].qt(&p.tree);
6102
+ return first_param;
6066
6103
  },
6067
- .__builtin_nontemporal_load,
6068
6104
  .__builtin_reduce_add,
6069
6105
  .__builtin_reduce_mul,
6070
6106
  .__builtin_reduce_and,
@@ -6073,30 +6109,19 @@ const CallExpr = union(enum) {
6073
6109
  .__builtin_reduce_max,
6074
6110
  .__builtin_reduce_min,
6075
6111
  => {
6076
- if (args.len < 1) return .invalid; // not enough arguments; already an error
6077
- const last_param = args[args.len - 1];
6078
- return last_param.qt(&p.tree).childType(p.comp);
6112
+ const first_param = args[0].qt(&p.tree);
6113
+ if (first_param.isInvalid()) return .invalid;
6114
+ const vector_ty = first_param.get(p.comp, .vector) orelse return .invalid;
6115
+ return vector_ty.elem;
6079
6116
  },
6080
- .__sync_add_and_fetch,
6081
- .__sync_and_and_fetch,
6082
- .__sync_fetch_and_add,
6083
- .__sync_fetch_and_and,
6084
- .__sync_fetch_and_nand,
6085
- .__sync_fetch_and_or,
6086
- .__sync_fetch_and_sub,
6087
- .__sync_fetch_and_xor,
6088
- .__sync_lock_test_and_set,
6089
- .__sync_nand_and_fetch,
6090
- .__sync_or_and_fetch,
6091
- .__sync_sub_and_fetch,
6092
- .__sync_swap,
6093
- .__sync_xor_and_fetch,
6094
- .__sync_val_compare_and_swap,
6095
6117
  .__atomic_load_n,
6118
+ .__c11_atomic_load,
6119
+ .__builtin_nontemporal_load,
6096
6120
  => {
6097
- if (args.len < 1) return .invalid; // not enough arguments; already an error
6098
- const first_param = args[0];
6099
- return first_param.qt(&p.tree).childType(p.comp);
6121
+ const first_param = args[0].qt(&p.tree);
6122
+ if (first_param.isInvalid()) return .invalid;
6123
+ if (!first_param.isPointer(p.comp)) return .invalid;
6124
+ return first_param.childType(p.comp);
6100
6125
  },
6101
6126
  else => func_ty.return_type,
6102
6127
  },
@@ -6104,9 +6129,16 @@ const CallExpr = union(enum) {
6104
6129
  };
6105
6130
  }
6106
6131
 
6107
- fn finish(self: CallExpr, p: *Parser, func_qt: QualType, list_buf_top: usize, l_paren: TokenIndex) Error!Result {
6132
+ fn finish(
6133
+ self: CallExpr,
6134
+ p: *Parser,
6135
+ func_qt: QualType,
6136
+ list_buf_top: usize,
6137
+ l_paren: TokenIndex,
6138
+ args_ok: bool,
6139
+ ) Error!Result {
6108
6140
  const args = p.list_buf.items[list_buf_top..];
6109
- const return_qt = try self.returnType(p, args, func_qt);
6141
+ const return_qt: QualType = if (args_ok) try self.returnType(p, args, func_qt) else .invalid;
6110
6142
  switch (self) {
6111
6143
  .standard => |func_node| return .{
6112
6144
  .qt = return_qt,
@@ -6118,7 +6150,7 @@ const CallExpr = union(enum) {
6118
6150
  } }),
6119
6151
  },
6120
6152
  .builtin => |builtin| return .{
6121
- .val = try evalBuiltin(builtin.expanded, p, args),
6153
+ .val = if (args_ok) try evalBuiltin(builtin.expanded, p, args) else .{},
6122
6154
  .qt = return_qt,
6123
6155
  .node = try p.addNode(.{ .builtin_call_expr = .{
6124
6156
  .builtin_tok = builtin.builtin_tok,
@@ -6283,14 +6315,12 @@ pub const Result = struct {
6283
6315
  if (!adjusted_elem_qt.eqlQualified(a_elem, p.comp)) {
6284
6316
  a.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
6285
6317
  .child = adjusted_elem_qt,
6286
- .decayed = null,
6287
6318
  } });
6288
6319
  try a.implicitCast(p, .bitcast, tok);
6289
6320
  }
6290
6321
  if (!adjusted_elem_qt.eqlQualified(b_elem, p.comp)) {
6291
6322
  b.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
6292
6323
  .child = adjusted_elem_qt,
6293
- .decayed = null,
6294
6324
  } });
6295
6325
  try b.implicitCast(p, .bitcast, tok);
6296
6326
  }
@@ -6478,6 +6508,7 @@ pub const Result = struct {
6478
6508
  .add => {
6479
6509
  // if both aren't arithmetic one should be pointer and the other an integer
6480
6510
  if (a_sk.isPointer() == b_sk.isPointer() or a_sk.isInt() == b_sk.isInt()) return a.invalidBinTy(tok, b, p);
6511
+ try p.boundsSafetyCheckPointerArithmetic(a.qt, b.qt, tok, a.node);
6481
6512
 
6482
6513
  if (a_sk == .void_pointer or b_sk == .void_pointer)
6483
6514
  try p.err(tok, .gnu_pointer_arith, .{});
@@ -6496,6 +6527,7 @@ pub const Result = struct {
6496
6527
  .sub => {
6497
6528
  // if both aren't arithmetic then either both should be pointers or just the left one.
6498
6529
  if (!a_sk.isPointer() or !(b_sk.isPointer() or b_sk.isInt())) return a.invalidBinTy(tok, b, p);
6530
+ try p.boundsSafetyCheckPointerArithmetic(a.qt, b.qt, tok, a.node);
6499
6531
 
6500
6532
  if (a_sk == .void_pointer)
6501
6533
  try p.err(tok, .gnu_pointer_arith, .{});
@@ -7087,14 +7119,14 @@ pub const Result = struct {
7087
7119
  } else if (dest_sk.isPointer()) {
7088
7120
  if (src_sk.isPointer()) {
7089
7121
  cast_kind = .bitcast;
7122
+ } else if (src_sk == .bool) {
7123
+ cast_kind = .bool_to_pointer;
7090
7124
  } else if (src_sk.isInt()) {
7091
7125
  if (!src_sk.isReal()) {
7092
7126
  res.qt = res.qt.toReal(p.comp);
7093
7127
  try res.implicitCast(p, .complex_int_to_real, l_paren);
7094
7128
  }
7095
7129
  cast_kind = .int_to_pointer;
7096
- } else if (src_sk == .bool) {
7097
- cast_kind = .bool_to_pointer;
7098
7130
  } else if (res.qt.is(p.comp, .array)) {
7099
7131
  cast_kind = .array_to_pointer;
7100
7132
  } else if (res.qt.is(p.comp, .func)) {
@@ -7497,7 +7529,16 @@ fn issueDeclaredConstHereNote(p: *Parser, decl_ref: Tree.Node.DeclRef, var_name:
7497
7529
  try p.err(location, .declared_const_here, .{var_name});
7498
7530
  }
7499
7531
 
7500
- fn issueConstAssignmetDiagnostics(p: *Parser, node_idx: Node.Index, tok: TokenIndex) Compilation.Error!void {
7532
+ fn issueBoundsDeclaredHereNote(p: *Parser, decl_ref: Tree.Node.DeclRef, var_name: []const u8, bounds: Type.Pointer.Bounds) Compilation.Error!void {
7533
+ const location = switch (decl_ref.decl.get(&p.tree)) {
7534
+ .variable => |variable| variable.name_tok,
7535
+ .param => |param| param.name_tok,
7536
+ else => return,
7537
+ };
7538
+ try p.err(location, .pointer_bounds_declared_here, .{ var_name, @tagName(bounds) });
7539
+ }
7540
+
7541
+ fn issueConstAssignmentDiagnostics(p: *Parser, node_idx: Node.Index, tok: TokenIndex) Compilation.Error!void {
7501
7542
  if (p.unwrapNestedOperation(node_idx)) |unwrapped| {
7502
7543
  const name = p.tokSlice(unwrapped.name_tok);
7503
7544
  try p.err(tok, .const_var_assignment, .{ name, unwrapped.qt });
@@ -7530,7 +7571,7 @@ fn assignExpr(p: *Parser) Error!?Result {
7530
7571
 
7531
7572
  var is_const: bool = undefined;
7532
7573
  if (!p.tree.isLvalExtra(lhs.node, &is_const) or is_const) {
7533
- try p.issueConstAssignmetDiagnostics(lhs.node, tok);
7574
+ try p.issueConstAssignmentDiagnostics(lhs.node, tok);
7534
7575
  lhs.qt = .invalid;
7535
7576
  }
7536
7577
 
@@ -8226,7 +8267,7 @@ fn builtinChooseExpr(p: *Parser) Error!Result {
8226
8267
  return cond;
8227
8268
  }
8228
8269
 
8229
- /// vaStart : __builtin_va_arg '(' assignExpr ',' typeName ')'
8270
+ /// vaArg : __builtin_va_arg '(' assignExpr ',' typeName ')'
8230
8271
  fn builtinVaArg(p: *Parser, builtin_tok: TokenIndex) Error!Result {
8231
8272
  const l_paren = try p.expectToken(.l_paren);
8232
8273
  const va_list_tok = p.tok_i;
@@ -8258,6 +8299,62 @@ fn builtinVaArg(p: *Parser, builtin_tok: TokenIndex) Error!Result {
8258
8299
  };
8259
8300
  }
8260
8301
 
8302
+ /// vaArgPack : __builtin_va_arg_pack '(' ')'
8303
+ fn builtinVaArgPack(p: *Parser, builtin_tok: TokenIndex) Error!Result {
8304
+ const l_paren = try p.expectToken(.l_paren);
8305
+ try p.expectClosing(l_paren, .r_paren);
8306
+
8307
+ var res_qt: QualType = .invalid;
8308
+ if (!try p.checkVaPackFunc(builtin_tok, "__builtin_va_arg_pack")) {
8309
+ // Only add one error.
8310
+ } else if (!p.va_arg_pack_ctx.valid) {
8311
+ try p.err(builtin_tok, .va_pack_non_call, .{});
8312
+ } else if (!p.va_arg_pack_ctx.variadic) {
8313
+ try p.err(builtin_tok, .va_pack_non_variadic_call, .{});
8314
+ } else if (p.va_arg_pack_ctx.typed) {
8315
+ try p.err(builtin_tok, .va_pack_non_variadic_arg, .{});
8316
+ } else {
8317
+ res_qt = .void;
8318
+ }
8319
+ return .{
8320
+ .qt = res_qt,
8321
+ .node = try p.addNode(.{
8322
+ .builtin_va_arg_pack = .{ .builtin_tok = builtin_tok },
8323
+ }),
8324
+ };
8325
+ }
8326
+
8327
+ /// vaArgPackLen : __builtin_va_arg_pack_len '(' ')'
8328
+ fn builtinVaArgPackLen(p: *Parser, builtin_tok: TokenIndex) Error!Result {
8329
+ const l_paren = try p.expectToken(.l_paren);
8330
+ try p.expectClosing(l_paren, .r_paren);
8331
+
8332
+ _ = try p.checkVaPackFunc(builtin_tok, "__builtin_va_arg_pack_len");
8333
+
8334
+ return .{
8335
+ .qt = .int,
8336
+ .node = try p.addNode(.{
8337
+ .builtin_va_arg_pack_len = .{
8338
+ .builtin_tok = builtin_tok,
8339
+ },
8340
+ }),
8341
+ };
8342
+ }
8343
+
8344
+ fn checkVaPackFunc(p: *Parser, builtin_tok: TokenIndex, va_func_name: []const u8) !bool {
8345
+ const func_qt, _ = (try p.checkVaFunc(builtin_tok, va_func_name)) orelse return false;
8346
+
8347
+ var it = Attribute.Iterator.initType(func_qt, p.comp);
8348
+ while (it.next()) |item| switch (item[0].tag) {
8349
+ .always_inline, .gnu_inline => break,
8350
+ else => {},
8351
+ } else {
8352
+ try p.err(builtin_tok, .va_func_not_always_inline, .{va_func_name});
8353
+ return false;
8354
+ }
8355
+ return true;
8356
+ }
8357
+
8261
8358
  const OffsetKind = enum { bits, bytes };
8262
8359
 
8263
8360
  /// offsetof
@@ -8504,7 +8601,6 @@ fn unExpr(p: *Parser) Error!?Result {
8504
8601
 
8505
8602
  operand.qt = try p.comp.type_store.put(gpa, .{ .pointer = .{
8506
8603
  .child = operand.qt,
8507
- .decayed = null,
8508
8604
  } });
8509
8605
  }
8510
8606
  if (p.getNode(operand.node, .decl_ref_expr)) |decl_ref| {
@@ -8596,6 +8692,9 @@ fn unExpr(p: *Parser) Error!?Result {
8596
8692
  try p.err(tok, .not_assignable, .{});
8597
8693
  return error.ParsingFailed;
8598
8694
  }
8695
+ if (operand.qt.get(p.comp, .pointer)) |pointer| {
8696
+ try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
8697
+ }
8599
8698
  try operand.usualUnaryConversion(p, tok);
8600
8699
 
8601
8700
  if (operand.val.is(.int, p.comp) or operand.val.is(.int, p.comp)) {
@@ -8624,6 +8723,9 @@ fn unExpr(p: *Parser) Error!?Result {
8624
8723
  try p.err(tok, .not_assignable, .{});
8625
8724
  return error.ParsingFailed;
8626
8725
  }
8726
+ if (operand.qt.get(p.comp, .pointer)) |pointer| {
8727
+ try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
8728
+ }
8627
8729
  try operand.usualUnaryConversion(p, tok);
8628
8730
 
8629
8731
  if (operand.val.is(.int, p.comp) or operand.val.is(.int, p.comp)) {
@@ -8826,7 +8928,7 @@ fn unExpr(p: *Parser) Error!?Result {
8826
8928
  } else switch (p.comp.langopts.emulate) {
8827
8929
  .msvc => {}, // Doesn't support `_Complex` or `__imag` in the first place
8828
8930
  .gcc => operand.val = .zero,
8829
- .clang => {
8931
+ .clang, .no => {
8830
8932
  if (operand.val.is(.int, p.comp) or operand.val.is(.float, p.comp)) {
8831
8933
  operand.val = .zero;
8832
8934
  } else {
@@ -8886,7 +8988,7 @@ fn compoundLiteral(p: *Parser, qt_opt: ?QualType, opt_l_paren: ?TokenIndex) Erro
8886
8988
  try p.err(tok, .invalid_compound_literal_storage_class, .{@tagName(d.storage_class)});
8887
8989
  d.storage_class = .none;
8888
8990
  },
8889
- .register => if (p.func.qt == null) try p.err(p.tok_i, .illegal_storage_on_global, .{}),
8991
+ .register => if (p.func.qt == null) try p.err(p.tok_i, .register_on_global_compound_literal, .{}),
8890
8992
  else => {},
8891
8993
  }
8892
8994
 
@@ -8968,6 +9070,9 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
8968
9070
  try p.err(p.tok_i, .not_assignable, .{});
8969
9071
  return error.ParsingFailed;
8970
9072
  }
9073
+ if (operand.qt.get(p.comp, .pointer)) |pointer| {
9074
+ try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
9075
+ }
8971
9076
  try operand.usualUnaryConversion(p, p.tok_i);
8972
9077
 
8973
9078
  try operand.un(p, .post_inc_expr, p.tok_i);
@@ -8989,6 +9094,9 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
8989
9094
  try p.err(p.tok_i, .not_assignable, .{});
8990
9095
  return error.ParsingFailed;
8991
9096
  }
9097
+ if (operand.qt.get(p.comp, .pointer)) |pointer| {
9098
+ try p.checkPtrArithmeticAllowed(pointer, p.tok_i, operand.node);
9099
+ }
8992
9100
  try operand.usualUnaryConversion(p, p.tok_i);
8993
9101
 
8994
9102
  try operand.un(p, .post_dec_expr, p.tok_i);
@@ -9003,6 +9111,7 @@ fn suffixExpr(p: *Parser, lhs: Result) Error!?Result {
9003
9111
  const array_before_conversion = lhs;
9004
9112
  const index_before_conversion = index;
9005
9113
  var ptr = lhs;
9114
+
9006
9115
  try ptr.lvalConversion(p, l_bracket);
9007
9116
  try index.lvalConversion(p, l_bracket);
9008
9117
  if (ptr.qt.get(p.comp, .pointer)) |pointer_ty| {
@@ -9176,14 +9285,7 @@ fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex,
9176
9285
  return error.ParsingFailed;
9177
9286
  }
9178
9287
 
9179
- const func_qt = p.func.qt orelse {
9180
- try p.err(builtin_tok, .va_start_not_in_func, .{});
9181
- return;
9182
- };
9183
- const func_ty = func_qt.get(p.comp, .func) orelse return;
9184
- if (func_ty.kind != .variadic or func_ty.params.len == 0) {
9185
- return p.err(builtin_tok, .va_start_fixed_args, .{});
9186
- }
9288
+ _, const func_ty = (try p.checkVaFunc(builtin_tok, "va_start")) orelse return;
9187
9289
  const last_param_name = func_ty.params[func_ty.params.len - 1].name;
9188
9290
  const decl_ref = p.getNode(arg.node, .decl_ref_expr);
9189
9291
  if (decl_ref == null or last_param_name != try p.comp.internString(p.tokSlice(decl_ref.?.name_tok))) {
@@ -9191,6 +9293,19 @@ fn checkVaStartArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex,
9191
9293
  }
9192
9294
  }
9193
9295
 
9296
+ fn checkVaFunc(p: *Parser, builtin_tok: TokenIndex, va_func_name: []const u8) !?struct { QualType, Type.Func } {
9297
+ const func_qt = p.func.qt orelse {
9298
+ try p.err(builtin_tok, .va_func_not_in_func, .{va_func_name});
9299
+ return null;
9300
+ };
9301
+ const func_ty = func_qt.get(p.comp, .func) orelse return null;
9302
+ if (func_ty.kind != .variadic or func_ty.params.len == 0) {
9303
+ try p.err(builtin_tok, .va_func_fixed_args, .{va_func_name});
9304
+ return null;
9305
+ }
9306
+ return .{ func_qt, func_ty };
9307
+ }
9308
+
9194
9309
  fn checkArithOverflowArg(p: *Parser, builtin_tok: TokenIndex, first_after: TokenIndex, param_tok: TokenIndex, arg: *Result, idx: u32) !void {
9195
9310
  _ = builtin_tok;
9196
9311
  _ = first_after;
@@ -9320,7 +9435,7 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
9320
9435
 
9321
9436
  // We cannot refer to the function type here because the pointer to
9322
9437
  // type_store.extra might get invalidated while parsing args.
9323
- const func_qt, const params_len, const func_kind = blk: {
9438
+ const func_qt, const typed_params_len, const func_kind_base = blk: {
9324
9439
  var base_qt = lhs.qt;
9325
9440
  if (base_qt.get(p.comp, .pointer)) |pointer_ty| base_qt = pointer_ty.child;
9326
9441
  if (base_qt.isInvalid()) break :blk .{ base_qt, std.math.maxInt(usize), undefined };
@@ -9343,9 +9458,44 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
9343
9458
 
9344
9459
  const call_expr = CallExpr.init(p, lhs.node, func.node);
9345
9460
 
9461
+ const param_len_override = call_expr.paramCountOverride();
9462
+ const params_len = param_len_override orelse typed_params_len;
9463
+ const func_kind = if (param_len_override != null) .normal else func_kind_base;
9464
+
9346
9465
  while (p.eatToken(.r_paren) == null) {
9347
9466
  const param_tok = p.tok_i;
9348
9467
  if (arg_count == params_len) first_after = p.tok_i;
9468
+
9469
+ // Check for __builtin_va_arg_pack
9470
+ {
9471
+ var i = p.tok_i;
9472
+ loop: switch (p.tok_ids[i]) {
9473
+ .l_paren => {
9474
+ i += 1;
9475
+ continue :loop p.tok_ids[i];
9476
+ },
9477
+ .identifier => if (mem.eql(u8, p.tokSlice(i), "__builtin_va_arg_pack")) {
9478
+ @branchHint(.cold);
9479
+ p.va_arg_pack_ctx = .{
9480
+ .valid = true,
9481
+ .variadic = func_kind != .normal,
9482
+ .typed = arg_count < typed_params_len,
9483
+ };
9484
+ defer p.va_arg_pack_ctx = .{};
9485
+
9486
+ const arg = try p.expect(assignExpr);
9487
+ try p.list_buf.append(gpa, arg.node);
9488
+ arg_count += 1;
9489
+ if (p.eatToken(.comma)) |_| {
9490
+ try p.err(i, .va_pack_non_final_arg, .{});
9491
+ continue;
9492
+ }
9493
+ try p.expectClosing(l_paren, .r_paren);
9494
+ break;
9495
+ },
9496
+ else => {},
9497
+ }
9498
+ }
9349
9499
  var arg = try p.expect(assignExpr);
9350
9500
 
9351
9501
  if (call_expr.shouldPerformLvalConversion(arg_count)) {
@@ -9353,7 +9503,7 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
9353
9503
  }
9354
9504
  if ((arg.qt.hasIncompleteSize(p.comp) and !arg.qt.is(p.comp, .void)) or arg.qt.isInvalid()) return error.ParsingFailed;
9355
9505
 
9356
- if (arg_count >= params_len) {
9506
+ if (arg_count >= typed_params_len) {
9357
9507
  if (call_expr.shouldPromoteVarArg(arg_count)) switch (arg.qt.base(p.comp).type) {
9358
9508
  .int => |int_ty| if (int_ty == .int) try arg.castToInt(p, arg.qt.promoteInt(p.comp), param_tok),
9359
9509
  .float => |float_ty| if (float_ty == .double) try arg.castToFloat(p, .double, param_tok),
@@ -9407,19 +9557,23 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
9407
9557
  }
9408
9558
  if (func_qt.isInvalid()) {
9409
9559
  // Skip argument count checks.
9410
- return try call_expr.finish(p, func_qt, list_buf_top, l_paren);
9560
+ return try call_expr.finish(p, func_qt, list_buf_top, l_paren, false);
9411
9561
  }
9412
9562
 
9413
- if (call_expr.paramCountOverride()) |expected| {
9414
- if (expected != arg_count) {
9415
- try p.err(first_after, .expected_arguments, .{ expected, arg_count });
9416
- }
9417
- } else switch (func_kind) {
9563
+ const r_paren = p.tok_i - 1;
9564
+ var args_ok = true;
9565
+ switch (func_kind) {
9418
9566
  .normal => if (params_len != arg_count) {
9419
- try p.err(first_after, .expected_arguments, .{ params_len, arg_count });
9567
+ try p.err(
9568
+ if (arg_count < params_len) r_paren else first_after,
9569
+ .expected_arguments,
9570
+ .{ params_len, arg_count },
9571
+ );
9572
+ args_ok = false;
9420
9573
  },
9421
9574
  .variadic => if (arg_count < params_len) {
9422
- try p.err(first_after, .expected_at_least_arguments, .{ params_len, arg_count });
9575
+ try p.err(r_paren, .expected_at_least_arguments, .{ params_len, arg_count });
9576
+ args_ok = false;
9423
9577
  },
9424
9578
  .old_style => if (params_len != arg_count) {
9425
9579
  if (params_len == 0)
@@ -9429,10 +9583,60 @@ fn callExpr(p: *Parser, lhs: Result) Error!Result {
9429
9583
  },
9430
9584
  }
9431
9585
 
9432
- return try call_expr.finish(p, func_qt, list_buf_top, l_paren);
9586
+ return try call_expr.finish(p, func_qt, list_buf_top, l_paren, args_ok);
9587
+ }
9588
+
9589
+ fn boundsSafetyCheckArrayAccess(p: *Parser, lhs: Result, rhs: Result, l_bracket: TokenIndex) !void {
9590
+ if (!p.comp.hasClangStyleBoundsSafety()) return;
9591
+
9592
+ const ptr_res, const pointer, const index = if (lhs.qt.get(p.comp, .pointer)) |pointer| .{ lhs, pointer, rhs } else .{ rhs, rhs.qt.get(p.comp, .pointer).?, lhs };
9593
+
9594
+ switch (pointer.bounds) {
9595
+ .c, .unsafe_indexable => {},
9596
+ .single => {
9597
+ if (!index.val.isZero(p.comp)) {
9598
+ try p.err(l_bracket, .single_requires_zero_index, .{});
9599
+ if (p.unwrapNestedOperation(ptr_res.node)) |unwrapped| {
9600
+ const name = p.tokSlice(unwrapped.name_tok);
9601
+ try p.issueBoundsDeclaredHereNote(unwrapped, name, pointer.bounds);
9602
+ }
9603
+ }
9604
+ },
9605
+ }
9606
+ }
9607
+
9608
+ fn boundsSafetyCheckPointerArithmetic(p: *Parser, lhs: QualType, rhs: QualType, tok: TokenIndex, node: Tree.Node.Index) !void {
9609
+ if (!p.comp.hasClangStyleBoundsSafety()) return;
9610
+
9611
+ const pointer = if (rhs.isInt(p.comp))
9612
+ lhs.get(p.comp, .pointer) orelse return
9613
+ else if (lhs.isInt(p.comp))
9614
+ rhs.get(p.comp, .pointer) orelse return
9615
+ else
9616
+ return;
9617
+
9618
+ try p.checkPtrArithmeticAllowed(pointer, tok, node);
9619
+ }
9620
+
9621
+ fn checkPtrArithmeticAllowed(p: *Parser, pointer: Type.Pointer, tok: TokenIndex, node: Tree.Node.Index) !void {
9622
+ if (!p.comp.hasClangStyleBoundsSafety()) return;
9623
+
9624
+ switch (pointer.bounds) {
9625
+ .c, .unsafe_indexable => {},
9626
+ .single => {
9627
+ // clang issues this diagnostic even with a constant `0` operand
9628
+ try p.err(tok, .pointer_arith_single, .{});
9629
+ if (p.unwrapNestedOperation(node)) |unwrapped| {
9630
+ const name = p.tokSlice(unwrapped.name_tok);
9631
+ try p.issueBoundsDeclaredHereNote(unwrapped, name, pointer.bounds);
9632
+ }
9633
+ },
9634
+ }
9433
9635
  }
9434
9636
 
9435
9637
  fn checkArrayBounds(p: *Parser, index: Result, array: Result, tok: TokenIndex) !void {
9638
+ try p.boundsSafetyCheckArrayAccess(array, index, tok);
9639
+
9436
9640
  if (index.val.opt_ref == .none) return;
9437
9641
 
9438
9642
  const array_len = array.qt.arrayLen(p.comp) orelse return;
@@ -9579,6 +9783,8 @@ fn primaryExpr(p: *Parser) Error!?Result {
9579
9783
  .common => |tag| switch (tag) {
9580
9784
  .__builtin_choose_expr => return try p.builtinChooseExpr(),
9581
9785
  .__builtin_va_arg => return try p.builtinVaArg(name_tok),
9786
+ .__builtin_va_arg_pack => return try p.builtinVaArgPack(name_tok),
9787
+ .__builtin_va_arg_pack_len => return try p.builtinVaArgPackLen(name_tok),
9582
9788
  .__builtin_offsetof => return try p.builtinOffsetof(name_tok, .bytes),
9583
9789
  .__builtin_bitoffsetof => return try p.builtinOffsetof(name_tok, .bits),
9584
9790
  .__builtin_types_compatible_p => return try p.typesCompatible(name_tok),
@@ -9719,8 +9925,9 @@ fn primaryExpr(p: *Parser) Error!?Result {
9719
9925
  if (p.func.pretty_ident) |some| {
9720
9926
  qt = some.qt;
9721
9927
  } else if (p.func.qt) |func_qt| {
9722
- var sf = std.heap.stackFallback(1024, gpa);
9723
- var allocating: Io.Writer.Allocating = .init(sf.get());
9928
+ var bfa_buf: [1024]u8 = undefined;
9929
+ var bfa: std.heap.BufferFirstAllocator = .init(&bfa_buf, gpa);
9930
+ var allocating: std.Io.Writer.Allocating = .init(bfa.allocator());
9724
9931
  defer allocating.deinit();
9725
9932
 
9726
9933
  func_qt.printNamed(p.tokSlice(p.func.name), p.comp, &allocating.writer) catch return error.OutOfMemory;
@@ -10009,8 +10216,9 @@ fn charLiteral(p: *Parser) Error!?Result {
10009
10216
  };
10010
10217
 
10011
10218
  const max_chars_expected = 4;
10012
- var sf = std.heap.stackFallback(max_chars_expected * @sizeOf(u32), gpa);
10013
- const allocator = sf.get();
10219
+ var bfa_buf: [max_chars_expected]u32 = undefined;
10220
+ var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa);
10221
+ const allocator = bfa.allocator();
10014
10222
  var chars: std.ArrayList(u32) = .empty;
10015
10223
  defer chars.deinit(allocator);
10016
10224
 
@@ -10277,16 +10485,13 @@ fn fixedSizeInt(p: *Parser, base: u8, buf: []const u8, suffix: NumberSuffix, tok
10277
10485
  if (res.qt.intRankOrder(suffix_qt, p.comp).compare(.lt)) continue;
10278
10486
  const max_int = try Value.maxInt(res.qt, p.comp);
10279
10487
  if (interned_val.compare(.lte, max_int, p.comp)) break;
10280
- } else {
10281
- if (p.comp.langopts.emulate == .gcc) {
10282
- if (p.comp.target.hasInt128()) {
10283
- res.qt = .int128;
10284
- } else {
10285
- res.qt = .long_long;
10286
- }
10488
+ } else switch (p.comp.langopts.emulate) {
10489
+ .no, .gcc => if (p.comp.target.hasInt128()) {
10490
+ res.qt = .int128;
10287
10491
  } else {
10288
- res.qt = .ulong_long;
10289
- }
10492
+ res.qt = .long_long;
10493
+ },
10494
+ .msvc, .clang => res.qt = .ulong_long,
10290
10495
  }
10291
10496
 
10292
10497
  res.node = try p.addNode(.{ .int_literal = .{ .qt = res.qt, .literal_tok = tok_i } });
@@ -10604,12 +10809,7 @@ fn genericSelection(p: *Parser) Error!?Result {
10604
10809
  }
10605
10810
 
10606
10811
  test "Node locations" {
10607
- var arena_state: std.heap.ArenaAllocator = .init(std.testing.allocator);
10608
- defer arena_state.deinit();
10609
- const arena = arena_state.allocator();
10610
-
10611
- var diagnostics: Diagnostics = .{ .output = .ignore };
10612
- var comp = Compilation.init(std.testing.allocator, arena, std.testing.io, &diagnostics, Io.Dir.cwd());
10812
+ var comp = try Compilation.init(.testing);
10613
10813
  defer comp.deinit();
10614
10814
 
10615
10815
  const file = try comp.addSourceFromBuffer("file.c",
@@ -10621,7 +10821,7 @@ test "Node locations" {
10621
10821
 
10622
10822
  const builtin_macros = try comp.generateBuiltinMacros(.no_system_defines);
10623
10823
 
10624
- var pp = Preprocessor.init(&comp, .default);
10824
+ var pp = try Preprocessor.init(&comp, .testing);
10625
10825
  defer pp.deinit();
10626
10826
  try pp.addBuiltinMacros();
10627
10827
 
@@ -10633,7 +10833,6 @@ test "Node locations" {
10633
10833
  var tree = try Parser.parse(&pp);
10634
10834
  defer tree.deinit();
10635
10835
 
10636
- try std.testing.expectEqual(0, comp.diagnostics.total);
10637
10836
  for (tree.root_decls.items[tree.root_decls.items.len - 3 ..], 0..) |node, i| {
10638
10837
  const slice = tree.tokSlice(node.tok(&tree));
10639
10838
  const expected_slice = switch (i) {