Commit 95619ecb8c

LemonBoy <thatlemon@gmail.com>
2020-01-11 19:59:01
Stop dropping errors from clang
* Refactor the error-writing code to be more compact and flexible
1 parent 9cc7fb6
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);
     }
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 {
+    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) {
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);
+                }
             }
         }