commit 363f54df6447c8a84f73ae6cd0f74179d6f9f4b3 (tree)
parent 67774255ed3e8f0ff24152150fc3af9eb2e025f2
Author: Motiejus Jakštys <motiejus@jakstys.lt>
Date: Mon, 16 Feb 2026 21:52:29 +0000
astgen: port lib_name handling for extern fn declarations from upstream Zig
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat:
2 files changed, 31 insertions(+), 7 deletions(-)
diff --git a/stage0/astgen.c b/stage0/astgen.c
@@ -14741,6 +14741,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
bool is_extern = false;
bool is_noinline = false;
bool has_inline_keyword = false;
+ uint32_t lib_name_token = NULL_TOKEN;
for (uint32_t i = fn_token; i > 0;) {
i--;
uint32_t ttag = tree->tokens.tags[i];
@@ -14754,10 +14755,30 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
is_noinline = true;
else if (ttag == TOKEN_KEYWORD_INLINE)
has_inline_keyword = true;
+ else if (ttag == TOKEN_STRING_LITERAL)
+ lib_name_token = i;
else
break;
}
+ // lib_name validation (AstGen.zig:4115-4124).
+ uint32_t lib_name = UINT32_MAX;
+ if (lib_name_token != NULL_TOKEN) {
+ uint32_t li, ll;
+ strLitAsString(ag, lib_name_token, &li, &ll);
+ // "library name cannot contain null bytes" (AstGen.zig:4118-4119).
+ if (memchr(ag->string_bytes + li, 0, ll) != NULL) {
+ SET_ERROR(ag);
+ return;
+ }
+ // "library name cannot be empty" (AstGen.zig:4120-4121).
+ if (ll == 0) {
+ SET_ERROR(ag);
+ return;
+ }
+ lib_name = li;
+ }
+
// makeDeclaration on fn_proto node (AstGen.zig:4090).
uint32_t decl_inst = makeDeclaration(ag, proto_node);
wip_decl_insts[*decl_idx] = decl_inst;
@@ -15449,16 +15470,19 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
bool has_type_body = (type_body_len > 0);
bool has_special_body
= (align_body_len > 0 || ls_body_len > 0 || as_body_len > 0);
+ bool has_lib_name = (lib_name_token != NULL_TOKEN);
- // Linkage: extern > export > normal (AstGen.zig:4217).
+ // Linkage: extern > export > normal (AstGen.zig:4217, 13928-13946).
DeclFlagsId decl_id;
if (is_extern) {
if (is_pub) {
- decl_id = (has_special_body) ? DECL_ID_PUB_EXTERN_CONST
- : DECL_ID_PUB_EXTERN_CONST_SIMPLE;
+ decl_id = (has_lib_name || has_special_body)
+ ? DECL_ID_PUB_EXTERN_CONST
+ : DECL_ID_PUB_EXTERN_CONST_SIMPLE;
} else {
- decl_id = (has_special_body) ? DECL_ID_EXTERN_CONST
- : DECL_ID_EXTERN_CONST_SIMPLE;
+ decl_id = (has_lib_name || has_special_body)
+ ? DECL_ID_EXTERN_CONST
+ : DECL_ID_EXTERN_CONST_SIMPLE;
}
} else if (is_export) {
decl_id = is_pub ? DECL_ID_PUB_EXPORT_CONST : DECL_ID_EXPORT_CONST;
@@ -15485,7 +15509,7 @@ static void fnDecl(AstGenCtx* ag, GenZir* gz, Scope* scope,
.src_column = decl_column,
.id = decl_id,
.name = name_str,
- .lib_name = UINT32_MAX,
+ .lib_name = lib_name,
.type_body = type_body,
.type_body_len = type_body_len,
.align_body = align_body,
diff --git a/stage0/stages_test.zig b/stage0/stages_test.zig
@@ -23,7 +23,7 @@ fn stagesCheck(gpa: Allocator, source: [:0]const u8) !void {
}
const corpus_files = .{
- //"../lib/build-web/fuzz.zig",
+ "../lib/build-web/fuzz.zig",
//"../lib/build-web/main.zig",
//"../lib/build-web/time_report.zig",
//"../lib/c/common.zig",