authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-21 19:37:39-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-25 00:06:57-04:00
log712274997e80a93bdfe204f2238c4cfaac72a5b8
tree1931c87f8222bb961e6a530e277f7a30ef56c2c8
parent976080462cf62f6f112d38176b99e5bb8a57bf37
signature Commit is signed but in an unrecognized format.

translate-c: unify API for self-hosted and C++ translate-c

See #1964

12 files changed, 281 insertions(+), 143 deletions(-)

src-self-hosted/clang.zig+17
......@@ -862,6 +862,7 @@ pub extern fn ZigClangAPSInt_free(self: ?*const struct_ZigClangAPSInt) void;
862862pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c]const u64;
863863pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
864864pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
865pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;
865866pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
866867pub const ZigClangQualType = struct_ZigClangQualType;
867868pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
......@@ -942,3 +943,19 @@ pub const ZigClangTypeClass = enum_ZigClangTypeClass;
942943pub const ZigClangStmtClass = enum_ZigClangStmtClass;
943944pub const ZigClangCK = enum_ZigClangCK;
944945pub const ZigClangAPValueKind = enum_ZigClangAPValueKind;
946
947pub const Stage2ErrorMsg = extern struct {
948 filename_ptr: ?[*]const u8,
949 filename_len: usize,
950 msg_ptr: [*]const u8,
951 msg_len: usize,
952 // valid until the ASTUnit is freed
953 source: ?[*]const u8,
954 // 0 based
955 line: c_uint,
956 // 0 based
957 column: c_uint,
958 // byte offset into source
959 offset: c_uint,
960};
961pub extern fn ZigClangErrorMsg_delete(ptr: [*c]Stage2ErrorMsg, len: usize) void;
src-self-hosted/main.zig+17-1
......@@ -858,7 +858,23 @@ fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
858858 try stdout.write(usage);
859859}
860860
861const info_zen = @import("stage1.zig").info_zen;
861pub const info_zen =
862 \\
863 \\ * Communicate intent precisely.
864 \\ * Edge cases matter.
865 \\ * Favor reading code over writing code.
866 \\ * Only one obvious way to do things.
867 \\ * Runtime crashes are better than bugs.
868 \\ * Compile errors are better than runtime crashes.
869 \\ * Incremental improvements.
870 \\ * Avoid local maximums.
871 \\ * Reduce the amount one must remember.
872 \\ * Minimize energy spent on coding style.
873 \\ * Together we serve end users.
874 \\
875 \\
876;
877
862878fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
863879 try stdout.write(info_zen);
864880}
src-self-hosted/stage1.zig+16-19
......@@ -3,37 +3,25 @@
33
44const std = @import("std");
55
6pub const info_zen =
7 \\
8 \\ * Communicate intent precisely.
9 \\ * Edge cases matter.
10 \\ * Favor reading code over writing code.
11 \\ * Only one obvious way to do things.
12 \\ * Runtime crashes are better than bugs.
13 \\ * Compile errors are better than runtime crashes.
14 \\ * Incremental improvements.
15 \\ * Avoid local maximums.
16 \\ * Reduce the amount one must remember.
17 \\ * Minimize energy spent on coding style.
18 \\ * Together we serve end users.
19 \\
20 \\
21;
22
6// ABI warning
237export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
8 const info_zen = @import("main.zig").info_zen;
249 ptr.* = &info_zen;
2510 len.* = info_zen.len;
2611}
2712
13// ABI warning
2814export fn stage2_panic(ptr: [*]const u8, len: usize) void {
2915 @panic(ptr[0..len]);
3016}
3117
18// ABI warning
3219const TranslateMode = extern enum {
3320 import,
3421 translate,
3522};
3623
24// ABI warning
3725const Error = extern enum {
3826 None,
3927 OutOfMemory,
......@@ -84,24 +72,33 @@ const Error = extern enum {
8472
8573const FILE = std.c.FILE;
8674const ast = std.zig.ast;
75const translate_c = @import("translate_c.zig");
8776
8877/// Args should have a null terminating last arg.
8978export fn stage2_translate_c(
9079 out_ast: **ast.Tree,
80 out_errors_ptr: *[*]translate_c.ClangErrMsg,
81 out_errors_len: *usize,
9182 args_begin: [*]?[*]const u8,
9283 args_end: [*]?[*]const u8,
9384 mode: TranslateMode,
85 resources_path: [*]const u8,
9486) Error {
95 const translate_c = @import("translate_c.zig");
87 var errors: []translate_c.ClangErrMsg = undefined;
9688 out_ast.* = translate_c.translate(args_begin, args_end, switch (mode) {
9789 .import => translate_c.Mode.import,
9890 .translate => translate_c.Mode.translate,
99 }) catch |err| switch (err) {
91 }, &errors) catch |err| switch (err) {
10092 error.Unimplemented => return Error.Unimplemented,
10193 };
94
10295 return Error.None;
10396}
10497
98export fn stage2_free_clang_errors(errors_ptr: [*]translate_c.ClangErrMsg, errors_len: usize) void {
99 translate_c.freeErrors(errors_ptr[0..errors_len]);
100}
101
105102export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
106103 const c_out_stream = &std.io.COutStream.init(output_file).stream;
107104 _ = std.zig.render(std.heap.c_allocator, c_out_stream, tree) catch |e| switch (e) {
src-self-hosted/translate_c.zig+12-1
......@@ -10,6 +10,17 @@ pub const Mode = enum {
1010 translate,
1111};
1212
13pub fn translate(args_begin: [*]?[*]const u8, args_end: [*]?[*]const u8, mode: Mode) !*ast.Tree {
13pub const ClangErrMsg = Stage2ErrorMsg;
14
15pub fn translate(
16 args_begin: [*]?[*]const u8,
17 args_end: [*]?[*]const u8,
18 mode: Mode,
19 errors: *[]ClangErrMsg,
20) !*ast.Tree {
1421 return error.Unimplemented;
1522}
23
24pub fn freeErrors(errors: []ClangErrMsg) void {
25 ZigClangErrorMsg_delete(errors.ptr, errors.len);
26}
src/codegen.cpp+30-19
......@@ -8298,31 +8298,42 @@ void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_us
82988298
82998299 clang_argv.append(nullptr); // to make the [start...end] argument work
83008300
8301 const char *resources_path = buf_ptr(g->zig_c_headers_dir);
8302 Stage2ErrorMsg *errors_ptr;
8303 size_t errors_len;
8304 Stage2Ast *ast;
8305 AstNode *root_node;
8306
83018307 if (use_userland_implementation) {
8302 Stage2Ast *ast;
8303 if ((err = stage2_translate_c(&ast, &clang_argv.at(0), &clang_argv.last(), trans_mode))) {
8304 zig_panic("TODO");
8305 }
8306 stage2_render_ast(ast, out_file);
8308 err = stage2_translate_c(&ast, &errors_ptr, &errors_len,
8309 &clang_argv.at(0), &clang_argv.last(), trans_mode, resources_path);
83078310 } else {
8308 ZigList<ErrorMsg *> errors = {0};
8309 AstNode *root_node;
8310
8311 err = parse_h_file(g, &root_node, &clang_argv.at(0), &clang_argv.last(), trans_mode, &errors);
8311 err = parse_h_file(g, &root_node, &errors_ptr, &errors_len, &clang_argv.at(0), &clang_argv.last(),
8312 trans_mode, resources_path);
8313 }
83128314
8313 if (err == ErrorCCompileErrors && errors.length > 0) {
8314 for (size_t i = 0; i < errors.length; i += 1) {
8315 ErrorMsg *err_msg = errors.at(i);
8316 print_err_msg(err_msg, g->err_color);
8317 }
8318 exit(1);
8315 if (err == ErrorCCompileErrors && errors_len > 0) {
8316 for (size_t i = 0; i < errors_len; i += 1) {
8317 Stage2ErrorMsg *clang_err = &errors_ptr[i];
8318 ErrorMsg *err_msg = err_msg_create_with_offset(
8319 clang_err->filename_ptr ?
8320 buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
8321 clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
8322 buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
8323 print_err_msg(err_msg, g->err_color);
83198324 }
8325 exit(1);
8326 }
83208327
8321 if (err) {
8322 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
8323 exit(1);
8324 }
8328 if (err) {
8329 fprintf(stderr, "unable to parse C file: %s\n", err_str(err));
8330 exit(1);
8331 }
83258332
8333
8334 if (use_userland_implementation) {
8335 stage2_render_ast(ast, out_file);
8336 } else {
83268337 ast_render(out_file, root_node, 4);
83278338 }
83288339}
src/ir.cpp+13-6
......@@ -19103,25 +19103,32 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1910319103
1910419104 clang_argv.append(nullptr); // to make the [start...end] argument work
1910519105
19106 ZigList<ErrorMsg *> errors = {0};
1910719106 AstNode *root_node;
19107 Stage2ErrorMsg *errors_ptr;
19108 size_t errors_len;
1910819109
19109 if ((err = parse_h_file(ira->codegen, &root_node, &clang_argv.at(0), &clang_argv.last(),
19110 Stage2TranslateModeImport, &errors)))
19110 const char *resources_path = buf_ptr(ira->codegen->zig_c_headers_dir);
19111
19112 if ((err = parse_h_file(ira->codegen, &root_node, &errors_ptr, &errors_len,
19113 &clang_argv.at(0), &clang_argv.last(), Stage2TranslateModeImport, resources_path)))
1911119114 {
1911219115 if (err != ErrorCCompileErrors) {
1911319116 ir_add_error_node(ira, node, buf_sprintf("C import failed: %s", err_str(err)));
1911419117 return ira->codegen->invalid_instruction;
1911519118 }
19116 assert(errors.length > 0);
1911719119
1911819120 ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
1911919121 if (ira->codegen->libc_link_lib == nullptr) {
1912019122 add_error_note(ira->codegen, parent_err_msg, node,
1912119123 buf_sprintf("libc headers not available; compilation does not link against libc"));
1912219124 }
19123 for (size_t i = 0; i < errors.length; i += 1) {
19124 ErrorMsg *err_msg = errors.at(i);
19125 for (size_t i = 0; i < errors_len; i += 1) {
19126 Stage2ErrorMsg *clang_err = &errors_ptr[i];
19127 ErrorMsg *err_msg = err_msg_create_with_offset(
19128 clang_err->filename_ptr ?
19129 buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(),
19130 clang_err->line, clang_err->column, clang_err->offset, clang_err->source,
19131 buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len));
1912519132 err_msg_add_note(parent_err_msg, err_msg);
1912619133 }
1912719134
src/translate_c.cpp+9-77
......@@ -76,10 +76,9 @@ struct TransScopeWhile {
7676};
7777
7878struct Context {
79 ZigList<ErrorMsg *> *errors;
79 AstNode *root;
8080 VisibMod visib_mod;
8181 bool want_export;
82 AstNode *root;
8382 HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
8483 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
8584 HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
......@@ -5018,13 +5017,14 @@ static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
50185017 }
50195018}
50205019
5021Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end,
5022 Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors)
5020Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
5021 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
5022 const char **args_begin, const char **args_end,
5023 Stage2TranslateMode mode, const char *resources_path)
50235024{
50245025 Context context = {0};
50255026 Context *c = &context;
50265027 c->warnings_on = codegen->verbose_cimport;
5027 c->errors = errors;
50285028 if (mode == Stage2TranslateModeImport) {
50295029 c->visib_mod = VisibModPub;
50305030 c->want_export = false;
......@@ -5039,78 +5039,10 @@ Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_
50395039 c->codegen = codegen;
50405040 c->global_scope = trans_scope_root_create(c);
50415041
5042
5043 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
5044
5045 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
5046
5047 bool only_local_decls = true;
5048 bool capture_diagnostics = true;
5049 bool user_files_are_volatile = true;
5050 bool allow_pch_with_compiler_errors = false;
5051 bool single_file_parse = false;
5052 bool for_serialization = false;
5053 const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
5054 std::unique_ptr<clang::ASTUnit> err_unit;
5055 ZigClangASTUnit *ast_unit = reinterpret_cast<ZigClangASTUnit *>(clang::ASTUnit::LoadFromCommandLine(
5056 args_begin, args_end,
5057 pch_container_ops, diags, resources_path,
5058 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
5059 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
5060 single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
5061 nullptr));
5062
5063 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
5064 if (!ast_unit && !err_unit) {
5065 return ErrorFileSystem;
5066 }
5067
5068 if (diags->getClient()->getNumErrors() > 0) {
5069 if (ast_unit) {
5070 err_unit = std::unique_ptr<clang::ASTUnit>(reinterpret_cast<clang::ASTUnit *>(ast_unit));
5071 }
5072
5073 for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
5074 it_end = err_unit->stored_diag_end();
5075 it != it_end; ++it)
5076 {
5077 switch (it->getLevel()) {
5078 case clang::DiagnosticsEngine::Ignored:
5079 case clang::DiagnosticsEngine::Note:
5080 case clang::DiagnosticsEngine::Remark:
5081 case clang::DiagnosticsEngine::Warning:
5082 continue;
5083 case clang::DiagnosticsEngine::Error:
5084 case clang::DiagnosticsEngine::Fatal:
5085 break;
5086 }
5087 llvm::StringRef msg_str_ref = it->getMessage();
5088 Buf *msg = string_ref_to_buf(msg_str_ref);
5089 clang::FullSourceLoc fsl = it->getLocation();
5090 if (fsl.hasManager()) {
5091 clang::FileID file_id = fsl.getFileID();
5092 clang::StringRef filename = fsl.getManager().getFilename(fsl);
5093 unsigned line = fsl.getSpellingLineNumber() - 1;
5094 unsigned column = fsl.getSpellingColumnNumber() - 1;
5095 unsigned offset = fsl.getManager().getFileOffset(fsl);
5096 const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
5097 Buf *path;
5098 if (filename.empty()) {
5099 path = buf_alloc();
5100 } else {
5101 path = string_ref_to_buf(filename);
5102 }
5103
5104 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
5105
5106 c->errors->append(err_msg);
5107 } else {
5108 // NOTE the only known way this gets triggered right now is if you have a lot of errors
5109 // clang emits "too many errors emitted, stopping now"
5110 fprintf(stderr, "unexpected error from clang: %s\n", buf_ptr(msg));
5111 }
5112 }
5113
5042 ZigClangASTUnit *ast_unit = ZigClangLoadFromCommandLine(args_begin, args_end, errors_ptr, errors_len,
5043 resources_path);
5044 if (ast_unit == nullptr) {
5045 if (*errors_len == 0) return ErrorNoMem;
51145046 return ErrorCCompileErrors;
51155047 }
51165048
src/translate_c.hpp+4-2
......@@ -11,7 +11,9 @@
1111
1212#include "all_types.hpp"
1313
14Error parse_h_file(CodeGen *codegen, AstNode **out_root_node, const char **args_begin, const char **args_end,
15 Stage2TranslateMode mode, ZigList<ErrorMsg *> *errors);
14Error parse_h_file(CodeGen *codegen, AstNode **out_root_node,
15 Stage2ErrorMsg **errors_ptr, size_t *errors_len,
16 const char **args_begin, const char **args_end,
17 Stage2TranslateMode mode, const char *resources_path);
1618
1719#endif
src/userland.cpp+8-1
......@@ -8,12 +8,19 @@
88#include <string.h>
99
1010Error stage2_translate_c(struct Stage2Ast **out_ast,
11 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode)
11 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
12 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
13 const char *resources_path)
1214{
1315 const char *msg = "stage0 called stage2_translate_c";
1416 stage2_panic(msg, strlen(msg));
1517}
1618
19void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len) {
20 const char *msg = "stage0 called stage2_free_clang_errors";
21 stage2_panic(msg, strlen(msg));
22}
23
1724void stage2_zen(const char **ptr, size_t *len) {
1825 const char *msg = "stage0 called stage2_zen";
1926 stage2_panic(msg, strlen(msg));
src/userland.h+35-11
......@@ -12,20 +12,21 @@
1212#include <stdio.h>
1313
1414#ifdef __cplusplus
15#define ZIG_USERLAND_EXTERN_C extern "C"
15#define ZIG_EXTERN_C extern "C"
1616#else
17#define ZIG_USERLAND_EXTERN_C
17#define ZIG_EXTERN_C
1818#endif
1919
2020#if defined(_MSC_VER)
21#define ZIG_USERLAND_ATTRIBUTE_NORETURN __declspec(noreturn)
21#define ZIG_ATTRIBUTE_NORETURN __declspec(noreturn)
2222#else
23#define ZIG_USERLAND_ATTRIBUTE_NORETURN __attribute__((noreturn))
23#define ZIG_ATTRIBUTE_NORETURN __attribute__((noreturn))
2424#endif
2525
26// The types and declarations in this file must match both those in userland.cpp and
27// src-self-hosted/stage1.zig.
26// ABI warning: the types and declarations in this file must match both those in
27// userland.cpp and src-self-hosted/stage1.zig.
2828
29// ABI warning
2930enum Error {
3031 ErrorNone,
3132 ErrorNoMem,
......@@ -74,20 +75,43 @@ enum Error {
7475 ErrorNoSpaceLeft,
7576};
7677
78// ABI warning
7779enum Stage2TranslateMode {
7880 Stage2TranslateModeImport,
7981 Stage2TranslateModeTranslate,
8082};
8183
84// ABI warning
85struct Stage2ErrorMsg {
86 const char *filename_ptr; // can be null
87 size_t filename_len;
88 const char *msg_ptr;
89 size_t msg_len;
90 const char *source; // valid until the ASTUnit is freed. can be null
91 unsigned line; // 0 based
92 unsigned column; // 0 based
93 unsigned offset; // byte offset into source
94};
95
96// ABI warning
8297struct Stage2Ast;
8398
84ZIG_USERLAND_EXTERN_C Error stage2_translate_c(struct Stage2Ast **out_ast,
85 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode);
99// ABI warning
100ZIG_EXTERN_C enum Error stage2_translate_c(struct Stage2Ast **out_ast,
101 struct Stage2ErrorMsg **out_errors_ptr, size_t *out_errors_len,
102 const char **args_begin, const char **args_end, enum Stage2TranslateMode mode,
103 const char *resources_path);
104
105// ABI warning
106ZIG_EXTERN_C void stage2_free_clang_errors(struct Stage2ErrorMsg *ptr, size_t len);
86107
87ZIG_USERLAND_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
108// ABI warning
109ZIG_EXTERN_C void stage2_render_ast(struct Stage2Ast *ast, FILE *output_file);
88110
89ZIG_USERLAND_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
111// ABI warning
112ZIG_EXTERN_C void stage2_zen(const char **ptr, size_t *len);
90113
91ZIG_USERLAND_EXTERN_C ZIG_USERLAND_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
114// ABI warning
115ZIG_EXTERN_C ZIG_ATTRIBUTE_NORETURN void stage2_panic(const char *ptr, size_t len);
92116
93117#endif
src/zig_clang.cpp+112
......@@ -1147,3 +1147,115 @@ ZigClangAPValueLValueBase ZigClangAPValue_getLValueBase(const ZigClangAPValue *s
11471147 clang::APValue::LValueBase lval_base = casted->getLValueBase();
11481148 return bitcast(lval_base);
11491149}
1150
1151ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
1152 struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path)
1153{
1154 clang::IntrusiveRefCntPtr<clang::DiagnosticsEngine> diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
1155
1156 std::shared_ptr<clang::PCHContainerOperations> pch_container_ops = std::make_shared<clang::PCHContainerOperations>();
1157
1158 bool only_local_decls = true;
1159 bool capture_diagnostics = true;
1160 bool user_files_are_volatile = true;
1161 bool allow_pch_with_compiler_errors = false;
1162 bool single_file_parse = false;
1163 bool for_serialization = false;
1164 std::unique_ptr<clang::ASTUnit> *err_unit = new std::unique_ptr<clang::ASTUnit>();
1165 clang::ASTUnit *ast_unit = clang::ASTUnit::LoadFromCommandLine(
1166 args_begin, args_end,
1167 pch_container_ops, diags, resources_path,
1168 only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
1169 false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
1170 single_file_parse, user_files_are_volatile, for_serialization, clang::None, err_unit,
1171 nullptr);
1172
1173 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
1174 if (!ast_unit && !err_unit) {
1175 return nullptr;
1176 }
1177
1178 if (diags->getClient()->getNumErrors() > 0) {
1179 if (ast_unit) {
1180 *err_unit = std::unique_ptr<clang::ASTUnit>(ast_unit);
1181 }
1182
1183 size_t cap = 4;
1184 *errors_len = 0;
1185 *errors_ptr = reinterpret_cast<Stage2ErrorMsg*>(malloc(cap * sizeof(Stage2ErrorMsg)));
1186 if (*errors_ptr == nullptr) {
1187 return nullptr;
1188 }
1189
1190 for (clang::ASTUnit::stored_diag_iterator it = (*err_unit)->stored_diag_begin(),
1191 it_end = (*err_unit)->stored_diag_end();
1192 it != it_end; ++it)
1193 {
1194 switch (it->getLevel()) {
1195 case clang::DiagnosticsEngine::Ignored:
1196 case clang::DiagnosticsEngine::Note:
1197 case clang::DiagnosticsEngine::Remark:
1198 case clang::DiagnosticsEngine::Warning:
1199 continue;
1200 case clang::DiagnosticsEngine::Error:
1201 case clang::DiagnosticsEngine::Fatal:
1202 break;
1203 }
1204 llvm::StringRef msg_str_ref = it->getMessage();
1205 if (*errors_len >= cap) {
1206 cap *= 2;
1207 Stage2ErrorMsg *new_errors = reinterpret_cast<Stage2ErrorMsg *>(
1208 realloc(*errors_ptr, cap * sizeof(Stage2ErrorMsg)));
1209 if (new_errors == nullptr) {
1210 free(*errors_ptr);
1211 *errors_ptr = nullptr;
1212 *errors_len = 0;
1213 return nullptr;
1214 }
1215 *errors_ptr = new_errors;
1216 }
1217 Stage2ErrorMsg *msg = *errors_ptr + *errors_len;
1218 *errors_len += 1;
1219 msg->msg_ptr = (const char *)msg_str_ref.bytes_begin();
1220 msg->msg_len = msg_str_ref.size();
1221
1222 clang::FullSourceLoc fsl = it->getLocation();
1223 if (fsl.hasManager()) {
1224 clang::FileID file_id = fsl.getFileID();
1225 clang::StringRef filename = fsl.getManager().getFilename(fsl);
1226 if (filename.empty()) {
1227 msg->filename_ptr = nullptr;
1228 } else {
1229 msg->filename_ptr = (const char *)filename.bytes_begin();
1230 msg->filename_len = filename.size();
1231 }
1232 msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
1233 msg->line = fsl.getSpellingLineNumber() - 1;
1234 msg->column = fsl.getSpellingColumnNumber() - 1;
1235 msg->offset = fsl.getManager().getFileOffset(fsl);
1236 } else {
1237 // The only known way this gets triggered right now is if you have a lot of errors
1238 // clang emits "too many errors emitted, stopping now"
1239 msg->filename_ptr = nullptr;
1240 msg->source = nullptr;
1241 }
1242 }
1243
1244 if (*errors_len == 0) {
1245 free(*errors_ptr);
1246 *errors_ptr = nullptr;
1247 }
1248
1249 return nullptr;
1250 }
1251
1252 return reinterpret_cast<ZigClangASTUnit *>(ast_unit);
1253}
1254
1255void ZigClangErrorMsg_delete(Stage2ErrorMsg *ptr, size_t len) {
1256 free(ptr);
1257}
1258
1259void ZigClangASTUnit_delete(struct ZigClangASTUnit *self) {
1260 delete reinterpret_cast<clang::ASTUnit *>(self);
1261}
src/zig_clang.h+8-6
......@@ -8,15 +8,10 @@
88#ifndef ZIG_ZIG_CLANG_H
99#define ZIG_ZIG_CLANG_H
1010
11#include "userland.h"
1112#include <inttypes.h>
1213#include <stdbool.h>
1314
14#ifdef __cplusplus
15#define ZIG_EXTERN_C extern "C"
16#else
17#define ZIG_EXTERN_C
18#endif
19
2015// ATTENTION: If you modify this file, be sure to update the corresponding
2116// extern function declarations in the self-hosted compiler file
2217// src-self-hosted/clang.zig.
......@@ -500,6 +495,13 @@ ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const struct Zig
500495
501496ZIG_EXTERN_C struct ZigClangQualType ZigClangASTContext_getPointerType(const struct ZigClangASTContext*, struct ZigClangQualType T);
502497
498
499// Can return null.
500ZIG_EXTERN_C struct ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char **args_end,
501 struct Stage2ErrorMsg **errors_ptr, size_t *errors_len, const char *resources_path);
502ZIG_EXTERN_C void ZigClangASTUnit_delete(struct ZigClangASTUnit *);
503ZIG_EXTERN_C void ZigClangErrorMsg_delete(struct Stage2ErrorMsg *ptr, size_t len);
504
503505ZIG_EXTERN_C struct ZigClangASTContext *ZigClangASTUnit_getASTContext(struct ZigClangASTUnit *);
504506ZIG_EXTERN_C struct ZigClangSourceManager *ZigClangASTUnit_getSourceManager(struct ZigClangASTUnit *);
505507ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(struct ZigClangASTUnit *, void *context,