authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-12 13:16:09+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-12-14 14:08:22+02:00
logbc97a5662da4dd0a82840de79dd5600cef0ef825
treec259592c1eca178bf6fc6b6380cd58896bb3035b
parent886fa455fad4997cf766ec2adcbac09d7e28f668

Sema: display cimport errors from clang


8 files changed, 115 insertions(+), 31 deletions(-)

src/Compilation.zig+24-3
......@@ -31,6 +31,7 @@ const clangMain = @import("main.zig").clangMain;
3131const Module = @import("Module.zig");
3232const Cache = @import("Cache.zig");
3333const translate_c = @import("translate_c.zig");
34const clang = @import("clang.zig");
3435const c_codegen = @import("codegen/c.zig");
3536const ThreadPool = @import("ThreadPool.zig");
3637const WaitGroup = @import("WaitGroup.zig");
......@@ -2749,6 +2750,9 @@ pub fn totalErrorCount(self: *Compilation) usize {
27492750 const decl = module.declPtr(key);
27502751 if (decl.getFileScope().okToReportErrors()) {
27512752 total += 1;
2753 if (module.cimport_errors.get(key)) |errors| {
2754 total += errors.len;
2755 }
27522756 }
27532757 }
27542758 if (module.emit_h) |emit_h| {
......@@ -2858,6 +2862,23 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
28582862 // We'll try again once parsing succeeds.
28592863 if (decl.getFileScope().okToReportErrors()) {
28602864 try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*);
2865 if (module.cimport_errors.get(entry.key_ptr.*)) |cimport_errors| for (cimport_errors) |c_error| {
2866 if (c_error.path) |some|
2867 try errors.append(.{
2868 .src = .{
2869 .src_path = try arena_allocator.dupe(u8, std.mem.span(some)),
2870 .span = .{ .start = c_error.offset, .end = c_error.offset + 1, .main = c_error.offset },
2871 .msg = try arena_allocator.dupe(u8, std.mem.span(c_error.msg)),
2872 .line = c_error.line,
2873 .column = c_error.column,
2874 .source_line = if (c_error.source_line) |line| try arena_allocator.dupe(u8, std.mem.span(line)) else null,
2875 },
2876 })
2877 else
2878 try errors.append(.{
2879 .plain = .{ .msg = try arena_allocator.dupe(u8, std.mem.span(c_error.msg)) },
2880 });
2881 };
28612882 }
28622883 }
28632884 }
......@@ -3524,7 +3545,7 @@ test "cImport" {
35243545
35253546const CImportResult = struct {
35263547 out_zig_path: []u8,
3527 errors: []translate_c.ClangErrMsg,
3548 errors: []clang.ErrorMsg,
35283549};
35293550
35303551/// Caller owns returned memory.
......@@ -3599,7 +3620,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
35993620
36003621 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
36013622 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);
3602 var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
3623 var clang_errors: []clang.ErrorMsg = &[0]clang.ErrorMsg{};
36033624 var tree = translate_c.translate(
36043625 comp.gpa,
36053626 new_argv.ptr,
......@@ -3665,7 +3686,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
36653686 }
36663687 return CImportResult{
36673688 .out_zig_path = out_zig_path,
3668 .errors = &[0]translate_c.ClangErrMsg{},
3689 .errors = &[0]clang.ErrorMsg{},
36693690 };
36703691}
36713692
src/Module.zig+30
......@@ -31,6 +31,7 @@ const target_util = @import("target.zig");
3131const build_options = @import("build_options");
3232const Liveness = @import("Liveness.zig");
3333const isUpDir = @import("introspect.zig").isUpDir;
34const clang = @import("clang.zig");
3435
3536/// General-purpose allocator. Used for both temporary and long-term storage.
3637gpa: Allocator,
......@@ -111,6 +112,9 @@ failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},
111112/// Using a map here for consistency with the other fields here.
112113/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
113114failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},
115/// If a decl failed due to a cimport error, the corresponding Clang errors
116/// are stored here.
117cimport_errors: std.AutoArrayHashMapUnmanaged(Decl.Index, []CImportError) = .{},
114118
115119/// Candidates for deletion. After a semantic analysis update completes, this list
116120/// contains Decls that need to be deleted if they end up having no references to them.
......@@ -172,6 +176,21 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
172176 src: LazySrcLoc,
173177}) = .{},
174178
179pub const CImportError = struct {
180 offset: u32,
181 line: u32,
182 column: u32,
183 path: ?[*:0]u8,
184 source_line: ?[*:0]u8,
185 msg: [*:0]u8,
186
187 pub fn deinit(err: CImportError, gpa: Allocator) void {
188 if (err.path) |some| gpa.free(std.mem.span(some));
189 if (err.source_line) |some| gpa.free(std.mem.span(some));
190 gpa.free(std.mem.span(err.msg));
191 }
192};
193
175194pub const StringLiteralContext = struct {
176195 bytes: *ArrayListUnmanaged(u8),
177196
......@@ -3449,6 +3468,11 @@ pub fn deinit(mod: *Module) void {
34493468 }
34503469 mod.failed_exports.deinit(gpa);
34513470
3471 for (mod.cimport_errors.values()) |errs| {
3472 for (errs) |err| err.deinit(gpa);
3473 }
3474 mod.cimport_errors.deinit(gpa);
3475
34523476 mod.compile_log_decls.deinit(gpa);
34533477
34543478 for (mod.decl_exports.values()) |*export_list| {
......@@ -5381,6 +5405,9 @@ pub fn clearDecl(
53815405 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
53825406 kv.value.destroy(gpa);
53835407 }
5408 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5409 for (kv.value) |err| err.deinit(gpa);
5410 }
53845411 if (mod.emit_h) |emit_h| {
53855412 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
53865413 kv.value.destroy(gpa);
......@@ -5768,6 +5795,9 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
57685795 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
57695796 kv.value.destroy(mod.gpa);
57705797 }
5798 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5799 for (kv.value) |err| err.deinit(mod.gpa);
5800 }
57715801 if (decl.has_tv and decl.owns_tv) {
57725802 if (decl.val.castTag(.function)) |payload| {
57735803 const func = payload.data;
src/Sema.zig+45-7
......@@ -5130,20 +5130,58 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
51305130
51315131 if (c_import_res.errors.len != 0) {
51325132 const msg = msg: {
5133 defer @import("clang.zig").ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
5134
51335135 const msg = try sema.errMsg(&child_block, src, "C import failed", .{});
51345136 errdefer msg.destroy(sema.gpa);
51355137
51365138 if (!mod.comp.bin_file.options.link_libc)
51375139 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});
51385140
5139 for (c_import_res.errors) |_| {
5140 // TODO integrate with LazySrcLoc
5141 // try mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]});
5142 // if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",
5143 // clang_err.line + 1,
5144 // clang_err.column + 1,
5141 const gop = try sema.mod.cimport_errors.getOrPut(sema.gpa, sema.owner_decl_index);
5142 if (!gop.found_existing) {
5143 var errs = try std.ArrayListUnmanaged(Module.CImportError).initCapacity(sema.gpa, c_import_res.errors.len);
5144 errdefer {
5145 for (errs.items) |err| err.deinit(sema.gpa);
5146 errs.deinit(sema.gpa);
5147 }
5148
5149 for (c_import_res.errors) |c_error| {
5150 const path = if (c_error.filename_ptr) |some|
5151 try sema.gpa.dupeZ(u8, some[0..c_error.filename_len])
5152 else
5153 null;
5154 errdefer if (path) |some| sema.gpa.free(some);
5155
5156 const c_msg = try sema.gpa.dupeZ(u8, c_error.msg_ptr[0..c_error.msg_len]);
5157 errdefer sema.gpa.free(c_msg);
5158
5159 const line = line: {
5160 const source = c_error.source orelse break :line null;
5161 var start = c_error.offset;
5162 while (start > 0) : (start -= 1) {
5163 if (source[start - 1] == '\n') break;
5164 }
5165 var end = c_error.offset;
5166 while (true) : (end += 1) {
5167 if (source[end] == 0) break;
5168 if (source[end] == '\n') break;
5169 }
5170 break :line try sema.gpa.dupeZ(u8, source[start..end]);
5171 };
5172 errdefer if (line) |some| sema.gpa.free(some);
5173
5174 errs.appendAssumeCapacity(.{
5175 .path = path orelse null,
5176 .source_line = line orelse null,
5177 .line = c_error.line,
5178 .column = c_error.column,
5179 .offset = c_error.offset,
5180 .msg = c_msg,
5181 });
5182 }
5183 gop.value_ptr.* = errs.items;
51455184 }
5146 @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
51475185 break :msg msg;
51485186 };
51495187 return sema.failWithOwnedErrorMsg(msg);
src/clang.zig+4-4
......@@ -1897,13 +1897,13 @@ pub const OffsetOfNode_Kind = enum(c_int) {
18971897 Base,
18981898};
18991899
1900pub const Stage2ErrorMsg = extern struct {
1900pub const ErrorMsg = extern struct {
19011901 filename_ptr: ?[*]const u8,
19021902 filename_len: usize,
19031903 msg_ptr: [*]const u8,
19041904 msg_len: usize,
19051905 // valid until the ASTUnit is freed
1906 source: ?[*]const u8,
1906 source: ?[*:0]const u8,
19071907 // 0 based
19081908 line: c_uint,
19091909 // 0 based
......@@ -1912,14 +1912,14 @@ pub const Stage2ErrorMsg = extern struct {
19121912 offset: c_uint,
19131913
19141914 pub const delete = ZigClangErrorMsg_delete;
1915 extern fn ZigClangErrorMsg_delete(ptr: [*]Stage2ErrorMsg, len: usize) void;
1915 extern fn ZigClangErrorMsg_delete(ptr: [*]ErrorMsg, len: usize) void;
19161916};
19171917
19181918pub const LoadFromCommandLine = ZigClangLoadFromCommandLine;
19191919extern fn ZigClangLoadFromCommandLine(
19201920 args_begin: [*]?[*]const u8,
19211921 args_end: [*]?[*]const u8,
1922 errors_ptr: *[*]Stage2ErrorMsg,
1922 errors_ptr: *[*]ErrorMsg,
19231923 errors_len: *usize,
19241924 resources_path: [*:0]const u8,
19251925) ?*ASTUnit;
src/main.zig+2-1
......@@ -19,6 +19,7 @@ const introspect = @import("introspect.zig");
1919const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2020const wasi_libc = @import("wasi_libc.zig");
2121const translate_c = @import("translate_c.zig");
22const clang = @import("clang.zig");
2223const Cache = @import("Cache.zig");
2324const target_util = @import("target.zig");
2425const ThreadPool = @import("ThreadPool.zig");
......@@ -3552,7 +3553,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void
35523553
35533554 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
35543555 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);
3555 var clang_errors: []translate_c.ClangErrMsg = &[0]translate_c.ClangErrMsg{};
3556 var clang_errors: []clang.ErrorMsg = &[0]clang.ErrorMsg{};
35563557 var tree = translate_c.translate(
35573558 comp.gpa,
35583559 new_argv.ptr,
src/translate_c.zig+1-7
......@@ -13,8 +13,6 @@ const Tag = Node.Tag;
1313
1414const CallingConvention = std.builtin.CallingConvention;
1515
16pub const ClangErrMsg = clang.Stage2ErrorMsg;
17
1816pub const Error = std.mem.Allocator.Error;
1917const MacroProcessingError = Error || error{UnexpectedMacroToken};
2018const TypeError = Error || error{UnsupportedType};
......@@ -350,7 +348,7 @@ pub fn translate(
350348 gpa: mem.Allocator,
351349 args_begin: [*]?[*]const u8,
352350 args_end: [*]?[*]const u8,
353 errors: *[]ClangErrMsg,
351 errors: *[]clang.ErrorMsg,
354352 resources_path: [*:0]const u8,
355353) !std.zig.Ast {
356354 // TODO stage2 bug
......@@ -5115,10 +5113,6 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti
51155113 try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
51165114}
51175115
5118pub fn freeErrors(errors: []ClangErrMsg) void {
5119 errors.ptr.delete(errors.len);
5120}
5121
51225116const PatternList = struct {
51235117 patterns: []Pattern,
51245118
test/cases/compile_errors/cImport_with_bogus_include.zig created+9
......@@ -0,0 +1,9 @@
1const c = @cImport(@cInclude("bogus.h"));
2export fn entry() usize { return @sizeOf(@TypeOf(c.bogo)); }
3
4// error
5// backend=llvm
6// target=native
7//
8// :1:11: error: C import failed
9// :1:10: error: 'bogus.h' file not found
test/cases/compile_errors/stage1/obj/cImport_with_bogus_include.zig deleted-9
......@@ -1,9 +0,0 @@
1const c = @cImport(@cInclude("bogus.h"));
2export fn entry() usize { return @sizeOf(@TypeOf(c.bogo)); }
3
4// error
5// backend=stage1
6// target=native
7//
8// tmp.zig:1:11: error: C import failed
9// .h:1:10: note: 'bogus.h' file not found