kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit aaf3e90b91d0938e78ff4af28c7fdc52f12bc3c4
parent 4ee57ded3d787ea29d4fa7528ae452c9a2ddc814
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed, 10 Jun 2026 07:31:49 -0700

fix(deps): T1.12 — report resolved-dir system flag, not include spelling

kit_dep_iter_next reported from_system_path from the <...>-vs-"..."
spelling bit, so a <foo.h> resolved via a plain -I dir was wrongly flagged
system (and dropped by cc -MM/-MMD). Thread the resolved include dir's
system flag (pp->inc_dirs[i].system) from find_and_open_include through a
new SourceInclude.resolved_system field, kit_source_add_include, and into
the dep edge. bracketed now carries the spelling; from_system_path carries
the resolved-dir flag (GCC -MM semantics).

Verified: <h> via -I now appears in cc -MM; via -isystem it is skipped;
-M shows it either way. test-pp, test-parse (3880+128), test-cg-api (211)
green. Updated the stale cc -MM/-MMD doc comment.

Diffstat:
Mdoc/plan/TODO.md | 11-----------
Mdriver/cmd/cc.c | 8+++++---
Minclude/kit/source.h | 7++++++-
Mlang/cpp/pp/pp.c | 5++++-
Mlang/cpp/pp/pp_directive.c | 28+++++++++++++++++++++-------
Msrc/api/compile.c | 16+++++-----------
Msrc/api/source.c | 4++--
Msrc/core/core.h | 7++++---
Msrc/core/source.c | 4+++-
9 files changed, 50 insertions(+), 40 deletions(-)

