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;...@@ -31,6 +31,7 @@ const clangMain = @import("main.zig").clangMain;
31const Module = @import("Module.zig");31const Module = @import("Module.zig");
32const Cache = @import("Cache.zig");32const Cache = @import("Cache.zig");
33const translate_c = @import("translate_c.zig");33const translate_c = @import("translate_c.zig");
34const clang = @import("clang.zig");
34const c_codegen = @import("codegen/c.zig");35const c_codegen = @import("codegen/c.zig");
35const ThreadPool = @import("ThreadPool.zig");36const ThreadPool = @import("ThreadPool.zig");
36const WaitGroup = @import("WaitGroup.zig");37const WaitGroup = @import("WaitGroup.zig");
...@@ -2749,6 +2750,9 @@ pub fn totalErrorCount(self: *Compilation) usize {...@@ -2749,6 +2750,9 @@ pub fn totalErrorCount(self: *Compilation) usize {
2749 const decl = module.declPtr(key);2750 const decl = module.declPtr(key);
2750 if (decl.getFileScope().okToReportErrors()) {2751 if (decl.getFileScope().okToReportErrors()) {
2751 total += 1;2752 total += 1;
2753 if (module.cimport_errors.get(key)) |errors| {
2754 total += errors.len;
2755 }
2752 }2756 }
2753 }2757 }
2754 if (module.emit_h) |emit_h| {2758 if (module.emit_h) |emit_h| {
...@@ -2858,6 +2862,23 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {...@@ -2858,6 +2862,23 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
2858 // We'll try again once parsing succeeds.2862 // We'll try again once parsing succeeds.
2859 if (decl.getFileScope().okToReportErrors()) {2863 if (decl.getFileScope().okToReportErrors()) {
2860 try AllErrors.add(module, &arena, &errors, entry.value_ptr.*.*);2864 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 };
2861 }2882 }
2862 }2883 }
2863 }2884 }
...@@ -3524,7 +3545,7 @@ test "cImport" {...@@ -3524,7 +3545,7 @@ test "cImport" {
35243545
3525const CImportResult = struct {3546const CImportResult = struct {
3526 out_zig_path: []u8,3547 out_zig_path: []u8,
3527 errors: []translate_c.ClangErrMsg,3548 errors: []clang.ErrorMsg,
3528};3549};
35293550
3530/// Caller owns returned memory.3551/// Caller owns returned memory.
...@@ -3599,7 +3620,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -3599,7 +3620,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
35993620
3600 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});3621 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
3601 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);3622 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{};
3603 var tree = translate_c.translate(3624 var tree = translate_c.translate(
3604 comp.gpa,3625 comp.gpa,
3605 new_argv.ptr,3626 new_argv.ptr,
...@@ -3665,7 +3686,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {...@@ -3665,7 +3686,7 @@ pub fn cImport(comp: *Compilation, c_src: []const u8) !CImportResult {
3665 }3686 }
3666 return CImportResult{3687 return CImportResult{
3667 .out_zig_path = out_zig_path,3688 .out_zig_path = out_zig_path,
3668 .errors = &[0]translate_c.ClangErrMsg{},3689 .errors = &[0]clang.ErrorMsg{},
3669 };3690 };
3670}3691}
36713692
src/Module.zig+30
...@@ -31,6 +31,7 @@ const target_util = @import("target.zig");...@@ -31,6 +31,7 @@ const target_util = @import("target.zig");
31const build_options = @import("build_options");31const build_options = @import("build_options");
32const Liveness = @import("Liveness.zig");32const Liveness = @import("Liveness.zig");
33const isUpDir = @import("introspect.zig").isUpDir;33const isUpDir = @import("introspect.zig").isUpDir;
34const clang = @import("clang.zig");
3435
35/// General-purpose allocator. Used for both temporary and long-term storage.36/// General-purpose allocator. Used for both temporary and long-term storage.
36gpa: Allocator,37gpa: Allocator,
...@@ -111,6 +112,9 @@ failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},...@@ -111,6 +112,9 @@ failed_embed_files: std.AutoArrayHashMapUnmanaged(*EmbedFile, *ErrorMsg) = .{},
111/// Using a map here for consistency with the other fields here.112/// Using a map here for consistency with the other fields here.
112/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.113/// The ErrorMsg memory is owned by the `Export`, using Module's general purpose allocator.
113failed_exports: std.AutoArrayHashMapUnmanaged(*Export, *ErrorMsg) = .{},114failed_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
115/// Candidates for deletion. After a semantic analysis update completes, this list119/// Candidates for deletion. After a semantic analysis update completes, this list
116/// contains Decls that need to be deleted if they end up having no references to them.120/// 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 {...@@ -172,6 +176,21 @@ reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
172 src: LazySrcLoc,176 src: LazySrcLoc,
173}) = .{},177}) = .{},
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
175pub const StringLiteralContext = struct {194pub const StringLiteralContext = struct {
176 bytes: *ArrayListUnmanaged(u8),195 bytes: *ArrayListUnmanaged(u8),
177196
...@@ -3449,6 +3468,11 @@ pub fn deinit(mod: *Module) void {...@@ -3449,6 +3468,11 @@ pub fn deinit(mod: *Module) void {
3449 }3468 }
3450 mod.failed_exports.deinit(gpa);3469 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
3452 mod.compile_log_decls.deinit(gpa);3476 mod.compile_log_decls.deinit(gpa);
34533477
3454 for (mod.decl_exports.values()) |*export_list| {3478 for (mod.decl_exports.values()) |*export_list| {
...@@ -5381,6 +5405,9 @@ pub fn clearDecl(...@@ -5381,6 +5405,9 @@ pub fn clearDecl(
5381 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {5405 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5382 kv.value.destroy(gpa);5406 kv.value.destroy(gpa);
5383 }5407 }
5408 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5409 for (kv.value) |err| err.deinit(gpa);
5410 }
5384 if (mod.emit_h) |emit_h| {5411 if (mod.emit_h) |emit_h| {
5385 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {5412 if (emit_h.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5386 kv.value.destroy(gpa);5413 kv.value.destroy(gpa);
...@@ -5768,6 +5795,9 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {...@@ -5768,6 +5795,9 @@ fn markOutdatedDecl(mod: *Module, decl_index: Decl.Index) !void {
5768 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {5795 if (mod.failed_decls.fetchSwapRemove(decl_index)) |kv| {
5769 kv.value.destroy(mod.gpa);5796 kv.value.destroy(mod.gpa);
5770 }5797 }
5798 if (mod.cimport_errors.fetchSwapRemove(decl_index)) |kv| {
5799 for (kv.value) |err| err.deinit(mod.gpa);
5800 }
5771 if (decl.has_tv and decl.owns_tv) {5801 if (decl.has_tv and decl.owns_tv) {
5772 if (decl.val.castTag(.function)) |payload| {5802 if (decl.val.castTag(.function)) |payload| {
5773 const func = payload.data;5803 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...@@ -5130,20 +5130,58 @@ fn zirCImport(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileEr
51305130
5131 if (c_import_res.errors.len != 0) {5131 if (c_import_res.errors.len != 0) {
5132 const msg = msg: {5132 const msg = msg: {
5133 defer @import("clang.zig").ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
5134
5133 const msg = try sema.errMsg(&child_block, src, "C import failed", .{});5135 const msg = try sema.errMsg(&child_block, src, "C import failed", .{});
5134 errdefer msg.destroy(sema.gpa);5136 errdefer msg.destroy(sema.gpa);
51355137
5136 if (!mod.comp.bin_file.options.link_libc)5138 if (!mod.comp.bin_file.options.link_libc)
5137 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});5139 try sema.errNote(&child_block, src, msg, "libc headers not available; compilation does not link against libc", .{});
51385140
5139 for (c_import_res.errors) |_| {5141 const gop = try sema.mod.cimport_errors.getOrPut(sema.gpa, sema.owner_decl_index);
5140 // TODO integrate with LazySrcLoc5142 if (!gop.found_existing) {
5141 // try mod.errNoteNonLazy(.{}, msg, "{s}", .{clang_err.msg_ptr[0..clang_err.msg_len]});5143 var errs = try std.ArrayListUnmanaged(Module.CImportError).initCapacity(sema.gpa, c_import_res.errors.len);
5142 // if (clang_err.filename_ptr) |p| p[0..clang_err.filename_len] else "(no file)",5144 errdefer {
5143 // clang_err.line + 1,5145 for (errs.items) |err| err.deinit(sema.gpa);
5144 // clang_err.column + 1,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;
5145 }5184 }
5146 @import("clang.zig").Stage2ErrorMsg.delete(c_import_res.errors.ptr, c_import_res.errors.len);
5147 break :msg msg;5185 break :msg msg;
5148 };5186 };
5149 return sema.failWithOwnedErrorMsg(msg);5187 return sema.failWithOwnedErrorMsg(msg);
src/clang.zig+4-4
...@@ -1897,13 +1897,13 @@ pub const OffsetOfNode_Kind = enum(c_int) {...@@ -1897,13 +1897,13 @@ pub const OffsetOfNode_Kind = enum(c_int) {
1897 Base,1897 Base,
1898};1898};
18991899
1900pub const Stage2ErrorMsg = extern struct {1900pub const ErrorMsg = extern struct {
1901 filename_ptr: ?[*]const u8,1901 filename_ptr: ?[*]const u8,
1902 filename_len: usize,1902 filename_len: usize,
1903 msg_ptr: [*]const u8,1903 msg_ptr: [*]const u8,
1904 msg_len: usize,1904 msg_len: usize,
1905 // valid until the ASTUnit is freed1905 // valid until the ASTUnit is freed
1906 source: ?[*]const u8,1906 source: ?[*:0]const u8,
1907 // 0 based1907 // 0 based
1908 line: c_uint,1908 line: c_uint,
1909 // 0 based1909 // 0 based
...@@ -1912,14 +1912,14 @@ pub const Stage2ErrorMsg = extern struct {...@@ -1912,14 +1912,14 @@ pub const Stage2ErrorMsg = extern struct {
1912 offset: c_uint,1912 offset: c_uint,
19131913
1914 pub const delete = ZigClangErrorMsg_delete;1914 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;
1916};1916};
19171917
1918pub const LoadFromCommandLine = ZigClangLoadFromCommandLine;1918pub const LoadFromCommandLine = ZigClangLoadFromCommandLine;
1919extern fn ZigClangLoadFromCommandLine(1919extern fn ZigClangLoadFromCommandLine(
1920 args_begin: [*]?[*]const u8,1920 args_begin: [*]?[*]const u8,
1921 args_end: [*]?[*]const u8,1921 args_end: [*]?[*]const u8,
1922 errors_ptr: *[*]Stage2ErrorMsg,1922 errors_ptr: *[*]ErrorMsg,
1923 errors_len: *usize,1923 errors_len: *usize,
1924 resources_path: [*:0]const u8,1924 resources_path: [*:0]const u8,
1925) ?*ASTUnit;1925) ?*ASTUnit;
src/main.zig+2-1
...@@ -19,6 +19,7 @@ const introspect = @import("introspect.zig");...@@ -19,6 +19,7 @@ const introspect = @import("introspect.zig");
19const LibCInstallation = @import("libc_installation.zig").LibCInstallation;19const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
20const wasi_libc = @import("wasi_libc.zig");20const wasi_libc = @import("wasi_libc.zig");
21const translate_c = @import("translate_c.zig");21const translate_c = @import("translate_c.zig");
22const clang = @import("clang.zig");
22const Cache = @import("Cache.zig");23const Cache = @import("Cache.zig");
23const target_util = @import("target.zig");24const target_util = @import("target.zig");
24const ThreadPool = @import("ThreadPool.zig");25const ThreadPool = @import("ThreadPool.zig");
...@@ -3552,7 +3553,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void...@@ -3552,7 +3553,7 @@ fn cmdTranslateC(comp: *Compilation, arena: Allocator, enable_cache: bool) !void
35523553
3553 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});3554 const c_headers_dir_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{"include"});
3554 const c_headers_dir_path_z = try arena.dupeZ(u8, c_headers_dir_path);3555 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{};
3556 var tree = translate_c.translate(3557 var tree = translate_c.translate(
3557 comp.gpa,3558 comp.gpa,
3558 new_argv.ptr,3559 new_argv.ptr,
src/translate_c.zig+1-7
...@@ -13,8 +13,6 @@ const Tag = Node.Tag;...@@ -13,8 +13,6 @@ const Tag = Node.Tag;
1313
14const CallingConvention = std.builtin.CallingConvention;14const CallingConvention = std.builtin.CallingConvention;
1515
16pub const ClangErrMsg = clang.Stage2ErrorMsg;
17
18pub const Error = std.mem.Allocator.Error;16pub const Error = std.mem.Allocator.Error;
19const MacroProcessingError = Error || error{UnexpectedMacroToken};17const MacroProcessingError = Error || error{UnexpectedMacroToken};
20const TypeError = Error || error{UnsupportedType};18const TypeError = Error || error{UnsupportedType};
...@@ -350,7 +348,7 @@ pub fn translate(...@@ -350,7 +348,7 @@ pub fn translate(
350 gpa: mem.Allocator,348 gpa: mem.Allocator,
351 args_begin: [*]?[*]const u8,349 args_begin: [*]?[*]const u8,
352 args_end: [*]?[*]const u8,350 args_end: [*]?[*]const u8,
353 errors: *[]ClangErrMsg,351 errors: *[]clang.ErrorMsg,
354 resources_path: [*:0]const u8,352 resources_path: [*:0]const u8,
355) !std.zig.Ast {353) !std.zig.Ast {
356 // TODO stage2 bug354 // TODO stage2 bug
...@@ -5115,10 +5113,6 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti...@@ -5115,10 +5113,6 @@ pub fn failDecl(c: *Context, loc: clang.SourceLocation, name: []const u8, compti
5115 try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));5113 try c.global_scope.nodes.append(try Tag.warning.create(c.arena, location_comment));
5116}5114}
51175115
5118pub fn freeErrors(errors: []ClangErrMsg) void {
5119 errors.ptr.delete(errors.len);
5120}
5121
5122const PatternList = struct {5116const PatternList = struct {
5123 patterns: []Pattern,5117 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