From 95619ecb8ccf8a5405b901e02cfbb389a8f95aba Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Sat, 11 Jan 2020 19:59:01 +0100 Subject: [PATCH] Stop dropping errors from clang * Refactor the error-writing code to be more compact and flexible --- src/codegen.cpp | 15 ++++----- src/errmsg.cpp | 78 +++++++++++++++++++++++++---------------------- src/zig_clang.cpp | 40 +++++++++++++++--------- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 84f3251c9..fd36e15f8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -9242,15 +9242,12 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { for (size_t i = 0; i < errors_len; i += 1) { Stage2ErrorMsg *clang_err = &errors_ptr[i]; - // Clang can emit "too many errors, stopping now", in which case `source` and `filename_ptr` are null - if (clang_err->source && clang_err->filename_ptr) { - ErrorMsg *err_msg = err_msg_create_with_offset( - clang_err->filename_ptr ? - buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : buf_alloc(), - clang_err->line, clang_err->column, clang_err->offset, clang_err->source, - buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); - print_err_msg(err_msg, g->err_color); - } + ErrorMsg *err_msg = err_msg_create_with_offset( + clang_err->filename_ptr ? + buf_create_from_mem(clang_err->filename_ptr, clang_err->filename_len) : nullptr, + clang_err->line, clang_err->column, clang_err->offset, clang_err->source, + buf_create_from_mem(clang_err->msg_ptr, clang_err->msg_len)); + print_err_msg(err_msg, g->err_color); } exit(1); } diff --git a/src/errmsg.cpp b/src/errmsg.cpp index edbfd858a..16d1dcd52 100644 --- a/src/errmsg.cpp +++ b/src/errmsg.cpp @@ -16,51 +16,49 @@ enum ErrType { }; static void print_err_msg_type(ErrorMsg *err, ErrColor color, ErrType err_type) { - const char *path = buf_ptr(err->path); - size_t line = err->line_start + 1; - size_t col = err->column_start + 1; - const char *text = buf_ptr(err->msg); - bool is_tty = os_stderr_tty(); - if (color == ErrColorOn || (color == ErrColorAuto && is_tty)) { - if (err_type == ErrTypeError) { - os_stderr_set_color(TermColorBold); - fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); - os_stderr_set_color(TermColorRed); - fprintf(stderr, "error:"); - os_stderr_set_color(TermColorBold); - fprintf(stderr, " %s", text); - os_stderr_set_color(TermColorReset); - fprintf(stderr, "\n"); - } else if (err_type == ErrTypeNote) { - os_stderr_set_color(TermColorBold); - fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", path, line, col); - os_stderr_set_color(TermColorCyan); - fprintf(stderr, "note:"); - os_stderr_set_color(TermColorBold); - fprintf(stderr, " %s", text); - os_stderr_set_color(TermColorReset); - fprintf(stderr, "\n"); - } else { - zig_unreachable(); - } + bool use_colors = color == ErrColorOn || (color == ErrColorAuto && is_tty); + // Show the error location, if available + if (err->path != nullptr) { + const size_t line = err->line_start + 1; + const size_t col = err->column_start + 1; + + if (use_colors) os_stderr_set_color(TermColorBold); + fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": ", buf_ptr(err->path), line, col); + } + + // Write out the error type + switch (err_type) { + case ErrTypeError: + if (use_colors) os_stderr_set_color(TermColorRed); + fprintf(stderr, "error: "); + break; + case ErrTypeNote: + if (use_colors) os_stderr_set_color(TermColorCyan); + fprintf(stderr, "note: "); + break; + default: + zig_unreachable(); + } + + // Write out the error message + if (use_colors) os_stderr_set_color(TermColorBold); + fputs(buf_ptr(err->msg), stderr); + if (use_colors) os_stderr_set_color(TermColorReset); + fputc('\n', stderr); + + if (buf_len(&err->line_buf) != 0){ + // Show the referenced line fprintf(stderr, "%s\n", buf_ptr(&err->line_buf)); for (size_t i = 0; i < err->column_start; i += 1) { fprintf(stderr, " "); } - os_stderr_set_color(TermColorGreen); + // Draw the caret + if (use_colors) os_stderr_set_color(TermColorGreen); fprintf(stderr, "^"); - os_stderr_set_color(TermColorReset); + if (use_colors) os_stderr_set_color(TermColorReset); fprintf(stderr, "\n"); - } else { - if (err_type == ErrTypeError) { - fprintf(stderr, "%s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": error: %s\n", path, line, col, text); - } else if (err_type == ErrTypeNote) { - fprintf(stderr, " %s:%" ZIG_PRI_usize ":%" ZIG_PRI_usize ": note: %s\n", path, line, col, text); - } else { - zig_unreachable(); - } } for (size_t i = 0; i < err->notes.length; i += 1) { @@ -86,6 +84,12 @@ ErrorMsg *err_msg_create_with_offset(Buf *path, size_t line, size_t column, size err_msg->column_start = column; err_msg->msg = msg; + if (source == nullptr) { + // Must initialize the buffer anyway + buf_init_from_str(&err_msg->line_buf, ""); + return err_msg; + } + size_t line_start_offset = offset; for (;;) { if (line_start_offset == 0) { diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index dd003a4f9..0afa2d28a 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -2111,28 +2111,40 @@ ZigClangASTUnit *ZigClangLoadFromCommandLine(const char **args_begin, const char llvm::StringRef msg_str_ref = it->getMessage(); Stage2ErrorMsg *msg = errors.add_one(); + memset(msg, 0, sizeof(*msg)); + msg->msg_ptr = (const char *)msg_str_ref.bytes_begin(); msg->msg_len = msg_str_ref.size(); clang::FullSourceLoc fsl = it->getLocation(); + // Expand the location if possible + fsl = fsl.getFileLoc(); + + // The only known way to obtain a Loc without a manager associated + // to it is if you have a lot of errors clang emits "too many errors + // emitted, stopping now" if (fsl.hasManager()) { - clang::FileID file_id = fsl.getFileID(); - clang::StringRef filename = fsl.getManager().getFilename(fsl); - if (filename.empty()) { - msg->filename_ptr = nullptr; - } else { + const clang::SourceManager &SM = fsl.getManager(); + + clang::PresumedLoc presumed_loc = SM.getPresumedLoc(fsl); + assert(!presumed_loc.isInvalid()); + + msg->line = presumed_loc.getLine() - 1; + msg->column = presumed_loc.getColumn() - 1; + + clang::StringRef filename = presumed_loc.getFilename(); + if (!filename.empty()) { msg->filename_ptr = (const char *)filename.bytes_begin(); msg->filename_len = filename.size(); } - msg->source = (const char *)fsl.getManager().getBufferData(file_id).bytes_begin(); - msg->line = fsl.getSpellingLineNumber() - 1; - msg->column = fsl.getSpellingColumnNumber() - 1; - msg->offset = fsl.getManager().getFileOffset(fsl); - } else { - // The only known way this gets triggered right now is if you have a lot of errors - // clang emits "too many errors emitted, stopping now" - msg->filename_ptr = nullptr; - msg->source = nullptr; + + bool invalid; + clang::StringRef buffer = fsl.getBufferData(&invalid); + + if (!invalid) { + msg->source = (const char *)buffer.bytes_begin(); + msg->offset = SM.getFileOffset(fsl); + } } }