Codex/sync upstream 0.9.8 - #1
Merged
Merged
Conversation
Remove inline declarations
…ts, and documentation ## Compiler - Lexer: fix off-by-one in PEEK_NEXT/PEEK_NEXT2 boundary checks - Parser: fix memory leaks in parse_file_expression, parse_variable_declaration, and string interpolation handling; fix undersized buffer for escaped strings - Semacheck2: fix wrong constant in upvalue limit error message (MAX_LOCALS → MAX_UPVALUES) - Codegen: fix wrong variable name in for-loop register allocation (temp2 → temp3); replace multiple early-return paths in visit_postfix_expr with goto cleanup to prevent leaking self_list/args arrays; fix register clobbering in LOCATION_CLASS_IVAR_OUTER assignment; remove unnecessary NOP for empty statements; add VISIT_MOVE_OPT macro to consolidate pragma patterns - Optimizer: fix constant folding checking wrong register (inst2->p2 → inst2->p1); fix NEG optimization writing to wrong destination register (inst->p2 → inst->p1); fix OPCODE_SET_FOUR8bit macro missing opcode field - IR code: convert register allocation from bool[256] array to compact bitmask (32 bytes), improving cache efficiency; add bounds checks on empty label stacks; add assertion after inst_new allocation ## Runtime / VM - Fix boolean fast-path comparison incorrectly applied to ordered comparisons (LT, GT, LEQ, GEQ) — now restricted to EQ/NEQ only - Fix crash in gravity_vm_setslot/gravity_vm_getslot when no frames exist - Fix OPCODE_GET_FOUR8bit macro inconsistency with encoder - Fix list_iterator_next out-of-bounds read (add bounds check) - Fix list_storeat duplicate marray_set after resize - Fix range_contains not handling reversed ranges correctly - Fix function_exec default-arg filling using wrong index formula - Fix int_random truncation from gravity_int_t to int - Fix string_count broken partial-match logic (rewrite using string_strnstr) - Fix string_upper/string_lower off-by-one (iterated one byte past end) - Fix string_loadat UTF-8 corruption when reversing multi-byte sequences - Fix string_loop iterating byte-by-byte instead of by UTF-8 character - Fix string_iterator/string_iterator_next missing bounds checks - Fix fiber_abort wrong nargs check (args[0] is self, not the message) - Fix system_input blindly stripping last char instead of checking for newline - Fix convert_map2string/convert_list2string losing original pointer on realloc failure - Fix gravity_class_grow discarding existing ivar values when growing - Add overflow guard to gravity_function_cpool_add (uint16_t limit) ## Optional Modules - Math: fix atan2 → atan2f for float builds; use POW macro consistently in math_xrt and math_round; fix division-by-zero in math_logx when base=1; fix integer overflow in math_random when range endpoint is GRAVITY_INT_MAX; fix pointer arithmetic bugs in math_round string truncation - File: fix memory leak in file_buildpath (result string not freed); fix leak in scan_directory recursive path; fix wrong nargs check in file_open; fix leaked FILE* when instance creation fails; fix crash on negative read size; fix swapped fread/fwrite arguments (size vs count); fix integer overflow in read buffer resize; fix typo "enought" → "enough" - JSON: rewrite string escaping in JSON.stringify to properly escape backslashes, quotes, control characters, and handle large strings - ENV: add Windows compatibility for environ access; simplify key-length loop ## Utilities - Debug: add buffer overflow protection in DUMP_VM macros; add bounds check in opcode_name; fix memory leak in gravity_disassemble - JSON serializer: fix escape buffer too small (len*2 → len*6+1); add control character escaping (\uXXXX); add overflow check - Utils: fix uninitialized fd in file_read; fix swapped PathCombineA arguments on Windows; fix file_name_frompath returning NULL when no separator found; add NULL check in string_dup; fix signed arithmetic and missing digit validation in number_from_bin ## Shared / Core Data Structures - gravity_array.h: fix marray_push updating capacity before confirming realloc succeeded; add bounds check before write; fix marray_resize/marray_resize0 to check realloc result - gravity_hash.c: fix gravity_hash_memsize counting buckets as nodes; improve float hashing precision (%f → %.17g) ## CLI - Fix memory leaks in unittest_scan (full_path not freed on skip/recurse) - Fix inline execution buffer leak ## Documentation - Add comprehensive ARCHITECTURE.md covering the full compilation pipeline, VM internals, value system, garbage collector, instruction set, and embedding API - Add CLAUDE.md with project conventions for Claude Code - Update README.md: add Building, Usage, and Project Structure sections; update line counts to reflect current codebase size; enhance Features list; add links to ARCHITECTURE.md ## Tests - Add 30 new unit tests covering all major bug fixes: bool comparison, string operations (count, upper/lower, UTF-8 iteration/reversal), math functions (round, logx, xrt, random), file I/O, JSON escaping, range operations, list bounds, fiber abort, optimizer constant folding, and more Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…le-free gravity_opt_free() was called unconditionally at the top of gravity_core_free(), before the refcount guard. This causes a double-free when gravity_compiler_reset() is called before teardown. gravity_compiler_reset() runs a mini-VM internally (internal_vm_cleanup) which frees GC objects via the GC callback — including the optionals. When gravity_core_free() is subsequently called, gravity_opt_free() then attempts to free already-freed memory. The fix moves gravity_opt_free() to after the refcount check, so optionals are only freed when the last VM is being torn down. Reproducer: call gravity_compiler_reset() on a compiler instance, then call gravity_core_free(). Crashes reliably under AddressSanitizer.
…vity-opt-free fix(core): move gravity_opt_free after refcount check to prevent double-free
…ite improvements Runtime / VM: - Add configurable fiber stack size limit (DEFAULT_MAXSTACK_SIZE = 1M slots). Infinite recursion and stack exhaustion now produce a clean RUNTIME error instead of a hard crash or silent failure. - Expose GRAVITY_VM_MAXSTACK key via gravity_vm_get/set for runtime tuning. - Fix gravity_fiber_reassign stack growth: large register-window in $moduleinit could push stacktop past the initial allocation (issue marcobambini#437). Compiler: - Fix class $init chain infinite recursion: parent $init helpers ($init2, $init3, …) previously used a dynamic name lookup against self, which resolved to the wrong override in subclass context. Now emits a direct static closure reference (LOADK) via ircode_patch_init_direct. Tests: - Re-enable test/disabled/heap.gravity and test/disabled/loop1.gravity, moved to test/unittest/. Both now pass with the new OOM error reporting. - Fix two bugs in heap.gravity (wrong variable assigned, wrong constructor called). - Add regression test for issue marcobambini#437 (bugfix_stack_overflow_large_regwin). - Delete test/disabled/ directory. Docs: - Add CHANGELOG.md covering all versions from 0.2.8 to 0.9.6. - Update README: CMake build instructions, Testing section, Embedding API example, CHANGELOG link, replace Gitter with GitHub Discussions. - Update CLAUDE.md: document fuzzy/infiniteloop test dirs and gravity_vm_get/set.
…n (issue marcobambini#420) Two root causes behind 'RUNTIME ERROR: Unknown LOADK index' on -c/-x path: 1. gravity_json.c: float constants were serialized with '%f' (6 decimal places), silently rounding small values like -0.000000004 to -0.000000. When two distinct floats rounded to the same string, one was dropped from the JSON pool, leaving the bytecode referencing a non-existent index. Fixed by switching to '%.17g' (17 significant digits, full IEEE 754 double round-trip), with a '.0' suffix appended for whole-number values so they deserialize as float rather than integer. 2. gravity_value.c: gravity_function_cpool_add used the epsilon-based gravity_value_equals (EPSILON=1e-6) to detect duplicate constants. Any two floats differing by less than 1e-6 were merged into one cpool entry, causing index mismatches at runtime. The cpool now uses exact bit-level comparison (v.f != v2.f) for float values before falling back to the fuzzy equality check used for all other types. Also fix run_all.sh to work on macOS where GNU 'timeout' is not available: detect 'timeout', 'gtimeout' (brew coreutils), or fall back to a pure-bash background kill-watcher that returns exit code 124 on expiry.
…ssue marcobambini#426) The four #ifndef GRAVITY_INCLUDE_* / #define ... / #endif blocks unconditionally defined every optional-module guard the moment the header was included, making the guards useless for embedders who want to exclude specific modules. Fix: remove the unconditional defines from gravity_optionals.h so the guard macros must be explicitly set by the includer. The three Gravity source files that want all optionals enabled (gravity_vm.c, gravity.c, gravity_parser.c) now define all four GRAVITY_INCLUDE_* macros before including gravity_optionals.h. Embedders can now selectively include only the modules they need.
Four problems corrected: 1. 'gravity' and 'example' were declared .PHONY despite producing real files, causing make to unconditionally rebuild them on every invocation regardless of whether any source had changed. Removed both from .PHONY. Only 'all', 'clean', and 'lib' are genuinely phony targets. 2. 'lib: gravity' was a wrong dependency — building the shared library only requires the compiled object files, not the gravity CLI executable. Changed to 'lib: $(OBJ)'. 3. GRAVITY_SRC (src/cli/gravity.c) and EXAMPLE_SRC (examples/example.c) were passed directly to the linker step rather than compiled separately, so -MMD never generated .d files for them. Header changes in those files would not trigger rebuilds. Both are now compiled to .o first (GRAVITY_OBJ / EXAMPLE_OBJ) so make tracks their header dependencies correctly via the generated .d files. 4. 'make clean' removed libgravity.so and gravity.dll but missed libgravity.dylib (macOS). Added it to the clean target along with the new GRAVITY_OBJ and EXAMPLE_OBJ intermediates.
…es, and build system
- Install now copies headers. - Build considers `BUILD_SHARED_LIBS` when deciding to build `gravityapi` target. - Install now works when CLI is disabled. - Local in-source install on Windows is now a CMake option. - Install paths propagated to parent scope so CLI install can see them.
…packaging Change CMake install instructions to be more readily packagable.
Automated security fix generated by OrbisAI Security
…-strcat-buffer-overflow fix: add buffer-length check in console.c
…core_init
VALUE_FROM_OBJECT() evaluates its argument twice when
GRAVITY_USE_HIDDEN_INITIALIZERS is not set:
#define VALUE_FROM_OBJECT(obj) ((gravity_value_t){.isa = ((gravity_object_t *)(obj)->isa), .p = (gravity_object_t *)(obj)})
Six bind sites in gravity_core_init called computed_property_create()
inline inside that macro (Object.class, Object.meta, Int.min/max meta,
Float.min/max meta), so each of those computed properties was created
twice: one copy bound, the duplicate orphaned (~2.2KB leaked per
gravity_core_init).
Use the same temp-variable pattern the rest of gravity_core_init already
uses for every other computed property.
Also free the nine computed properties missing from gravity_core_free's
manual free list (Object.class, Object.meta, Range.from, Range.to,
String.bytes, Int meta min/max, Float meta min/max) — previously leaked
on every core init/free cycle.
gravity_vm_new calls gravity_gc_setenabled(vm, true) before marray_init(vm->graylist). Enabling the GC can trigger a collection (gravity_gc_check -> gravity_gc_start), which grows the graylist buffer via marray_push/realloc. The marray_init that follows then zeroes the array struct, orphaning that buffer (leaked once per VM). Initialize graylist/gctemp before enabling the GC.
Fix three VM memory leaks: computed-property double creation, missing frees in gravity_core_free, orphaned GC gray-list buffer
…#446) parse_number_expression checked for a 0b/0o/0x prefix by reading value[1] whenever value[0] was '0', without first confirming the token is at least 2 bytes long. token.value points directly into the caller's source buffer (lexer->buffer + lexer->offset) and is not separately zero terminated, so a source whose last byte is a lone '0' caused a 1-byte read past the end of the buffer. The CLI is unaffected because file_read over-allocates by one byte and zero terminates, but gravity_compiler_run accepts an explicit length and embedders may legitimately pass an exact-size, non terminated buffer. Confirmed with ASan on a 3-byte malloc holding "x=0": ERROR: AddressSanitizer: heap-buffer-overflow READ of size 1 at 0x6020000000d3 thread T0 #0 parse_number_expression gravity_parser.c:684 Guard the prefix check with token.bytes > 1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…er-oob-read fix: heap out-of-bounds read in parse_number_expression (marcobambini#446)
gravity_opt_register() runs once per gravity_core_register(), but gravity_opt_free() is reached only on the last gravity_core_free(), when the core refcount hits zero. In the usual embedding flow (a mini VM for the compiler plus a real VM) each optional class therefore ends up with a refcount of 2 while only one decrement ever happens, so Math/ENV/JSON/File and their metaclasses are never freed. They are not owned by any VM garbage collector, so nothing else can reclaim them. Track the number of outstanding registrations and balance them all when the last VM is torn down. gravity_opt_free() still runs only after the refcount check, preserving the ordering introduced by dd81589, and each optional keeps its own refcount and NULL guard so it is still freed exactly once. Verified with macOS leaks on examples/example.c: allocations owned by gravity and still live at exit drop from 347 blocks / 31,698 bytes to zero, and the total live heap goes from 534 nodes / 66 KB to 187 nodes / 31 KB. Running a script through the CLI improves the same way (537 nodes / 67 KB to 190 nodes / 31 KB). Unit tests pass 352/352, also under AddressSanitizer, together with a stress program covering repeated teardown and re-init, two concurrent VMs with a partial teardown, a reused compiler, and an extra unbalanced gravity_core_free(). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…arcobambini#447, marcobambini#448) gravity_vm_loadbuffer() trusted the shape of the JSON it was handed, and the scanner underneath it had several out of bounds and overflow issues. All of them are reachable through `gravity -x` with a hand written file. gravity_vm_loadbuffer: - a top level entry was tested for emptiness through u.object.length before its type was checked, reading an unset union member whenever the entry was not an object - a deserialized function may legitimately have a NULL identifier (missing field, or an anonymous function serialized as $anon_), and strlen() was called on it unconditionally: {"x":{"type":"function"}} was enough to crash the loader (marcobambini#444). A top level function must be named, so a NULL identifier is now a load error - string_casencmp(identifier, INITMODULE_NAME, strlen(identifier)) compared only as many characters as the identifier is long, so any prefix of $moduleinit was accepted as the module initializer. Use string_cmp() for a full comparison json_parse_ex: - the "\uXXXX" escape, the trailing surrogate, and the true/false/null literals all checked one byte less than they consume, so each could read one byte past the end of a buffer that is not NUL terminated (marcobambini#448). gravity_vm_loadbuffer accepts exactly such a buffer - during the first pass u.object.values is a byte tally, not a pointer, and was incremented through a json_char pointer: undefined behaviour on a null pointer, which traps under -fsanitize=undefined (marcobambini#448). Keep the tally in a uintptr_t, which also stops it truncating on LLP64 targets - integer and exponent accumulators were multiplied without any range check, overflowing signed 64-bit on a long digit run (marcobambini#447). The integer accumulator now reports an out of range literal, the exponent saturates, and fraction digits below the precision of a double are dropped while keeping the fraction scale in sync murmur3_32 read the key four bytes at a time through a uint32_t pointer, which is undefined for an unaligned key and faults outright on strict alignment targets. memcpy each block instead; byte order and therefore every hash value is unchanged, and compilers fold it back to a single unaligned load. Adds test/loadbuffer/: one malformed executable per rejection path plus a valid round trip as a positive control, and json_bounds.c for what the CLI cannot reach, since the CLI always hands the loader a NUL terminated buffer while the API does not. Build it with `make jsontest`, ideally under a sanitizer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gravity_compiler_run() called gravity_core_register() on each invocation, but only gravity_compiler_free() ever released a reference. An embedder reusing one compiler for N compilations left N-1 unreleased core references, so gravity_core_free() never reached refcount 0 and neither the core classes nor the optional ones (Math/ENV/JSON/File) were freed (~107 KB retained at exit). On a successful compile the compiler was never reset, so the next run also overwrote compiler->vm and orphaned the previous mini VM struct (320 bytes per extra compilation). The mini VM holds no per-compilation state (it is just a container for the transfer/cleanup callbacks), so create it once and reuse it, and pair the core reference it takes with a release wherever the mini VM is freed. The refcount keeps the core alive for a real VM created with gravity_vm_new, which owns its own reference. This also removes the unconditional gravity_core_free() in gravity_compiler_free(): it released a reference the compiler may never have taken, so freeing a never-run compiler while a VM was alive freed the core out from under it (segfault). Verified with a program compiling N times on one compiler followed by a full teardown: retained heap at exit is now 534 nodes / 66 KB for N=1, 3 and 10, identical to the single-compile flow in examples/example.c, with no unreachable blocks. Unit tests 350/350, ASan/UBSan build of examples/example.c and of the test suite report nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
) Int arithmetic in Gravity wraps around on overflow, which is what the runtime operators and the constant folder have always produced, but the wrap was performed directly on signed operands: signed overflow is undefined behaviour in C, so every one of those sites traps under -fsanitize=undefined and is at the mercy of the optimizer elsewhere. Add GRAVITY_INT_ADD/SUB/MUL/NEG/DIV/REM in gravity_value.h, which do the arithmetic on the unsigned counterpart and convert back. The values are unchanged, they are simply no longer undefined. Both operands are widened to 64bit so a single definition serves either GRAVITY_ENABLE_INT64 setting. All three paths now go through them, so the folded constant and the runtime cannot drift apart: - CHECK_FAST_BINARY_MATH / CHECK_FAST_UNARY_MATH take the Int operation as a macro parameter and apply it on the Int path only, the Float one keeps using the plain operator - operator_int_add/sub/mul/neg/div/rem in gravity_core.c - optimize_const_instruction in gravity_optimizer.c GRAVITY_INT_DIV and GRAVITY_INT_REM also cover GRAVITY_INT_MIN op -1, which does not merely wrap: on x86 idiv faults and the process dies with SIGFPE, both while folding and at runtime. Separately, optimize_const_instruction folded a floating point REM by truncating both operands to int64_t. That divided by zero for any 0 < |divisor| < 1, and disagreed with the runtime on every operand with a fractional part: 2.5 % 2.0 folded to 0 where the VM evaluates 0.5. Fold with remainder(), which is what operator_float_rem computes. REM is also dispatched on the class of the left operand, so a mixed Int/Float expression runs operator_int_rem and does not follow float semantics at all. Those are left to the runtime instead of folded. Adds a unit test which compares each folded expression against the same operation evaluated at runtime, so the two paths cannot silently diverge again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Harden the JSON executable loader and scanner (marcobambini#444, marcobambini#447, marcobambini#448).
Fix Int overflow and float remainder constant folding (marcobambini#443).
Fix optional classes never released due to unbalanced refcount (marcobambini#442).
Fix core reference leaked by every gravity_compiler_run (marcobambini#442).
Travis is no longer running for this repository. Add a GitHub Actions workflow that builds with gcc and clang on Linux and macOS and runs the unit tests, the -t assertion pass, and the JSON loader tests. A second job builds with -fsanitize=address,undefined and runs the unit tests, the fuzzing corpus and the JSON loader tests through it, so the memory safety fixes stay covered. The unit test timeouts in run_all.sh are calibrated for an optimized build, so the sanitizer job runs the tests directly with a generous per test timeout instead. Also run the -t assertion pass in .travis.yml for parity. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gravity -i built the wrapped source in a heap buffer and passed it to gravity_compiler_run with is_static false. That hands the buffer to the lexer, which frees it in parser_run once parsing is done, so the free in the CLI cleanup path was a second free of the same pointer. The file paths do not hit this because they never free the buffer returned by file_read: only the inline buffer was tracked and freed. Clear the pointer once ownership has passed to the compiler. The free in cleanup stays for the paths that bail out before compilation starts. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The CLI compiles to gravity.g (DEFAULT_OUTPUT), but the usage text and both README.md and CLAUDE.md still documented the older gravity.json. Print DEFAULT_OUTPUT in the usage text so the two cannot drift again. Also gitignore gravity.g, which a plain gravity -c drops in the working directory. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Security and memory safety release covering the compiler crash and the bytecode loader crashes reported in marcobambini#442, marcobambini#443, marcobambini#444, marcobambini#446, marcobambini#447 and marcobambini#448, each with a regression test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
optimize_const_instruction folded a float REM with remainder() whatever GRAVITY_ENABLE_DOUBLE was set to, while operator_float_rem switches to remainderf() when gravity_float_t is a float. An IEEE remainder is exact, so the two agree in practice, but the folder claimed to match the runtime without mirroring its conditional. Make the claim literally true. No change to the default build, where GRAVITY_ENABLE_DOUBLE is 1. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Storing past the end of a list reallocates the backing array through marray_resize, which leaves both p and m untouched when the realloc fails. The guard tested list->array.p for NULL, but a failed realloc keeps the old, smaller, non NULL buffer in place, so it never fired. marray_nset then set the count to the requested index and the fill loop wrote past the end of the allocation. Check the capacity actually obtained instead, so the out of memory case is reported as the runtime error it was always meant to be. The fill loop is bounded by that capacity too: it agrees with the old index+MIN_LIST_RESIZE bound for every list the runtime builds today, since they all carry spare capacity, but the loop should not have to rely on that. This is reachable from a script, x[4444444444444444444] = 0 is enough, and it is what several inputs in test/fuzzy do. They were never run in CI before the sanitizer job was added. CI: cap a single allocation at 1GB in the sanitizer job so those inputs fail cleanly rather than pushing the runner into the OOM killer, which is what made the job die with exit code 143. Pin abort_on_error so a finding arrives as a signal on every platform instead of the bare exit code 1 the runtime uses on Linux, which the fuzzing step could not tell apart from an input the interpreter simply rejected, and scan the output for sanitizer reports too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CodeQL ran on github/codeql-action@v1, deprecated since January 2023 and no longer updated or supported, so it kept reporting green without being a current analysis. It is not a required status check and code scanning default setup is not configured, so the workflow was its only trigger. Before removing it, fix its one open finding: report_error was passing a size_t to a %d conversion in gravity_codegen.c, which reads 32 bits of a 64bit variadic argument. Use %zu. The compiler could not catch that because report_error only forwards its arguments to vsnprintf. Annotate all three of them with the printf format attribute on gcc and clang, so every call site is type checked from now on and this class fails the build rather than needing an external analyser. The tree is clean under it today. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
is_newline() looked at PEEK_CURRENT for the character following c, which only holds where the caller had already consumed c (the comment scanner and skip_line). In gravity_lexer_next, lexer_scan_number and lexer_scan_string c was still the character at the current offset, so the CR of a CR+LF pair never saw the LF next to it: the pair was counted as two line breaks and every row the compiler reported drifted by one per line read so far. On a source file saved on Windows an error on row 5 was reported on row 9. The lookahead is now passed in explicitly, so each call site says which two characters follow the one being examined, and newline_length() returns the size of the terminator without consuming anything. The two callers that still hold the offset skip the whole sequence themselves, and the string scanner keeps every byte of it inside the token so that a literal spanning CR+LF lines is not shortened by one byte per line. NEL and LS are left exactly as they were: PEEK_NEXT and PEEK_NEXT2 read plain char, so their comparisons are still false where char is signed. That is pre-existing and out of scope here. Reported in marcobambini#389, and this is the fix proposed in marcobambini#401 by Matthew Asplund (mwasplund) with the string and number scanners corrected. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
lib already builds the shared library out of $(OBJ), which is every source but the CLI entry point. staticlib archives the same objects, so embedders who link gravity statically no longer have to drive ar by hand. Requested in marcobambini#427 by Jock Murphy (jockm). The clean fix from that pull request is already in: clean removes the shared library under each of its platform specific names. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
gravity_utils.h picks DIRREF and windows.h on _WIN32, but gravity_utils.c, gravity_opt_file.c and the CLI guarded their Windows bodies with WIN32, which is not a compiler defined macro. The Visual Studio projects define it in the two 32 bit configurations of gravity.vcxproj alone, so every x64 build compiled the POSIX bodies against the Windows header: opendir and readdir do not exist under MSVC and DIRREF is a HANDLE there, so the two halves cannot even agree on a type. MinGW and tcc land in the same place. _WIN32 is defined by MSVC, MinGW and tcc on both 32 and 64 bit, and is what the header already tests. WIN32_FIND_DATA and friends are Windows API type names and are left alone. From marcobambini#411 by tDwtp, which is the pull request that reported it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.