authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 00:01:49-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-01-27 00:01:49-07:00
log0278468479d52d6ea64521ab78574b593a6832ae
treed7438d5c45de76b453efa7d3fab5a33ea27db347
parentac085a869d068ca60548ad5298682ff054e91141

upgrade to the libclang C++ API

c_import creates a tmp .h file and parses it with libclang, reporting any errors found. See #88

16 files changed, 373 insertions(+), 684 deletions(-)

CMakeLists.txt+2-2
......@@ -17,7 +17,7 @@ include_directories(${LLVM_INCLUDE_DIRS})
1717link_directories(${LLVM_LIBDIRS})
1818
1919find_package(clang)
20include_directories(${CLANG_INCLUDE_DIR})
20include_directories(${CLANG_INCLUDE_DIRS})
2121
2222include_directories(
2323 ${CMAKE_SOURCE_DIR}
......@@ -148,7 +148,7 @@ set_target_properties(zig PROPERTIES
148148 COMPILE_FLAGS ${EXE_CFLAGS})
149149target_link_libraries(zig LINK_PUBLIC
150150 ${LLVM_LIBRARIES}
151 ${CLANG_LIBRARY}
151 ${CLANG_LIBRARIES}
152152)
153153install(TARGETS zig DESTINATION bin)
154154
README.md+1-1
......@@ -75,7 +75,7 @@ be set to (example below).
7575```
7676mkdir build
7777cd build
78cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_DIR=$(dirname $(cc -print-file-name=crt1.o))
78cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_DIR=$(dirname $(dirname $(cc -print-file-name=crt1.o)))
7979make
8080make install
8181./run_tests
cmake/Findclang.cmake+25-7
......@@ -1,16 +1,34 @@
1# Copyright (c) 2015 Andrew Kelley
1# Copyright (c) 2016 Andrew Kelley
22# This file is MIT licensed.
33# See http://opensource.org/licenses/MIT
44
55# CLANG_FOUND
6# CLANG_INCLUDE_DIR
7# CLANG_LIBRARY
6# CLANG_INCLUDE_DIRS
7# CLANG_LIBRARIES
88
9find_path(CLANG_INCLUDE_DIR NAMES clang-c/Index.h PATHS /usr/lib/llvm-3.7/include/)
9find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h)
1010
11find_library(CLANG_LIBRARY NAMES clang PATHS /usr/lib/llvm-3.7/lib/)
11macro(FIND_AND_ADD_CLANG_LIB _libname_)
12 string(TOUPPER ${_libname_} _prettylibname_)
13 find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_})
14 if(CLANG_${_prettylibname_}_LIB)
15 set(CLANG_LIBRARIES ${CLANG_LIBRARIES} ${CLANG_${_prettylibname_}_LIB})
16 endif()
17endmacro(FIND_AND_ADD_CLANG_LIB)
18
19FIND_AND_ADD_CLANG_LIB(clangFrontend)
20FIND_AND_ADD_CLANG_LIB(clangDriver)
21FIND_AND_ADD_CLANG_LIB(clangSerialization)
22FIND_AND_ADD_CLANG_LIB(clangSema)
23FIND_AND_ADD_CLANG_LIB(clangAnalysis)
24FIND_AND_ADD_CLANG_LIB(clangAST)
25FIND_AND_ADD_CLANG_LIB(clangParse)
26FIND_AND_ADD_CLANG_LIB(clangSema)
27FIND_AND_ADD_CLANG_LIB(clangBasic)
28FIND_AND_ADD_CLANG_LIB(clangEdit)
29FIND_AND_ADD_CLANG_LIB(clangLex)
1230
1331include(FindPackageHandleStandardArgs)
14find_package_handle_standard_args(CLANG DEFAULT_MSG CLANG_LIBRARY CLANG_INCLUDE_DIR)
32find_package_handle_standard_args(CLANG DEFAULT_MSG CLANG_LIBRARIES CLANG_INCLUDE_DIRS)
1533
16mark_as_advanced(CLANG_INCLUDE_DIR CLANG_LIBRARY)
34mark_as_advanced(CLANG_INCLUDE_DIRS CLANG_LIBRARIES)
src/all_types.hpp+10
......@@ -995,6 +995,8 @@ struct CodeGen {
995995 bool have_exported_main;
996996 bool link_libc;
997997 Buf *libc_path;
998 Buf *libc_lib_path;
999 Buf *libc_include_path;
9981000 CodeGenBuildType build_type;
9991001 LLVMTargetMachineRef target_machine;
10001002 LLVMZigDIFile *dummy_di_file;
......@@ -1068,4 +1070,12 @@ struct BlockContext {
10681070 Buf *c_import_buf;
10691071};
10701072
1073struct ParseH {
1074 ZigList<ErrorMsg*> errors;
1075 ZigList<AstNode *> fn_list;
1076 ZigList<AstNode *> struct_list;
1077 ZigList<AstNode *> var_list;
1078 ZigList<AstNode *> incomplete_struct_list;
1079};
1080
10711081#endif
src/analyze.cpp+43-14
......@@ -10,6 +10,8 @@
1010#include "error.hpp"
1111#include "zig_llvm.hpp"
1212#include "os.hpp"
13#include "parseh.hpp"
14#include "config.h"
1315
1416static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, BlockContext *context,
1517 TypeTableEntry *expected_type, AstNode *node);
......@@ -83,18 +85,12 @@ static AstNode *first_executing_node(AstNode *node) {
8385 zig_unreachable();
8486}
8587
86void add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
87 ErrorMsg *err = allocate<ErrorMsg>(1);
88 err->line_start = node->line;
89 err->column_start = node->column;
90 err->line_end = -1;
91 err->column_end = -1;
92 err->msg = msg;
93 err->path = node->owner->path;
94 err->source = node->owner->source_code;
95 err->line_offsets = node->owner->line_offsets;
88ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg) {
89 ErrorMsg *err = err_msg_create_with_line(node->owner->path, node->line, node->column,
90 node->owner->source_code, node->owner->line_offsets, msg);
9691
9792 g->errors.append(err);
93 return err;
9894}
9995
10096TypeTableEntry *new_type_table_entry(TypeTableEntryId id) {
......@@ -1036,8 +1032,22 @@ static void resolve_c_import_decl(CodeGen *g, ImportTableEntry *import, AstNode
10361032 return;
10371033 }
10381034
1039 fprintf(stderr, "c import buf:\n%s\n", buf_ptr(child_context->c_import_buf));
1040 zig_panic("TODO");
1035 find_libc_path(g);
1036 int err;
1037 ParseH parse_h = {{0}};
1038 if ((err = parse_h_buf(&parse_h, child_context->c_import_buf, buf_ptr(g->libc_include_path)))) {
1039 zig_panic("unable to parse h file: %s\n", err_str(err));
1040 }
1041
1042 if (parse_h.errors.length > 0) {
1043 ErrorMsg *parent_err_msg = add_node_error(g, node, buf_sprintf("C import failed"));
1044 for (int i = 0; i < parse_h.errors.length; i += 1) {
1045 ErrorMsg *err_msg = parse_h.errors.at(i);
1046 err_msg_add_note(parent_err_msg, err_msg);
1047 }
1048 } else {
1049 zig_panic("TODO integrate the parsed AST");
1050 }
10411051}
10421052
10431053static void resolve_top_level_decl(CodeGen *g, ImportTableEntry *import, AstNode *node) {
......@@ -3444,7 +3454,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
34443454 return g->builtin_types.entry_void;
34453455 }
34463456
3447 buf_appendf(context->c_import_buf, "#include \"");
3457 buf_appendf(context->c_import_buf, "#include <");
34483458 ConstExprValue *ptr_field = const_str_val->data.x_struct.fields[0];
34493459 uint64_t len = ptr_field->data.x_ptr.len;
34503460 for (uint64_t i = 0; i < len; i += 1) {
......@@ -3454,7 +3464,7 @@ static TypeTableEntry *analyze_builtin_fn_call_expr(CodeGen *g, ImportTableEntry
34543464 uint8_t c = big_c;
34553465 buf_appendf(context->c_import_buf, "%c", c);
34563466 }
3457 buf_appendf(context->c_import_buf, "\"\n");
3467 buf_appendf(context->c_import_buf, ">\n");
34583468
34593469 return g->builtin_types.entry_void;
34603470 }
......@@ -4976,3 +4986,22 @@ bool handle_is_ptr(TypeTableEntry *type_entry) {
49764986 }
49774987 zig_unreachable();
49784988}
4989
4990void find_libc_path(CodeGen *g) {
4991 if (!g->libc_path || buf_len(g->libc_path) == 0) {
4992 g->libc_path = buf_create_from_str(ZIG_LIBC_DIR);
4993 if (!g->libc_path || buf_len(g->libc_path) == 0) {
4994 // later we can handle this better by reporting an error via the normal mechanism
4995 zig_panic("Unable to determine libc path. You can use `--libc-path`");
4996 }
4997 }
4998 if (!g->libc_lib_path) {
4999 g->libc_lib_path = buf_alloc();
5000 os_path_join(g->libc_path, buf_create_from_str("lib"), g->libc_lib_path);
5001 }
5002 if (!g->libc_include_path) {
5003 g->libc_include_path = buf_alloc();
5004 os_path_join(g->libc_path, buf_create_from_str("include"), g->libc_include_path);
5005 }
5006}
5007
src/analyze.hpp+3-1
......@@ -11,7 +11,7 @@
1111#include "all_types.hpp"
1212
1313void semantic_analyze(CodeGen *g);
14void add_node_error(CodeGen *g, AstNode *node, Buf *msg);
14ErrorMsg *add_node_error(CodeGen *g, AstNode *node, Buf *msg);
1515TypeTableEntry *new_type_table_entry(TypeTableEntryId id);
1616TypeTableEntry *get_pointer_to_type(CodeGen *g, TypeTableEntry *child_type, bool is_const);
1717VariableTableEntry *find_variable(BlockContext *context, Buf *name);
......@@ -23,4 +23,6 @@ bool is_node_void_expr(AstNode *node);
2323TypeTableEntry **get_int_type_ptr(CodeGen *g, bool is_signed, int size_in_bits);
2424TypeTableEntry *get_int_type(CodeGen *g, bool is_signed, int size_in_bits);
2525bool handle_is_ptr(TypeTableEntry *type_entry);
26void find_libc_path(CodeGen *g);
27
2628#endif
src/codegen.cpp+3-20
......@@ -3051,15 +3051,8 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *abs_full_path,
30513051 tokenize(source_code, &tokenization);
30523052
30533053 if (tokenization.err) {
3054 ErrorMsg *err = allocate<ErrorMsg>(1);
3055 err->line_start = tokenization.err_line;
3056 err->column_start = tokenization.err_column;
3057 err->line_end = -1;
3058 err->column_end = -1;
3059 err->msg = tokenization.err;
3060 err->path = full_path;
3061 err->source = source_code;
3062 err->line_offsets = tokenization.line_offsets;
3054 ErrorMsg *err = err_msg_create_with_line(full_path, tokenization.err_line, tokenization.err_column,
3055 source_code, tokenization.line_offsets, tokenization.err);
30633056
30643057 print_err_msg(err, g->err_color);
30653058 exit(1);
......@@ -3401,19 +3394,9 @@ static void generate_h_file(CodeGen *g) {
34013394 zig_panic("unable to close h file: %s", strerror(errno));
34023395}
34033396
3404static void find_libc_path(CodeGen *g) {
3405 if (g->libc_path && buf_len(g->libc_path))
3406 return;
3407 g->libc_path = buf_create_from_str(ZIG_LIBC_DIR);
3408 if (g->libc_path && buf_len(g->libc_path))
3409 return;
3410 fprintf(stderr, "Unable to determine libc path. Consider using `--libc-path [path]`\n");
3411 exit(1);
3412}
3413
34143397static const char *get_libc_file(CodeGen *g, const char *file) {
34153398 Buf *out_buf = buf_alloc();
3416 os_path_join(g->libc_path, buf_create_from_str(file), out_buf);
3399 os_path_join(g->libc_lib_path, buf_create_from_str(file), out_buf);
34173400 return buf_ptr(out_buf);
34183401}
34193402
src/errmsg.cpp+58-10
......@@ -15,16 +15,7 @@ void print_err_msg(ErrorMsg *err, ErrColor color) {
1515 err->line_start + 1, err->column_start + 1,
1616 buf_ptr(err->msg));
1717
18 assert(err->source);
19 assert(err->line_offsets);
20
21 int line_start_offset = err->line_offsets->at(err->line_start);
22 int end_line = err->line_start + 1;
23 int line_end_offset = (end_line >= err->line_offsets->length) ?
24 buf_len(err->source) : err->line_offsets->at(err->line_start + 1);
25
26 fwrite(buf_ptr(err->source) + line_start_offset, 1, line_end_offset - line_start_offset - 1, stderr);
27 fprintf(stderr, "\n");
18 fprintf(stderr, "%s\n", buf_ptr(&err->line_buf));
2819 for (int i = 0; i < err->column_start; i += 1) {
2920 fprintf(stderr, " ");
3021 }
......@@ -36,5 +27,62 @@ void print_err_msg(ErrorMsg *err, ErrColor color) {
3627 err->line_start + 1, err->column_start + 1,
3728 buf_ptr(err->msg));
3829 }
30
31 for (int i = 0; i < err->notes.length; i += 1) {
32 ErrorMsg *note = err->notes.at(i);
33 print_err_msg(note, color);
34 }
35}
36
37void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note) {
38 parent->notes.append(note);
3939}
4040
41ErrorMsg *err_msg_create_with_offset(Buf *path, int line, int column, int offset,
42 const char *source, Buf *msg)
43{
44 ErrorMsg *err_msg = allocate<ErrorMsg>(1);
45 err_msg->path = path;
46 err_msg->line_start = line;
47 err_msg->column_start = column;
48 err_msg->msg = msg;
49
50 int line_start_offset = offset;
51 for (;;) {
52 if (line_start_offset == 0) {
53 break;
54 } else if (source[line_start_offset] == '\n') {
55 line_start_offset += 1;
56 break;
57 }
58 line_start_offset -= 1;
59 }
60
61 int line_end_offset = offset;
62 while (source[line_end_offset] && source[line_end_offset] != '\n') {
63 line_end_offset += 1;
64 }
65
66 buf_init_from_mem(&err_msg->line_buf, source + line_start_offset, line_end_offset - line_start_offset);
67
68 return err_msg;
69}
70
71ErrorMsg *err_msg_create_with_line(Buf *path, int line, int column,
72 Buf *source, ZigList<int> *line_offsets, Buf *msg)
73{
74 ErrorMsg *err_msg = allocate<ErrorMsg>(1);
75 err_msg->path = path;
76 err_msg->line_start = line;
77 err_msg->column_start = column;
78 err_msg->msg = msg;
79
80 int line_start_offset = line_offsets->at(line);
81 int end_line = line + 1;
82 int line_end_offset = (end_line >= line_offsets->length) ? buf_len(source) : line_offsets->at(line + 1);
83
84 buf_init_from_mem(&err_msg->line_buf, buf_ptr(source) + line_start_offset,
85 line_end_offset - line_start_offset - 1);
86
87 return err_msg;
88}
src/errmsg.hpp+10-4
......@@ -20,14 +20,20 @@ enum ErrColor {
2020struct ErrorMsg {
2121 int line_start;
2222 int column_start;
23 int line_end;
24 int column_end;
2523 Buf *msg;
2624 Buf *path;
27 Buf *source;
28 ZigList<int> *line_offsets;
25 Buf line_buf;
26
27 ZigList<ErrorMsg *> notes;
2928};
3029
3130void print_err_msg(ErrorMsg *msg, ErrColor color);
3231
32void err_msg_add_note(ErrorMsg *parent, ErrorMsg *note);
33ErrorMsg *err_msg_create_with_offset(Buf *path, int line, int column, int offset,
34 const char *source, Buf *msg);
35
36ErrorMsg *err_msg_create_with_line(Buf *path, int line, int column,
37 Buf *source, ZigList<int> *line_offsets, Buf *msg);
38
3339#endif
src/main.cpp+86-1
......@@ -156,6 +156,25 @@ static int build(const char *arg0, int argc, char **argv) {
156156 return 0;
157157}
158158
159struct ParseHPrint {
160 ParseH parse_h;
161 FILE *f;
162 int cur_indent;
163};
164
165static const int indent_size = 4;
166
167static void print_indent(ParseHPrint *p) {
168 for (int i = 0; i < p->cur_indent; i += 1) {
169 fprintf(p->f, " ");
170 }
171}
172
173static const char *type_node_to_name(AstNode *type_node) {
174 assert(type_node->type == NodeTypeSymbol);
175 return buf_ptr(&type_node->data.symbol_expr.symbol);
176}
177
159178static int parseh(const char *arg0, int argc, char **argv) {
160179 char *in_file = nullptr;
161180 ZigList<const char *> clang_argv = {0};
......@@ -187,7 +206,73 @@ static int parseh(const char *arg0, int argc, char **argv) {
187206 return usage(arg0);
188207 }
189208
190 parse_h_file(in_file, &clang_argv, stdout);
209 clang_argv.append(in_file);
210
211 ParseHPrint parse_h_print = {{{0}}};
212 ParseHPrint *p = &parse_h_print;
213 p->f = stdout;
214 p->cur_indent = 0;
215
216 parse_h_file(&p->parse_h, &clang_argv);
217
218 if (p->parse_h.errors.length > 0) {
219 for (int i = 0; i < p->parse_h.errors.length; i += 1) {
220 ErrorMsg *err_msg = p->parse_h.errors.at(i);
221 // TODO respect --color arg
222 print_err_msg(err_msg, ErrColorAuto);
223 }
224 return EXIT_FAILURE;
225 }
226
227 for (int struct_i = 0; struct_i < p->parse_h.struct_list.length; struct_i += 1) {
228 AstNode *struct_decl = p->parse_h.struct_list.at(struct_i);
229 assert(struct_decl->type == NodeTypeStructDecl);
230 const char *struct_name = buf_ptr(&struct_decl->data.struct_decl.name);
231 print_indent(p);
232 fprintf(p->f, "struct %s {\n", struct_name);
233 p->cur_indent += indent_size;
234 for (int field_i = 0; field_i < struct_decl->data.struct_decl.fields.length; field_i += 1) {
235 AstNode *field_node = struct_decl->data.struct_decl.fields.at(field_i);
236 assert(field_node->type == NodeTypeStructField);
237 const char *field_name = buf_ptr(&field_node->data.struct_field.name);
238 const char *type_name = type_node_to_name(field_node->data.struct_field.type);
239 print_indent(p);
240 fprintf(p->f, "%s: %s,\n", field_name, type_name);
241 }
242
243 p->cur_indent -= indent_size;
244 fprintf(p->f, "}\n\n");
245 }
246
247 for (int fn_i = 0; fn_i < p->parse_h.fn_list.length; fn_i += 1) {
248 AstNode *fn_proto = p->parse_h.fn_list.at(fn_i);
249 assert(fn_proto->type == NodeTypeFnProto);
250 print_indent(p);
251 const char *fn_name = buf_ptr(&fn_proto->data.fn_proto.name);
252 fprintf(p->f, "extern fn %s(", fn_name);
253 int arg_count = fn_proto->data.fn_proto.params.length;
254 bool is_var_args = fn_proto->data.fn_proto.is_var_args;
255 for (int arg_i = 0; arg_i < arg_count; arg_i += 1) {
256 AstNode *param_decl = fn_proto->data.fn_proto.params.at(arg_i);
257 assert(param_decl->type == NodeTypeParamDecl);
258 const char *arg_name = buf_ptr(&param_decl->data.param_decl.name);
259 const char *arg_type = type_node_to_name(param_decl->data.param_decl.type);
260 fprintf(p->f, "%s: %s", arg_name, arg_type);
261 if (arg_i + 1 < arg_count || is_var_args) {
262 fprintf(p->f, ", ");
263 }
264 }
265 if (is_var_args) {
266 fprintf(p->f, "...");
267 }
268 fprintf(p->f, ")");
269 const char *return_type_name = type_node_to_name(fn_proto->data.fn_proto.return_type);
270 if (strcmp(return_type_name, "void") != 0) {
271 fprintf(p->f, " -> %s", return_type_name);
272 }
273 fprintf(p->f, ";\n");
274 }
275
191276 return 0;
192277}
193278
src/os.cpp+26
......@@ -208,3 +208,29 @@ int os_get_cwd(Buf *out_cwd) {
208208bool os_stderr_tty(void) {
209209 return isatty(STDERR_FILENO);
210210}
211
212int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
213 buf_resize(out_tmp_path, 0);
214 buf_appendf(out_tmp_path, "/tmp/XXXXXX%s", buf_ptr(suffix));
215
216 int fd = mkstemps(buf_ptr(out_tmp_path), buf_len(suffix));
217 if (fd < 0) {
218 return ErrorFileSystem;
219 }
220
221 ssize_t amt_written = write(fd, buf_ptr(contents), buf_len(contents));
222 if (amt_written != buf_len(contents))
223 zig_panic("write failed: %s", strerror(errno));
224 if (close(fd) == -1)
225 zig_panic("close failed");
226
227 return 0;
228}
229
230int os_delete_file(Buf *path) {
231 if (remove(buf_ptr(path))) {
232 return ErrorFileSystem;
233 } else {
234 return 0;
235 }
236}
src/os.hpp+3-1
......@@ -29,7 +29,9 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents);
2929
3030int os_get_cwd(Buf *out_cwd);
3131
32
3332bool os_stderr_tty(void);
3433
34int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
35int os_delete_file(Buf *path);
36
3537#endif
src/parseh.cpp+84-599
......@@ -7,540 +7,52 @@
77
88#include "parseh.hpp"
99#include "config.h"
10#include "os.hpp"
11#include "error.hpp"
1012
11#include <clang-c/Index.h>
13#include <clang/Frontend/ASTUnit.h>
14#include <clang/Frontend/CompilerInstance.h>
1215
1316#include <string.h>
1417
15struct TypeDef {
16 Buf alias;
17 Buf target;
18};
19
20struct Arg {
21 Buf name;
22 Buf *type;
23};
24
25struct Fn {
26 Buf name;
27 Buf *return_type;
28 Arg *args;
29 int arg_count;
30 bool is_variadic;
31};
32
33struct Field {
34 Buf name;
35 Buf *type;
36};
37
38struct Struct {
39 Buf name;
40 ZigList<Field*> fields;
41 bool have_def;
42};
43
44struct ParseH {
45 CXTranslationUnit tu;
46 FILE *f;
47 ZigList<Fn *> fn_list;
48 ZigList<Struct *> struct_list;
49 ZigList<TypeDef *> type_def_list;
50 ZigList<Struct *> incomplete_struct_list;
51 Fn *cur_fn;
52 Struct *cur_struct;
53 int arg_index;
54 int cur_indent;
55 CXSourceRange range;
56 CXSourceLocation location;
57};
58
59static const int indent_size = 4;
18using namespace clang;
6019
61struct TypeMapping {
62 const char *c_name;
63 const char *zig_name;
20struct Context {
21 ParseH *parse_h;
6422};
6523
66static const TypeMapping type_mappings[] = {
67 {
68 "int8_t",
69 "i8",
70 },
71 {
72 "uint8_t",
73 "u8",
74 },
75 {
76 "uint16_t",
77 "u16",
78 },
79 {
80 "uint32_t",
81 "u32",
82 },
83 {
84 "uint64_t",
85 "u64",
86 },
87 {
88 "int16_t",
89 "i16",
90 },
91 {
92 "int32_t",
93 "i32",
94 },
95 {
96 "int64_t",
97 "i64",
98 },
99 {
100 "intptr_t",
101 "isize",
102 },
103 {
104 "uintptr_t",
105 "usize",
106 },
107};
108
109static bool have_struct_def(ParseH *p, Buf *name) {
110 for (int i = 0; i < p->struct_list.length; i += 1) {
111 Struct *struc = p->struct_list.at(i);
112 if (struc->fields.length > 0 && buf_eql_buf(&struc->name, name)) {
113 return true;
114 }
115 }
116 return false;
117}
24static bool decl_visitor(void *context, const Decl *decl) {
25 //Context *c = (Context*)context;
11826
119static const char *c_to_zig_name(const char *name) {
120 for (int i = 0; i < array_length(type_mappings); i += 1) {
121 const TypeMapping *mapping = &type_mappings[i];
122 if (strcmp(mapping->c_name, name) == 0)
123 return mapping->zig_name;
124 }
125 return nullptr;
126}
27 fprintf(stderr, "got top level decl\n");
12728
128static bool str_has_prefix(const char *str, const char *prefix) {
129 while (*prefix) {
130 if (*str && *str == *prefix) {
131 str += 1;
132 prefix += 1;
133 } else {
134 return false;
135 }
136 }
13729 return true;
13830}
13931
140static const char *prefixes_stripped(CXType type) {
141 CXString name = clang_getTypeSpelling(type);
142 const char *c_name = clang_getCString(name);
143
144 static const char *prefixes[] = {
145 "struct ",
146 "enum ",
147 "const ",
148 };
149
150start_over:
151
152 for (int i = 0; i < array_length(prefixes); i += 1) {
153 const char *prefix = prefixes[i];
154 if (str_has_prefix(c_name, prefix)) {
155 c_name += strlen(prefix);
156 goto start_over;
157 }
158 }
159 return c_name;
160}
161
162static void print_location(ParseH *p) {
163 CXFile file;
164 unsigned line, column, offset;
165 clang_getFileLocation(p->location, &file, &line, &column, &offset);
166 CXString file_name = clang_getFileName(file);
167
168 fprintf(stderr, "%s line %u, column %u\n", clang_getCString(file_name), line, column);
169}
170
171static bool resolves_to_void(ParseH *p, CXType raw_type) {
172 if (raw_type.kind == CXType_Unexposed) {
173 CXType canonical = clang_getCanonicalType(raw_type);
174 if (canonical.kind == CXType_Unexposed)
175 zig_panic("clang C api insufficient");
176 else
177 return resolves_to_void(p, canonical);
178 }
179 if (raw_type.kind == CXType_Void) {
180 return true;
181 } else if (raw_type.kind == CXType_Typedef) {
182 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
183 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
184 return resolves_to_void(p, underlying_type);
185 }
186 return false;
187}
188
189static Buf *to_zig_type(ParseH *p, CXType raw_type) {
190 if (raw_type.kind == CXType_Unexposed) {
191 CXType canonical = clang_getCanonicalType(raw_type);
192 if (canonical.kind == CXType_Unexposed)
193 zig_panic("clang C api insufficient");
194 else
195 return to_zig_type(p, canonical);
196 }
197 switch (raw_type.kind) {
198 case CXType_Invalid:
199 case CXType_Unexposed:
200 zig_unreachable();
201 case CXType_Void:
202 zig_panic("void type encountered");
203 case CXType_Bool:
204 return buf_create_from_str("bool");
205 case CXType_SChar:
206 return buf_create_from_str("i8");
207 case CXType_UChar:
208 case CXType_Char_U:
209 case CXType_Char_S:
210 return buf_create_from_str("u8");
211 case CXType_WChar:
212 print_location(p);
213 zig_panic("TODO wchar");
214 case CXType_Char16:
215 print_location(p);
216 zig_panic("TODO char16");
217 case CXType_Char32:
218 print_location(p);
219 zig_panic("TODO char32");
220 case CXType_UShort:
221 return buf_create_from_str("c_ushort");
222 case CXType_UInt:
223 return buf_create_from_str("c_uint");
224 case CXType_ULong:
225 return buf_create_from_str("c_ulong");
226 case CXType_ULongLong:
227 return buf_create_from_str("c_ulonglong");
228 case CXType_UInt128:
229 print_location(p);
230 zig_panic("TODO uint128");
231 case CXType_Short:
232 return buf_create_from_str("c_short");
233 case CXType_Int:
234 return buf_create_from_str("c_int");
235 case CXType_Long:
236 return buf_create_from_str("c_long");
237 case CXType_LongLong:
238 return buf_create_from_str("c_longlong");
239 case CXType_Int128:
240 print_location(p);
241 zig_panic("TODO int128");
242 case CXType_Float:
243 return buf_create_from_str("f32");
244 case CXType_Double:
245 return buf_create_from_str("f64");
246 case CXType_LongDouble:
247 return buf_create_from_str("f128");
248 case CXType_IncompleteArray:
249 {
250 CXType pointee_type = clang_getArrayElementType(raw_type);
251 Buf *pointee_buf = to_zig_type(p, pointee_type);
252 if (clang_isConstQualifiedType(pointee_type)) {
253 return buf_sprintf("&const %s", buf_ptr(pointee_buf));
254 } else {
255 return buf_sprintf("&%s", buf_ptr(pointee_buf));
256 }
257 }
258 case CXType_Pointer:
259 {
260 CXType pointee_type = clang_getPointeeType(raw_type);
261 Buf *pointee_buf;
262 if (resolves_to_void(p, pointee_type)) {
263 pointee_buf = buf_create_from_str("u8");
264 } else {
265 pointee_buf = to_zig_type(p, pointee_type);
266 }
267 if (clang_isConstQualifiedType(pointee_type)) {
268 return buf_sprintf("&const %s", buf_ptr(pointee_buf));
269 } else {
270 return buf_sprintf("&%s", buf_ptr(pointee_buf));
271 }
272 }
273 case CXType_Record:
274 {
275 const char *name = prefixes_stripped(raw_type);
276 return buf_sprintf("%s", name);
277 }
278 case CXType_Enum:
279 {
280 const char *name = prefixes_stripped(raw_type);
281 return buf_sprintf("%s", name);
282 }
283 case CXType_Typedef:
284 {
285 const char *name = prefixes_stripped(raw_type);
286 const char *zig_name = c_to_zig_name(name);
287 if (zig_name) {
288 return buf_create_from_str(zig_name);
289 } else {
290 CXCursor typedef_cursor = clang_getTypeDeclaration(raw_type);
291 CXType underlying_type = clang_getTypedefDeclUnderlyingType(typedef_cursor);
292 if (resolves_to_void(p, underlying_type)) {
293 return buf_create_from_str("u8");
294 } else {
295 return buf_create_from_str(name);
296 }
297 }
298 }
299 case CXType_ConstantArray:
300 {
301 CXType child_type = clang_getArrayElementType(raw_type);
302 Buf *zig_child_type = to_zig_type(p, child_type);
303 long size = (long)clang_getArraySize(raw_type);
304 return buf_sprintf("[%s; %ld]", buf_ptr(zig_child_type), size);
305 }
306 case CXType_FunctionProto:
307 fprintf(stderr, "warning: TODO function proto\n");
308 print_location(p);
309 return buf_create_from_str("u8");
310 case CXType_FunctionNoProto:
311 print_location(p);
312 zig_panic("TODO function no proto");
313 case CXType_BlockPointer:
314 print_location(p);
315 zig_panic("TODO block pointer");
316 case CXType_Vector:
317 print_location(p);
318 zig_panic("TODO vector");
319 case CXType_LValueReference:
320 case CXType_RValueReference:
321 case CXType_VariableArray:
322 case CXType_DependentSizedArray:
323 case CXType_MemberPointer:
324 case CXType_ObjCInterface:
325 case CXType_ObjCObjectPointer:
326 case CXType_NullPtr:
327 case CXType_Overload:
328 case CXType_Dependent:
329 case CXType_ObjCId:
330 case CXType_ObjCClass:
331 case CXType_ObjCSel:
332 case CXType_Complex:
333 print_location(p);
334 zig_panic("TODO");
335 }
336
337 zig_unreachable();
338}
339
340static bool is_storage_class_export(CX_StorageClass storage_class) {
341 switch (storage_class) {
342 case CX_SC_Invalid:
343 zig_unreachable();
344 case CX_SC_None:
345 case CX_SC_Extern:
346 case CX_SC_Auto:
347 return true;
348 case CX_SC_Static:
349 case CX_SC_PrivateExtern:
350 case CX_SC_OpenCLWorkGroupLocal:
351 case CX_SC_Register:
352 return false;
353 }
354 zig_unreachable();
355}
356
357static enum CXChildVisitResult visit_fn_children(CXCursor cursor, CXCursor parent, CXClientData client_data) {
358 ParseH *p = (ParseH*)client_data;
359 enum CXCursorKind kind = clang_getCursorKind(cursor);
360
361 switch (kind) {
362 case CXCursor_ParmDecl:
363 {
364 assert(p->cur_fn);
365 assert(p->arg_index < p->cur_fn->arg_count);
366 CXString name = clang_getCursorSpelling(cursor);
367 Buf *arg_name = &p->cur_fn->args[p->arg_index].name;
368 buf_init_from_str(arg_name, clang_getCString(name));
369 if (buf_len(arg_name) == 0) {
370 buf_appendf(arg_name, "arg%d", p->arg_index);
371 }
372
373 p->arg_index += 1;
374 return CXChildVisit_Continue;
375 }
376 default:
377 return CXChildVisit_Recurse;
378 }
379}
380
381static enum CXChildVisitResult visit_struct_children(CXCursor cursor, CXCursor parent, CXClientData client_data) {
382 ParseH *p = (ParseH*)client_data;
383 enum CXCursorKind kind = clang_getCursorKind(cursor);
384
385 switch (kind) {
386 case CXCursor_FieldDecl:
387 {
388 assert(p->cur_struct);
389 CXString name = clang_getCursorSpelling(cursor);
390 Field *field = allocate<Field>(1);
391 buf_init_from_str(&field->name, clang_getCString(name));
392 CXType cursor_type = clang_getCursorType(cursor);
393 field->type = to_zig_type(p, cursor_type);
394
395 p->cur_struct->fields.append(field);
396
397 return CXChildVisit_Continue;
398 }
399 default:
400 return CXChildVisit_Recurse;
401 }
402}
403
404static bool handle_struct_cursor(ParseH *p, CXCursor cursor, const char *name, bool expect_name) {
405 p->cur_struct = allocate<Struct>(1);
406
407 buf_init_from_str(&p->cur_struct->name, name);
408
409 bool got_name = (buf_len(&p->cur_struct->name) != 0);
410 if (expect_name != got_name)
411 return false;
412
413 clang_visitChildren(cursor, visit_struct_children, p);
414
415 if (p->cur_struct->fields.length > 0) {
416 p->struct_list.append(p->cur_struct);
417 } else {
418 p->incomplete_struct_list.append(p->cur_struct);
32int parse_h_buf(ParseH *parse_h, Buf *source, const char *libc_include_path) {
33 int err;
34 Buf tmp_file_path = BUF_INIT;
35 if ((err = os_buf_to_tmp_file(source, buf_create_from_str(".h"), &tmp_file_path))) {
36 return err;
41937 }
38 ZigList<const char *> clang_argv = {0};
39 clang_argv.append(buf_ptr(&tmp_file_path));
42040
421 p->cur_struct = nullptr;
422
423 return true;
424}
425
426
427static enum CXChildVisitResult fn_visitor(CXCursor cursor, CXCursor parent, CXClientData client_data) {
428 ParseH *p = (ParseH*)client_data;
429 enum CXCursorKind kind = clang_getCursorKind(cursor);
430 CXString name = clang_getCursorSpelling(cursor);
431
432 p->range = clang_getCursorExtent(cursor);
433 p->location = clang_getRangeStart(p->range);
434
435 switch (kind) {
436 case CXCursor_FunctionDecl:
437 {
438 CX_StorageClass storage_class = clang_Cursor_getStorageClass(cursor);
439 if (!is_storage_class_export(storage_class))
440 return CXChildVisit_Continue;
441
442 CXType fn_type = clang_getCursorType(cursor);
443 if (clang_getFunctionTypeCallingConv(fn_type) != CXCallingConv_C) {
444 print_location(p);
445 fprintf(stderr, "warning: skipping non c calling convention function, not yet supported\n");
446 return CXChildVisit_Continue;
447 }
448
449 assert(!p->cur_fn);
450 p->cur_fn = allocate<Fn>(1);
451
452 p->cur_fn->is_variadic = clang_isFunctionTypeVariadic(fn_type);
453
454 CXType return_type = clang_getResultType(fn_type);
455 if (!resolves_to_void(p, return_type)) {
456 p->cur_fn->return_type = to_zig_type(p, return_type);
457 }
458
459 buf_init_from_str(&p->cur_fn->name, clang_getCString(name));
460
461 p->cur_fn->arg_count = clang_getNumArgTypes(fn_type);
462 p->cur_fn->args = allocate<Arg>(p->cur_fn->arg_count);
463
464 for (int i = 0; i < p->cur_fn->arg_count; i += 1) {
465 CXType param_type = clang_getArgType(fn_type, i);
466 p->cur_fn->args[i].type = to_zig_type(p, param_type);
467 }
468
469 p->arg_index = 0;
470
471 clang_visitChildren(cursor, visit_fn_children, p);
472
473 p->fn_list.append(p->cur_fn);
474 p->cur_fn = nullptr;
475
476 return CXChildVisit_Recurse;
477 }
478 case CXCursor_CompoundStmt:
479 case CXCursor_FieldDecl:
480 case CXCursor_TypedefDecl:
481 {
482 CXType underlying_type = clang_getTypedefDeclUnderlyingType(cursor);
483
484 if (resolves_to_void(p, underlying_type)) {
485 return CXChildVisit_Continue;
486 }
487
488 if (underlying_type.kind == CXType_Unexposed) {
489 underlying_type = clang_getCanonicalType(underlying_type);
490 }
491 bool skip_typedef;
492 if (underlying_type.kind == CXType_Unexposed) {
493 fprintf(stderr, "warning: unexposed type\n");
494 print_location(p);
495 skip_typedef = true;
496 } else if (underlying_type.kind == CXType_Record) {
497 CXCursor decl_cursor = clang_getTypeDeclaration(underlying_type);
498 skip_typedef = handle_struct_cursor(p, decl_cursor, clang_getCString(name), false);
499 } else if (underlying_type.kind == CXType_Invalid) {
500 fprintf(stderr, "warning: invalid type\n");
501 print_location(p);
502 skip_typedef = true;
503 } else {
504 skip_typedef = false;
505 }
506
507 CXType typedef_type = clang_getCursorType(cursor);
508 const char *name_str = prefixes_stripped(typedef_type);
509 if (!skip_typedef && c_to_zig_name(name_str)) {
510 skip_typedef = true;
511 }
41 clang_argv.append("-isystem");
42 clang_argv.append(libc_include_path);
51243
513 if (!skip_typedef) {
514 TypeDef *type_def = allocate<TypeDef>(1);
515 buf_init_from_str(&type_def->alias, name_str);
516 buf_init_from_buf(&type_def->target, to_zig_type(p, underlying_type));
517 p->type_def_list.append(type_def);
518 }
519
520 return CXChildVisit_Continue;
521 }
522 case CXCursor_StructDecl:
523 {
524 handle_struct_cursor(p, cursor, clang_getCString(name), true);
44 err = parse_h_file(parse_h, &clang_argv);
52545
526 return CXChildVisit_Continue;
527 }
528 default:
529 return CXChildVisit_Recurse;
530 }
531}
46 os_delete_file(&tmp_file_path);
53247
533static void print_indent(ParseH *p) {
534 for (int i = 0; i < p->cur_indent; i += 1) {
535 fprintf(p->f, " ");
536 }
48 return err;
49 // write to temp file, parse it, delete it
53750}
53851
539void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FILE *f) {
540 ParseH parse_h = {0};
541 ParseH *p = &parse_h;
542 p->f = f;
543 CXIndex index = clang_createIndex(1, 0);
52int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv) {
53 Context context = {0};
54 Context *c = &context;
55 c->parse_h = parse_h;
54456
54557 char *ZIG_PARSEH_CFLAGS = getenv("ZIG_PARSEH_CFLAGS");
54658 if (ZIG_PARSEH_CFLAGS) {
......@@ -558,105 +70,78 @@ void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FI
55870 buf_init_from_str(&tmp_buf, start);
55971 clang_argv->append(buf_ptr(buf_create_from_buf(&tmp_buf)));
56072 }
73
56174 clang_argv->append("-isystem");
56275 clang_argv->append(ZIG_HEADERS_DIR);
56376
77 // we don't need spell checking and it slows things down
78 clang_argv->append("-fno-spell-checking");
79 // to make the end argument work
56480 clang_argv->append(nullptr);
56581
566 enum CXErrorCode err_code;
567 if ((err_code = clang_parseTranslationUnit2(index, target_path,
568 clang_argv->items, clang_argv->length - 1,
569 NULL, 0, CXTranslationUnit_None, &p->tu)))
570 {
571 zig_panic("parse translation unit failure");
572 }
573
574
575 unsigned diag_count = clang_getNumDiagnostics(p->tu);
82 IntrusiveRefCntPtr<DiagnosticsEngine> diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
57683
577 if (diag_count > 0) {
578 for (unsigned i = 0; i < diag_count; i += 1) {
579 CXDiagnostic diagnostic = clang_getDiagnostic(p->tu, i);
580 CXSourceLocation location = clang_getDiagnosticLocation(diagnostic);
581
582 CXFile file;
583 unsigned line, column, offset;
584 clang_getSpellingLocation(location, &file, &line, &column, &offset);
585 CXString text = clang_getDiagnosticSpelling(diagnostic);
586 CXString file_name = clang_getFileName(file);
587 fprintf(stderr, "%s line %u, column %u: %s\n", clang_getCString(file_name),
588 line, column, clang_getCString(text));
589 }
590
591 exit(1);
592 }
84 std::shared_ptr<PCHContainerOperations> pch_container_ops = std::make_shared<PCHContainerOperations>();
59385
86 bool skip_function_bodies = true;
87 bool only_local_decls = true;
88 bool capture_diagnostics = true;
89 bool user_files_are_volatile = true;
90 bool allow_pch_with_compiler_errors = false;
91 const char *resources_path = ZIG_HEADERS_DIR;
92 std::unique_ptr<ASTUnit> err_unit;
93 std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
94 &clang_argv->at(0), &clang_argv->last(),
95 pch_container_ops, diags, resources_path,
96 only_local_decls, capture_diagnostics, None, true, false, TU_Complete,
97 false, false, allow_pch_with_compiler_errors, skip_function_bodies,
98 user_files_are_volatile, false, &err_unit));
59499
595 CXCursor cursor = clang_getTranslationUnitCursor(p->tu);
596 clang_visitChildren(cursor, fn_visitor, p);
597
598 for (int struct_i = 0; struct_i < p->struct_list.length; struct_i += 1) {
599 Struct *struc = p->struct_list.at(struct_i);
600 fprintf(f, "struct %s {\n", buf_ptr(&struc->name));
601 p->cur_indent += indent_size;
602 for (int field_i = 0; field_i < struc->fields.length; field_i += 1) {
603 Field *field = struc->fields.at(field_i);
604 print_indent(p);
605 fprintf(f, "%s: %s,\n", buf_ptr(&field->name), buf_ptr(field->type));
606 }
607
608 p->cur_indent -= indent_size;
609 fprintf(f, "}\n\n");
610 }
611100
612 int total_typedef_count = p->type_def_list.length;
613 for (int i = 0; i < p->incomplete_struct_list.length; i += 1) {
614 Struct *struc = p->incomplete_struct_list.at(i);
615 struc->have_def = have_struct_def(p, &struc->name);
616 total_typedef_count += (int)!struc->have_def;
101 // Early failures in LoadFromCommandLine may return with ErrUnit unset.
102 if (!ast_unit && !err_unit) {
103 return ErrorFileSystem;
617104 }
618105
619 if (total_typedef_count) {
620 for (int i = 0; i < p->incomplete_struct_list.length; i += 1) {
621 Struct *struc = p->incomplete_struct_list.at(i);
622 if (struc->have_def)
623 continue;
624
625 fprintf(f, "struct %s;\n", buf_ptr(&struc->name));
106 if (diags->getClient()->getNumErrors() > 0) {
107 if (ast_unit) {
108 err_unit = std::move(ast_unit);
626109 }
627110
628 for (int type_def_i = 0; type_def_i < p->type_def_list.length; type_def_i += 1) {
629 TypeDef *type_def = p->type_def_list.at(type_def_i);
630 fprintf(f, "type %s = %s;\n", buf_ptr(&type_def->alias), buf_ptr(&type_def->target));
111 for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
112 it_end = err_unit->stored_diag_end();
113 it != it_end; ++it)
114 {
115 switch (it->getLevel()) {
116 case DiagnosticsEngine::Ignored:
117 case DiagnosticsEngine::Note:
118 case DiagnosticsEngine::Remark:
119 case DiagnosticsEngine::Warning:
120 continue;
121 case DiagnosticsEngine::Error:
122 case DiagnosticsEngine::Fatal:
123 break;
124 }
125 StringRef msg_str_ref = it->getMessage();
126 FullSourceLoc fsl = it->getLocation();
127 FileID file_id = fsl.getManager().getFileID(fsl);
128 StringRef filename = fsl.getManager().getFilename(fsl);
129 unsigned line = fsl.getSpellingLineNumber() - 1;
130 unsigned column = fsl.getSpellingColumnNumber() - 1;
131 unsigned offset = fsl.getManager().getFileOffset(fsl);
132 const char *source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin();
133 Buf *msg = buf_create_from_str((const char *)msg_str_ref.bytes_begin());
134 Buf *path = buf_create_from_str((const char *)filename.bytes_begin());
135
136 ErrorMsg *err_msg = err_msg_create_with_offset(path, line, column, offset, source, msg);
137
138 parse_h->errors.append(err_msg);
631139 }
632140
633 fprintf(f, "\n");
141 return 0;
634142 }
635143
636 if (p->fn_list.length) {
637 fprintf(f, "extern {\n");
638 p->cur_indent += indent_size;
639 for (int fn_i = 0; fn_i < p->fn_list.length; fn_i += 1) {
640 Fn *fn = p->fn_list.at(fn_i);
641 print_indent(p);
642 fprintf(p->f, "fn %s(", buf_ptr(&fn->name));
643 for (int arg_i = 0; arg_i < fn->arg_count; arg_i += 1) {
644 Arg *arg = &fn->args[arg_i];
645 fprintf(p->f, "%s: %s", buf_ptr(&arg->name), buf_ptr(arg->type));
646 if (arg_i + 1 < fn->arg_count || fn->is_variadic) {
647 fprintf(p->f, ", ");
648 }
649 }
650 if (fn->is_variadic) {
651 fprintf(p->f, "...");
652 }
653 fprintf(p->f, ")");
654 if (fn->return_type) {
655 fprintf(p->f, " -> %s", buf_ptr(fn->return_type));
656 }
657 fprintf(p->f, ";\n");
658 }
659 p->cur_indent -= indent_size;
660 fprintf(f, "}\n");
661 }
144 ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
145
146 return 0;
662147}
src/parseh.hpp+3-4
......@@ -9,10 +9,9 @@
99#ifndef ZIG_PARSEH_HPP
1010#define ZIG_PARSEH_HPP
1111
12#include "buffer.hpp"
12#include "all_types.hpp"
1313
14#include <stdio.h>
15
16void parse_h_file(const char *target_path, ZigList<const char *> *clang_argv, FILE *f);
14int parse_h_file(ParseH *parse_h, ZigList<const char *> *clang_argv);
15int parse_h_buf(ParseH *parse_h, Buf *buf, const char *libc_include_path);
1716
1817#endif
src/parser.cpp+9-20
......@@ -488,23 +488,16 @@ __attribute__ ((noreturn))
488488static void ast_asm_error(ParseContext *pc, AstNode *node, int offset, const char *format, ...) {
489489 assert(node->type == NodeTypeAsmExpr);
490490
491 ErrorMsg *err = allocate<ErrorMsg>(1);
492491
493492 SrcPos pos = node->data.asm_expr.offset_map.at(offset);
494493
495 err->line_start = pos.line;
496 err->column_start = pos.column;
497 err->line_end = -1;
498 err->column_end = -1;
499
500494 va_list ap;
501495 va_start(ap, format);
502 err->msg = buf_vprintf(format, ap);
496 Buf *msg = buf_vprintf(format, ap);
503497 va_end(ap);
504498
505 err->path = pc->owner->path;
506 err->source = pc->owner->source_code;
507 err->line_offsets = pc->owner->line_offsets;
499 ErrorMsg *err = err_msg_create_with_line(pc->owner->path, pos.line, pos.column,
500 pc->owner->source_code, pc->owner->line_offsets, msg);
508501
509502 print_err_msg(err, pc->err_color);
510503 exit(EXIT_FAILURE);
......@@ -513,20 +506,16 @@ static void ast_asm_error(ParseContext *pc, AstNode *node, int offset, const cha
513506__attribute__ ((format (printf, 3, 4)))
514507__attribute__ ((noreturn))
515508static void ast_error(ParseContext *pc, Token *token, const char *format, ...) {
516 ErrorMsg *err = allocate<ErrorMsg>(1);
517 err->line_start = token->start_line;
518 err->column_start = token->start_column;
519 err->line_end = -1;
520 err->column_end = -1;
521
522509 va_list ap;
523510 va_start(ap, format);
524 err->msg = buf_vprintf(format, ap);
511 Buf *msg = buf_vprintf(format, ap);
525512 va_end(ap);
526513
527 err->path = pc->owner->path;
528 err->source = pc->owner->source_code;
529 err->line_offsets = pc->owner->line_offsets;
514
515 ErrorMsg *err = err_msg_create_with_line(pc->owner->path, token->start_line, token->start_column,
516 pc->owner->source_code, pc->owner->line_offsets, msg);
517 err->line_start = token->start_line;
518 err->column_start = token->start_column;
530519
531520 print_err_msg(err, pc->err_color);
532521 exit(EXIT_FAILURE);
test/run_tests.cpp+7
......@@ -1673,6 +1673,13 @@ fn f(s: []u8) -> []u8 {
16731673}
16741674 )SOURCE", 1, ".tmp_source.zig:3:5: error: string concatenation requires constant expression");
16751675
1676 add_compile_fail_case("c_import with bogus include", R"SOURCE(
1677c_import {
1678 @c_include("bogus.h");
1679}
1680 )SOURCE", 2, ".tmp_source.zig:2:1: error: C import failed",
1681 ".h:1:10: error: 'bogus.h' file not found");
1682
16761683}
16771684
16781685static void print_compiler_invocation(TestCase *test_case) {