diff --git a/doc/plan/TODO.md b/doc/plan/TODO.md @@ -73,17 +73,6 @@ Add new deferred fixes below as they are discovered. which programs compile vs panic, so it must be a reviewed change, NOT folded into a dedup. Unblocks A.2 (below). -- **`kit_dep_iter` system-path conflation (T1.12).** `kit_dep_iter_next` - (`src/api/compile.c:654-655`) reports both `from_system_path` and `bracketed` - from the single `<>`-vs-`""` spelling bit, so a `<...>` include resolved via a - plain `-I` dir falsely reports `from_system_path=1`. The accurate signal (the - resolved dir's system flag) is discarded at resolution. A correct fix needs a - cross-file change: widen `SourceInclude` (`src/core/core.h`) with a resolved-system - bit and thread it through `lang/cpp/pp/pp_directive.c` (`find_and_open_include` → - `do_include`), `pp.{c,h}`, `include/kit/source.h`, `src/api/source.c`, - `src/core/source.c`. Currently documented at the assignment site; value is - identical to before. - ## Design-needed (not a quick fix) - **c_target data relocations (T1.3 / D.5).** `c_emit_data_symbol` diff --git a/driver/cmd/cc.c b/driver/cmd/cc.c @@ -46,10 +46,12 @@ /* Header-dependency emission mode (subset of GCC's -M family). * M — print all deps; do not compile. - * MM — like M but skip <bracketed> includes. + * MM — like M but skip headers resolved via system (-isystem) dirs. * MD — compile normally AND write all deps to a file. - * MMD — like MD but skip <bracketed> includes. - * MD/MMD currently require -c (single-source compile_obj_emit path). */ + * MMD — like MD but skip headers resolved via system (-isystem) dirs. + * The MM/MMD filter keys on the resolved include directory (GCC semantics), + * not the <...>-vs-"..." spelling, so a <foo.h> found via a plain -I dir is + * still reported. MD/MMD currently require -c (single-source path). */ typedef enum CcDepMode { CC_DEP_NONE = 0, CC_DEP_M, diff --git a/include/kit/source.h b/include/kit/source.h @@ -17,10 +17,15 @@ KIT_API KitStatus kit_source_add_memory(KitCompiler*, KitSlice name, uint32_t* file_id_out); KIT_API KitStatus kit_source_add_builtin(KitCompiler*, KitSlice name, uint32_t* file_id_out); +/* `system` is the spelling form (<...> vs "..."); `resolved_system` records + * whether the header was actually resolved through a system (-isystem) include + * directory. The two differ when a <...> include is satisfied by a plain -I + * dir; dependency reporting wants the resolved flag, not the spelling. */ KIT_API KitStatus kit_source_add_include(KitCompiler*, uint32_t includer_file_id, uint32_t included_file_id, - KitSrcLoc loc, int system); + KitSrcLoc loc, int system, + int resolved_system); typedef struct KitSourceFile { uint32_t id; diff --git a/lang/cpp/pp/pp.c b/lang/cpp/pp/pp.c @@ -871,5 +871,8 @@ uint32_t pp_pack_alignment(const Pp* pp) { return pp ? pp->pack_align : 0; } void pp_add_include_edge(Pp* pp, u32 includer, u32 included, SrcLoc include_loc, int system) { - kit_source_add_include(pp->c, includer, included, include_loc, system); + /* This generic edge-recording entry point has no resolved-dir context, so it + * can only fall back to the spelling form for the resolved-system flag. */ + kit_source_add_include(pp->c, includer, included, include_loc, system, + system); } diff --git a/lang/cpp/pp/pp_directive.c b/lang/cpp/pp/pp_directive.c @@ -662,11 +662,16 @@ static int includer_dir(Pp* pp, SrcLoc loc, char* dir_out, size_t cap) { * Both forms then walk the configured -I / -isystem dirs in order. */ static int find_and_open_include(Pp* pp, const char* path, int system, SrcLoc loc, const u8** data, size_t* size, - char* resolved, size_t resolved_cap) { + char* resolved, size_t resolved_cap, + int* resolved_system_out) { char buf[4096]; u32 i; size_t plen = kit_slice_cstr(path).len; + /* Absolute paths and the includer-relative ("...") step are not system + * search dirs; only a configured -isystem dir flips this to 1 below. */ + *resolved_system_out = 0; + if (plen > 0 && path[0] == '/') { if (try_open_include(pp, path, data, size)) { if (plen + 1 > resolved_cap) return 0; @@ -704,6 +709,7 @@ static int find_and_open_include(Pp* pp, const char* path, int system, if (try_open_include(pp, buf, data, size)) { if (dlen + 1 + plen + 1 > resolved_cap) return 0; memcpy(resolved, buf, dlen + 1 + plen + 1); + *resolved_system_out = pp->inc_dirs[i].system ? 1 : 0; return 1; } } @@ -801,6 +807,7 @@ static void do_include(Pp* pp, const Tok* line, u32 n, SrcLoc loc) { char path[4096]; char resolved[4096]; int system_form = 0; + int resolved_system = 0; const u8* data; size_t size; Lexer* lex; @@ -812,7 +819,7 @@ static void do_include(Pp* pp, const Tok* line, u32 n, SrcLoc loc) { parse_include_path(pp, line, n, loc, path, sizeof(path), &system_form); if (!find_and_open_include(pp, path, system_form, loc, &data, &size, resolved, - sizeof(resolved))) { + sizeof(resolved), &resolved_system)) { compiler_panic(pp->c, loc, "#include: file not found: %.*s", KIT_SLICE_ARG(kit_slice_cstr(path))); } @@ -834,7 +841,8 @@ static void do_include(Pp* pp, const Tok* line, u32 n, SrcLoc loc) { s.lex = lex; src_push(pp, s); - kit_source_add_include(pp->c, includer_id, included_id, loc, system_form); + kit_source_add_include(pp->c, includer_id, included_id, loc, system_form, + resolved_system); } /* ============================================================ @@ -1242,10 +1250,16 @@ static void do_embed(Pp* pp, const Tok* line, u32 n, SrcLoc loc) { compiler_panic(pp->c, loc, "#embed: unexpected token in parameter list"); } - if (!find_and_open_include(pp, path, system_form, loc, &data, &size, resolved, - sizeof(resolved))) { - compiler_panic(pp->c, loc, "#embed: file not found: %.*s", - KIT_SLICE_ARG(kit_slice_cstr(path))); + { + /* #embed does not record a dependency edge, so the resolved-dir system + * flag is not consumed here. */ + int embed_resolved_system = 0; + if (!find_and_open_include(pp, path, system_form, loc, &data, &size, + resolved, sizeof(resolved), + &embed_resolved_system)) { + compiler_panic(pp->c, loc, "#embed: file not found: %.*s", + KIT_SLICE_ARG(kit_slice_cstr(path))); + } } /* Apply limit(). */ diff --git a/src/api/compile.c b/src/api/compile.c @@ -651,18 +651,12 @@ KitIterResult kit_dep_iter_next(KitDepIter* it, KitDepEdge* out) { out->included_name = included ? pool_slice(it->c->global, included->name) : KIT_SLICE_NULL; out->include_loc = edge->include_loc; - /* SourceInclude.system records only the spelling form (<...> vs "..."), not - * which configured directory ultimately resolved the header: the resolved-dir - * system flag (pp->inc_dirs[i].system in lang/cpp/pp/pp_directive.c) is never - * threaded onto the dep edge — find_and_open_include / source_add_include - * drop it. So a true from_system_path (e.g. "<...>" or "..." satisfied by an - * -isystem dir, vs. a plain -I dir) is not derivable here without widening - * the SourceInclude record + its producers. Until that plumbing exists, both - * fields carry the same spelling bit: `bracketed` is its accurate meaning, - * and `from_system_path` is reported as the spelling bit too (an - * approximation that over-reports <...> via plain -I as system). */ + /* `bracketed` is the spelling form (<...> vs "..."); `from_system_path` is the + * resolved-dir system flag (whether an -isystem dir satisfied the header), + * threaded from find_and_open_include through SourceInclude.resolved_system. + * They differ when a <...> include is resolved via a plain -I dir. */ out->bracketed = (uint8_t)(edge->system ? 1 : 0); - out->from_system_path = out->bracketed; + out->from_system_path = (uint8_t)(edge->resolved_system ? 1 : 0); out->pad[0] = 0; out->pad[1] = 0; return KIT_ITER_ITEM; diff --git a/src/api/source.c b/src/api/source.c @@ -26,10 +26,10 @@ KitStatus kit_source_add_builtin(KitCompiler* c, KitSlice name, KitStatus kit_source_add_include(KitCompiler* c, uint32_t includer_file_id, uint32_t included_file_id, KitSrcLoc loc, - int system) { + int system, int resolved_system) { if (!c) return KIT_INVALID; return source_add_include(c->sources, includer_file_id, included_file_id, loc, - system); + system, resolved_system); } KitStatus kit_source_file(KitCompiler* c, uint32_t file_id, diff --git a/src/core/core.h b/src/core/core.h @@ -82,8 +82,9 @@ typedef struct SourceInclude { u32 includer_file_id; u32 included_file_id; SrcLoc include_loc; - u8 system; - u8 pad[3]; + u8 system; /* spelling form: <...> (1) vs "..." (0) */ + u8 resolved_system; /* resolved via a system (-isystem) include dir */ + u8 pad[2]; } SourceInclude; typedef struct SourceExpansion { @@ -103,7 +104,7 @@ KitStatus source_add_memory(SourceManager*, KitSlice name, u32* id_out); KitStatus source_add_builtin(SourceManager*, KitSlice name, u32* id_out); KitStatus source_add_include(SourceManager*, u32 includer_file_id, u32 included_file_id, SrcLoc include_loc, - int system); + int system, int resolved_system); KitStatus source_add_macro_expansion(SourceManager*, Sym macro_name, SrcLoc spelling_loc, SrcLoc expansion_loc, u32* id_out); diff --git a/src/core/source.c b/src/core/source.c @@ -125,12 +125,14 @@ KitStatus source_add_builtin(SourceManager* sm, KitSlice name, u32* id_out) { KitStatus source_add_include(SourceManager* sm, u32 includer_file_id, u32 included_file_id, SrcLoc include_loc, - int system) { + int system, int resolved_system) { if (includes_grow(sm)) return KIT_NOMEM; sm->includes[sm->nincludes].info.includer_file_id = includer_file_id; sm->includes[sm->nincludes].info.included_file_id = included_file_id; sm->includes[sm->nincludes].info.include_loc = include_loc; sm->includes[sm->nincludes].info.system = (u8)(system ? 1 : 0); + sm->includes[sm->nincludes].info.resolved_system = + (u8)(resolved_system ? 1 : 0); sm->nincludes++; return KIT_OK; }