Identify current toolchain on error

Currently errors from GN identify the source location that failed, but
not the toolchain. This can be confusing, and adding a

  print(current_toolchain)

is often helpful when debugging these errors. This patch changes GN to
include the toolchain in the error message whenever there's an error
in a non-default toolchain.

This produces output like the following:

  ERROR at //subdir/BUILD.gn:3:1 (//:toolchain): Assertion failed.
  assert(only_true_in_default_toolchain)
  ^-----
  See //BUILD.gn:51:14: which caused the file to be included.
      deps = [ "subdir" ]
               ^-------

Bug: 184

Change-Id: I8463f04cf94242c4f7c518d4840ae8f586b4e4fa
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/9640
Commit-Queue: Brett Wilson <brettw@chromium.org>
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/src/gn/err.cc b/src/gn/err.cc
index 5eaba67..301ee8d 100644
--- a/src/gn/err.cc
+++ b/src/gn/err.cc
@@ -168,9 +168,17 @@
       loc_str.insert(0, "See ");
     else
       loc_str.insert(0, "at ");
-    loc_str.append(": ");
+    if (!toolchain_label_.is_null())
+      loc_str += " ";
   }
-  OutputString(loc_str + message_ + "\n");
+  std::string toolchain_str;
+  if (!toolchain_label_.is_null()) {
+    toolchain_str += "(" + toolchain_label_.GetUserVisibleName(false) + ")";
+  }
+  std::string colon;
+  if (!loc_str.empty() || !toolchain_str.empty())
+    colon = ": ";
+  OutputString(loc_str + toolchain_str + colon + message_ + "\n");
 
   // Quoted line.
   if (input_file) {
diff --git a/src/gn/err.h b/src/gn/err.h
index da05f2e..6bd2f02 100644
--- a/src/gn/err.h
+++ b/src/gn/err.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "gn/label.h"
 #include "gn/location.h"
 #include "gn/token.h"
 
@@ -66,6 +67,10 @@
   void AppendRange(const LocationRange& range) { ranges_.push_back(range); }
   const RangeList& ranges() const { return ranges_; }
 
+  void set_toolchain_label(const Label& toolchain_label) {
+    toolchain_label_ = toolchain_label;
+  }
+
   void AppendSubErr(const Err& err);
 
   void PrintToStdout() const;
@@ -87,6 +92,7 @@
 
   bool has_error_;
   Location location_;
+  Label toolchain_label_;
 
   std::vector<LocationRange> ranges_;
 
diff --git a/src/gn/loader.cc b/src/gn/loader.cc
index 547e919..c615170 100644
--- a/src/gn/loader.cc
+++ b/src/gn/loader.cc
@@ -270,6 +270,10 @@
   if (err.has_error()) {
     if (!origin.is_null())
       err.AppendSubErr(Err(origin, "which caused the file to be included."));
+
+    if (!settings->is_default())
+      err.set_toolchain_label(settings->toolchain_label());
+
     g_scheduler->FailWithError(err);
   }
 
@@ -330,8 +334,12 @@
 
   trace.Done();
 
-  if (err.has_error())
+  if (err.has_error()) {
+    if (!settings->is_default())
+      err.set_toolchain_label(settings->toolchain_label());
+
     g_scheduler->FailWithError(err);
+  }
 
   base_config->ClearProcessingBuildConfig();
   if (settings->is_default()) {