[lld] r316624 - [lld] unified COFF and ELF error handling on new Common/ErrorHandler

Bob Haarman via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 25 15:28:39 PDT 2017


Author: inglorion
Date: Wed Oct 25 15:28:38 2017
New Revision: 316624

URL: http://llvm.org/viewvc/llvm-project?rev=316624&view=rev
Log:
[lld] unified COFF and ELF error handling on new Common/ErrorHandler

Summary:
The COFF linker and the ELF linker have long had similar but separate
Error.h and Error.cpp files to implement error handling. This change
introduces new error handling code in Common/ErrorHandler.h, changes the
COFF and ELF linkers to use it, and removes the old, separate
implementations.

Reviewers: ruiu

Reviewed By: ruiu

Subscribers: smeenai, jyknight, emaste, sdardis, nemanjai, nhaehnle, mgorny, javed.absar, kbarton, fedor.sergeev, llvm-commits

Differential Revision: https://reviews.llvm.org/D39259

Added:
    lld/trunk/Common/ErrorHandler.cpp
    lld/trunk/include/lld/Common/ErrorHandler.h
Removed:
    lld/trunk/COFF/Error.cpp
    lld/trunk/COFF/Error.h
    lld/trunk/ELF/Error.cpp
    lld/trunk/ELF/Error.h
Modified:
    lld/trunk/COFF/CMakeLists.txt
    lld/trunk/COFF/Chunks.cpp
    lld/trunk/COFF/Config.h
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/DriverUtils.cpp
    lld/trunk/COFF/ICF.cpp
    lld/trunk/COFF/InputFiles.cpp
    lld/trunk/COFF/LTO.cpp
    lld/trunk/COFF/MapFile.cpp
    lld/trunk/COFF/MinGW.cpp
    lld/trunk/COFF/PDB.cpp
    lld/trunk/COFF/SymbolTable.cpp
    lld/trunk/COFF/Symbols.cpp
    lld/trunk/COFF/Writer.cpp
    lld/trunk/Common/CMakeLists.txt
    lld/trunk/ELF/Arch/AArch64.cpp
    lld/trunk/ELF/Arch/AMDGPU.cpp
    lld/trunk/ELF/Arch/ARM.cpp
    lld/trunk/ELF/Arch/AVR.cpp
    lld/trunk/ELF/Arch/Mips.cpp
    lld/trunk/ELF/Arch/MipsArchTree.cpp
    lld/trunk/ELF/Arch/PPC.cpp
    lld/trunk/ELF/Arch/PPC64.cpp
    lld/trunk/ELF/Arch/SPARCV9.cpp
    lld/trunk/ELF/Arch/X86.cpp
    lld/trunk/ELF/Arch/X86_64.cpp
    lld/trunk/ELF/CMakeLists.txt
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/DriverUtils.cpp
    lld/trunk/ELF/EhFrame.cpp
    lld/trunk/ELF/InputFiles.cpp
    lld/trunk/ELF/InputFiles.h
    lld/trunk/ELF/InputSection.cpp
    lld/trunk/ELF/LTO.cpp
    lld/trunk/ELF/Relocations.cpp
    lld/trunk/ELF/ScriptLexer.cpp
    lld/trunk/ELF/ScriptParser.cpp
    lld/trunk/ELF/Strings.cpp
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/Symbols.cpp
    lld/trunk/ELF/SyntheticSections.cpp
    lld/trunk/ELF/Target.cpp
    lld/trunk/ELF/Target.h
    lld/trunk/ELF/Thunks.cpp
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/COFF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/CMakeLists.txt?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/CMakeLists.txt (original)
+++ lld/trunk/COFF/CMakeLists.txt Wed Oct 25 15:28:38 2017
@@ -11,7 +11,6 @@ add_lld_library(lldCOFF
   DLL.cpp
   Driver.cpp
   DriverUtils.cpp
-  Error.cpp
   ICF.cpp
   InputFiles.cpp
   LTO.cpp

Modified: lld/trunk/COFF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Chunks.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/Chunks.cpp (original)
+++ lld/trunk/COFF/Chunks.cpp Wed Oct 25 15:28:38 2017
@@ -8,10 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Chunks.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "Writer.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/Object/COFF.h"

Modified: lld/trunk/COFF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Config.h?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/Config.h (original)
+++ lld/trunk/COFF/Config.h Wed Oct 25 15:28:38 2017
@@ -84,13 +84,10 @@ struct Configuration {
   bool NoEntry = false;
   std::string OutputFile;
   std::string ImportName;
-  bool ColorDiagnostics;
   bool DoGC = true;
   bool DoICF = true;
-  uint64_t ErrorLimit = 20;
   bool Relocatable = true;
   bool Force = false;
-  bool FatalWarnings = false;
   bool Debug = false;
   bool WriteSymtab = true;
   unsigned DebugTypes = static_cast<unsigned>(DebugType::None);

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Wed Oct 25 15:28:38 2017
@@ -9,7 +9,6 @@
 
 #include "Driver.h"
 #include "Config.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "Memory.h"
 #include "MinGW.h"
@@ -17,6 +16,7 @@
 #include "Symbols.h"
 #include "Writer.h"
 #include "lld/Common/Driver.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Version.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -55,12 +55,14 @@ StringSaver Saver{BAlloc};
 std::vector<SpecificAllocBase *> SpecificAllocBase::Instances;
 
 bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {
-  ErrorCount = 0;
-  ErrorOS = &Diag;
-
+  errorHandler().LogName = Args[0];
+  errorHandler().ErrorOS = &Diag;
+  errorHandler().ColorDiagnostics = Diag.has_colors();
+  errorHandler().ErrorLimitExceededMsg =
+      "too many errors emitted, stopping now"
+      " (use /ERRORLIMIT:0 to see all errors)";
   Config = make<Configuration>();
   Config->Argv = {Args.begin(), Args.end()};
-  Config->ColorDiagnostics = ErrorOS->has_colors();
   Config->CanExitEarly = CanExitEarly;
 
   Symtab = make<SymbolTable>();
@@ -70,10 +72,10 @@ bool link(ArrayRef<const char *> Args, b
 
   // Call exit() if we can to avoid calling destructors.
   if (CanExitEarly)
-    exitLld(ErrorCount ? 1 : 0);
+    exitLld(errorCount() ? 1 : 0);
 
   freeArena();
-  return !ErrorCount;
+  return !errorCount();
 }
 
 // Drop directory components and replace extension with ".exe" or ".dll".
@@ -212,8 +214,8 @@ void LinkerDriver::enqueueArchiveMember(
   enqueueTask([=]() {
     auto MBOrErr = Future->get();
     if (MBOrErr.second)
-      fatal(MBOrErr.second,
-            "could not get the buffer for the member defining " + SymName);
+      fatal("could not get the buffer for the member defining " + SymName +
+            ": " + MBOrErr.second.message());
     Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,
                              ParentName);
   });
@@ -619,7 +621,7 @@ filterBitcodeFiles(StringRef Path, std::
   SmallString<128> S;
   if (auto EC = sys::fs::createTemporaryFile("lld-" + sys::path::stem(Path),
                                              ".lib", S))
-    fatal(EC, "cannot create a temporary file");
+    fatal("cannot create a temporary file: " + EC.message());
   std::string Temp = S.str();
   TemporaryFiles.push_back(Temp);
 
@@ -648,7 +650,7 @@ void LinkerDriver::invokeMSVC(opt::Input
     int Fd;
     if (auto EC = sys::fs::createTemporaryFile(
             "lld-" + sys::path::filename(Obj->ParentName), ".obj", Fd, S))
-      fatal(EC, "cannot create a temporary file");
+      fatal("cannot create a temporary file: " + EC.message());
     raw_fd_ostream OS(Fd, /*shouldClose*/ true);
     OS << Obj->MB.getBuffer();
     Temps.push_back(S.str());
@@ -736,7 +738,7 @@ void LinkerDriver::link(ArrayRef<const c
     StringRef S = Arg->getValue();
     if (S.getAsInteger(10, N))
       error(Arg->getSpelling() + " number expected, but got " + S);
-    Config->ErrorLimit = N;
+    errorHandler().ErrorLimit = N;
   }
 
   // Handle /help
@@ -792,6 +794,7 @@ void LinkerDriver::link(ArrayRef<const c
   // Handle /verbose
   if (Args.hasArg(OPT_verbose))
     Config->Verbose = true;
+  errorHandler().Verbose = Config->Verbose;
 
   // Handle /force or /force:unresolved
   if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved))
@@ -1010,7 +1013,7 @@ void LinkerDriver::link(ArrayRef<const c
 
   Config->MapFile = getMapFile(Args);
 
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   bool WholeArchiveFlag = Args.hasArg(OPT_wholearchive_flag);
@@ -1191,7 +1194,7 @@ void LinkerDriver::link(ArrayRef<const c
       addUndefined(mangle("_load_config_used"));
   } while (run());
 
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // If /msvclto is given, we use the MSVC linker to link LTO output files.
@@ -1208,7 +1211,7 @@ void LinkerDriver::link(ArrayRef<const c
 
   // Make sure we have resolved all symbols.
   Symtab->reportRemainingUndefines();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // Windows specific -- if no /subsystem is given, we need to infer
@@ -1224,7 +1227,7 @@ void LinkerDriver::link(ArrayRef<const c
     for (ObjFile *File : ObjFile::Instances)
       if (!File->SEHCompat)
         error("/safeseh: " + File->getName() + " is not compatible with SEH");
-    if (ErrorCount)
+    if (errorCount())
       return;
   }
 

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Wed Oct 25 15:28:38 2017
@@ -15,9 +15,9 @@
 
 #include "Config.h"
 #include "Driver.h"
-#include "Error.h"
 #include "Memory.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/BinaryFormat/COFF.h"
@@ -57,7 +57,7 @@ public:
   void run() {
     ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog);
     if (auto EC = ExeOrErr.getError())
-      fatal(EC, "unable to find " + Prog + " in PATH");
+      fatal("unable to find " + Prog + " in PATH: " + EC.message());
     StringRef Exe = Saver.save(*ExeOrErr);
     Args.insert(Args.begin(), Exe);
 
@@ -288,14 +288,14 @@ public:
   TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") {
     SmallString<128> S;
     if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S))
-      fatal(EC, "cannot create a temporary file");
+      fatal("cannot create a temporary file: " + EC.message());
     Path = S.str();
 
     if (!Contents.empty()) {
       std::error_code EC;
       raw_fd_ostream OS(Path, EC, sys::fs::F_None);
       if (EC)
-        fatal(EC, "failed to open " + Path);
+        fatal("failed to open " + Path + ": " + EC.message());
       OS << Contents;
     }
   }
@@ -363,13 +363,15 @@ static std::string createManifestXmlWith
 
   windows_manifest::WindowsManifestMerger Merger;
   if (auto E = Merger.merge(*DefaultXmlCopy.get()))
-    fatal(E, "internal manifest tool failed on default xml");
+    fatal("internal manifest tool failed on default xml: " +
+          toString(std::move(E)));
 
   for (StringRef Filename : Config->ManifestInput) {
     std::unique_ptr<MemoryBuffer> Manifest =
         check(MemoryBuffer::getFile(Filename));
     if (auto E = Merger.merge(*Manifest.get()))
-      fatal(E, "internal manifest tool failed on file " + Filename);
+      fatal("internal manifest tool failed on file " + Filename + ": " +
+            toString(std::move(E)));
   }
 
   return Merger.getMergedManifest().get()->getBuffer();
@@ -381,7 +383,7 @@ static std::string createManifestXmlWith
   std::error_code EC;
   raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text);
   if (EC)
-    fatal(EC, "failed to open " + Default.Path);
+    fatal("failed to open " + Default.Path + ": " + EC.message());
   OS << DefaultXml;
   OS.close();
 
@@ -482,7 +484,7 @@ void createSideBySideManifest() {
   std::error_code EC;
   raw_fd_ostream Out(Path, EC, sys::fs::F_Text);
   if (EC)
-    fatal(EC, "failed to create manifest");
+    fatal("failed to create manifest: " + EC.message());
   Out << createManifestXml();
 }
 
@@ -649,13 +651,13 @@ MemoryBufferRef convertResToCOFF(const s
     if (!RF)
       fatal("cannot compile non-resource file as resource");
     if (auto EC = Parser.parse(RF))
-      fatal(EC, "failed to parse .res file");
+      fatal("failed to parse .res file: " + toString(std::move(EC)));
   }
 
   Expected<std::unique_ptr<MemoryBuffer>> E =
       llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);
   if (!E)
-    fatal(errorToErrorCode(E.takeError()), "failed to write .res to COFF");
+    fatal("failed to write .res to COFF: " + toString(E.takeError()));
 
   MemoryBufferRef MBRef = **E;
   make<std::unique_ptr<MemoryBuffer>>(std::move(*E)); // take ownership
@@ -739,7 +741,7 @@ opt::InputArgList ArgParser::parse(Array
   }
 
   // Handle /WX early since it converts missing argument warnings to errors.
-  Config->FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
+  errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);
 
   if (MissingCount)
     fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");

Removed: lld/trunk/COFF/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Error.cpp?rev=316623&view=auto
==============================================================================
--- lld/trunk/COFF/Error.cpp (original)
+++ lld/trunk/COFF/Error.cpp (removed)
@@ -1,120 +0,0 @@
-//===- Error.cpp ----------------------------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "Config.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/raw_ostream.h"
-#include <mutex>
-
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#endif
-
-using namespace llvm;
-
-namespace lld {
-// The functions defined in this file can be called from multiple threads,
-// but outs() or errs() are not thread-safe. We protect them using a mutex.
-static std::mutex Mu;
-
-namespace coff {
-uint64_t ErrorCount;
-raw_ostream *ErrorOS;
-
-LLVM_ATTRIBUTE_NORETURN void exitLld(int Val) {
-  // Dealloc/destroy ManagedStatic variables before calling
-  // _exit(). In a non-LTO build, this is a nop. In an LTO
-  // build allows us to get the output of -time-passes.
-  llvm_shutdown();
-
-  outs().flush();
-  errs().flush();
-  _exit(Val);
-}
-
-static void print(StringRef S, raw_ostream::Colors C) {
-  *ErrorOS << Config->Argv[0] << ": ";
-  if (Config->ColorDiagnostics) {
-    ErrorOS->changeColor(C, true);
-    *ErrorOS << S;
-    ErrorOS->resetColor();
-  } else {
-    *ErrorOS << S;
-  }
-}
-
-void log(const Twine &Msg) {
-  if (Config->Verbose) {
-    std::lock_guard<std::mutex> Lock(Mu);
-    outs() << Config->Argv[0] << ": " << Msg << "\n";
-    outs().flush();
-  }
-}
-
-void message(const Twine &Msg) {
-  std::lock_guard<std::mutex> Lock(Mu);
-  outs() << Msg << "\n";
-  outs().flush();
-}
-
-void error(const Twine &Msg) {
-  std::lock_guard<std::mutex> Lock(Mu);
-
-  if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
-    print("error: ", raw_ostream::RED);
-    *ErrorOS << Msg << "\n";
-  } else if (ErrorCount == Config->ErrorLimit) {
-    print("error: ", raw_ostream::RED);
-    *ErrorOS << "too many errors emitted, stopping now"
-             << " (use /ERRORLIMIT:0 to see all errors)\n";
-    if (Config->CanExitEarly)
-      exitLld(1);
-  }
-
-  ++ErrorCount;
-}
-
-void fatal(const Twine &Msg) {
-  if (Config->ColorDiagnostics) {
-    errs().changeColor(raw_ostream::RED, /*bold=*/true);
-    errs() << "error: ";
-    errs().resetColor();
-  } else {
-    errs() << "error: ";
-  }
-  errs() << Msg << "\n";
-  exitLld(1);
-}
-
-void fatal(std::error_code EC, const Twine &Msg) {
-  fatal(Msg + ": " + EC.message());
-}
-
-void fatal(llvm::Error &Err, const Twine &Msg) {
-  fatal(errorToErrorCode(std::move(Err)), Msg);
-}
-
-void warn(const Twine &Msg) {
-  if (Config->FatalWarnings) {
-    error(Msg);
-    return;
-  }
-
-  std::lock_guard<std::mutex> Lock(Mu);
-  print("warning: ", raw_ostream::MAGENTA);
-  *ErrorOS << Msg << "\n";
-}
-
-} // namespace coff
-} // namespace lld

Removed: lld/trunk/COFF/Error.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Error.h?rev=316623&view=auto
==============================================================================
--- lld/trunk/COFF/Error.h (original)
+++ lld/trunk/COFF/Error.h (removed)
@@ -1,64 +0,0 @@
-//===- Error.h --------------------------------------------------*- C++ -*-===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_COFF_ERROR_H
-#define LLD_COFF_ERROR_H
-
-#include "lld/Common/LLVM.h"
-#include "llvm/Support/Error.h"
-
-namespace lld {
-namespace coff {
-
-extern uint64_t ErrorCount;
-extern llvm::raw_ostream *ErrorOS;
-
-void log(const Twine &Msg);
-void message(const Twine &Msg);
-void warn(const Twine &Msg);
-void error(const Twine &Msg);
-LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
-LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
-LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
-
-LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
-
-template <class T> T check(ErrorOr<T> V, const Twine &Prefix) {
-  if (auto EC = V.getError())
-    fatal(EC, Prefix);
-  return std::move(*V);
-}
-
-template <class T> T check(Expected<T> E, const Twine &Prefix) {
-  if (llvm::Error Err = E.takeError())
-    fatal(Err, Prefix);
-  return std::move(*E);
-}
-
-template <class T> T check(ErrorOr<T> EO) {
-  if (!EO)
-    fatal(EO.getError().message());
-  return std::move(*EO);
-}
-
-template <class T> T check(Expected<T> E) {
-  if (!E) {
-    std::string Buf;
-    llvm::raw_string_ostream OS(Buf);
-    logAllUnhandledErrors(E.takeError(), OS, "");
-    OS.flush();
-    fatal(Buf);
-  }
-  return std::move(*E);
-}
-
-} // namespace coff
-} // namespace lld
-
-#endif

Modified: lld/trunk/COFF/ICF.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/ICF.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/ICF.cpp (original)
+++ lld/trunk/COFF/ICF.cpp Wed Oct 25 15:28:38 2017
@@ -19,8 +19,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "Chunks.h"
-#include "Error.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/Hashing.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Parallel.h"

Modified: lld/trunk/COFF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/InputFiles.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/InputFiles.cpp (original)
+++ lld/trunk/COFF/InputFiles.cpp Wed Oct 25 15:28:38 2017
@@ -11,10 +11,10 @@
 #include "Chunks.h"
 #include "Config.h"
 #include "Driver.h"
-#include "Error.h"
 #include "Memory.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm-c/lto.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Triple.h"
@@ -127,9 +127,9 @@ void ObjFile::initializeChunks() {
     const coff_section *Sec;
     StringRef Name;
     if (auto EC = COFFObj->getSection(I, Sec))
-      fatal(EC, "getSection failed: #" + Twine(I));
+      fatal("getSection failed: #" + Twine(I) + ": " + EC.message());
     if (auto EC = COFFObj->getSectionName(Sec, Name))
-      fatal(EC, "getSectionName failed: #" + Twine(I));
+      fatal("getSectionName failed: #" + Twine(I) + ": " + EC.message());
     if (Name == ".sxdata") {
       SXData = Sec;
       continue;
@@ -179,7 +179,6 @@ void ObjFile::initializeSymbols() {
   int32_t LastSectionNumber = 0;
 
   for (uint32_t I = 0; I < NumSymbols; ++I) {
-    // Get a COFFSymbolRef object.
     COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
 
     const void *AuxP = nullptr;

Modified: lld/trunk/COFF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/LTO.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/LTO.cpp (original)
+++ lld/trunk/COFF/LTO.cpp Wed Oct 25 15:28:38 2017
@@ -9,9 +9,9 @@
 
 #include "LTO.h"
 #include "Config.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"

Modified: lld/trunk/COFF/MapFile.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MapFile.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/MapFile.cpp (original)
+++ lld/trunk/COFF/MapFile.cpp Wed Oct 25 15:28:38 2017
@@ -20,11 +20,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "MapFile.h"
-#include "Error.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "Writer.h"
 
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Parallel.h"
 #include "llvm/Support/raw_ostream.h"
 

Modified: lld/trunk/COFF/MinGW.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/MinGW.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/MinGW.cpp (original)
+++ lld/trunk/COFF/MinGW.cpp Wed Oct 25 15:28:38 2017
@@ -8,7 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "MinGW.h"
-#include "Error.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/raw_ostream.h"

Modified: lld/trunk/COFF/PDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/PDB.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/PDB.cpp (original)
+++ lld/trunk/COFF/PDB.cpp Wed Oct 25 15:28:38 2017
@@ -11,10 +11,10 @@
 #include "Chunks.h"
 #include "Config.h"
 #include "Driver.h"
-#include "Error.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "Writer.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
 #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
@@ -188,7 +188,7 @@ maybeReadTypeServerRecord(CVTypeArray &T
     return None;
   TypeServer2Record TS;
   if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS))
-    fatal(EC, "error reading type server record");
+    fatal("error reading type server record: " + toString(std::move(EC)));
   return std::move(TS);
 }
 
@@ -202,7 +202,7 @@ const CVIndexMap &PDBLinker::mergeDebugT
   CVTypeArray Types;
   BinaryStreamReader Reader(Stream);
   if (auto EC = Reader.readArray(Types, Reader.getLength()))
-    fatal(EC, "Reader::readArray failed");
+    fatal("Reader::readArray failed: " + toString(std::move(EC)));
 
   // Look through type servers. If we've already seen this type server, don't
   // merge any type information.
@@ -213,7 +213,8 @@ const CVIndexMap &PDBLinker::mergeDebugT
   // ObjectIndexMap.
   if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
                                        ObjectIndexMap.TPIMap, Types))
-    fatal(Err, "codeview::mergeTypeAndIdRecords failed");
+    fatal("codeview::mergeTypeAndIdRecords failed: " +
+          toString(std::move(Err)));
   return ObjectIndexMap;
 }
 
@@ -275,23 +276,23 @@ const CVIndexMap &PDBLinker::maybeMergeT
     ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
   }
   if (auto E = ExpectedSession.takeError())
-    fatal(E, "Type server PDB was not found");
+    fatal("Type server PDB was not found: " + toString(std::move(E)));
 
   // Merge TPI first, because the IPI stream will reference type indices.
   auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
   if (auto E = ExpectedTpi.takeError())
-    fatal(E, "Type server does not have TPI stream");
+    fatal("Type server does not have TPI stream: " + toString(std::move(E)));
   if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
                                   ExpectedTpi->typeArray()))
-    fatal(Err, "codeview::mergeTypeRecords failed");
+    fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
 
   // Merge IPI.
   auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
   if (auto E = ExpectedIpi.takeError())
-    fatal(E, "Type server does not have TPI stream");
+    fatal("Type server does not have TPI stream: " + toString(std::move(E)));
   if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
                                 ExpectedIpi->typeArray()))
-    fatal(Err, "codeview::mergeIdRecords failed");
+    fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
 
   return IndexMap;
 }

Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Wed Oct 25 15:28:38 2017
@@ -10,10 +10,10 @@
 #include "SymbolTable.h"
 #include "Config.h"
 #include "Driver.h"
-#include "Error.h"
 #include "LTO.h"
 #include "Memory.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"

Modified: lld/trunk/COFF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Symbols.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/Symbols.cpp (original)
+++ lld/trunk/COFF/Symbols.cpp Wed Oct 25 15:28:38 2017
@@ -8,10 +8,10 @@
 //===----------------------------------------------------------------------===//
 
 #include "Symbols.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "Memory.h"
 #include "Strings.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"

Modified: lld/trunk/COFF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Writer.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/COFF/Writer.cpp (original)
+++ lld/trunk/COFF/Writer.cpp Wed Oct 25 15:28:38 2017
@@ -10,13 +10,13 @@
 #include "Writer.h"
 #include "Config.h"
 #include "DLL.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "MapFile.h"
 #include "Memory.h"
 #include "PDB.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringSwitch.h"
@@ -316,7 +316,7 @@ void Writer::run() {
   writeMapFile(OutputSections);
 
   if (auto EC = Buffer->commit())
-    fatal(EC, "failed to write the output file");
+    fatal("failed to write the output file: " + EC.message());
 }
 
 static StringRef getOutputSection(StringRef Name) {

Modified: lld/trunk/Common/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/Common/CMakeLists.txt?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/Common/CMakeLists.txt (original)
+++ lld/trunk/Common/CMakeLists.txt Wed Oct 25 15:28:38 2017
@@ -3,6 +3,7 @@ if(NOT LLD_BUILT_STANDALONE)
 endif()
 
 add_lld_library(lldCommon
+  ErrorHandler.cpp
   Reproduce.cpp
   TargetOptionsCommandFlags.cpp
   Threads.cpp

Added: lld/trunk/Common/ErrorHandler.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/Common/ErrorHandler.cpp?rev=316624&view=auto
==============================================================================
--- lld/trunk/Common/ErrorHandler.cpp (added)
+++ lld/trunk/Common/ErrorHandler.cpp Wed Oct 25 15:28:38 2017
@@ -0,0 +1,122 @@
+//===- ErrorHandler.cpp ---------------------------------------------------===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/Common/ErrorHandler.h"
+
+#include "lld/Common/Threads.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/raw_ostream.h"
+#include <mutex>
+
+#if !defined(_MSC_VER) && !defined(__MINGW32__)
+#include <unistd.h>
+#endif
+
+using namespace llvm;
+
+using namespace lld;
+
+// The functions defined in this file can be called from multiple threads,
+// but outs() or errs() are not thread-safe. We protect them using a mutex.
+static std::mutex Mu;
+
+// Prints "\n" or does nothing, depending on Msg contents of
+// the previous call of this function.
+static void newline(raw_ostream *ErrorOS, const Twine &Msg) {
+  // True if the previous error message contained "\n".
+  // We want to separate multi-line error messages with a newline.
+  static bool Flag;
+
+  if (Flag)
+    *ErrorOS << "\n";
+  Flag = StringRef(Msg.str()).contains('\n');
+}
+
+namespace lld {
+
+ErrorHandler &errorHandler() {
+  static ErrorHandler Handler;
+  return Handler;
+}
+
+void exitLld(int Val) {
+  waitForBackgroundThreads();
+  // Dealloc/destroy ManagedStatic variables before calling
+  // _exit(). In a non-LTO build, this is a nop. In an LTO
+  // build allows us to get the output of -time-passes.
+  llvm_shutdown();
+
+  outs().flush();
+  errs().flush();
+  _exit(Val);
+}
+
+void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {
+  *ErrorOS << LogName << ": ";
+  if (ColorDiagnostics) {
+    ErrorOS->changeColor(C, true);
+    *ErrorOS << S;
+    ErrorOS->resetColor();
+  } else {
+    *ErrorOS << S;
+  }
+}
+
+void ErrorHandler::log(const Twine &Msg) {
+  if (Verbose) {
+    std::lock_guard<std::mutex> Lock(Mu);
+    outs() << LogName << ": " << Msg << "\n";
+    outs().flush();
+  }
+}
+
+void ErrorHandler::message(const Twine &Msg) {
+  std::lock_guard<std::mutex> Lock(Mu);
+  outs() << Msg << "\n";
+  outs().flush();
+}
+
+void ErrorHandler::warn(const Twine &Msg) {
+  if (FatalWarnings) {
+    error(Msg);
+    return;
+  }
+
+  std::lock_guard<std::mutex> Lock(Mu);
+  newline(ErrorOS, Msg);
+  print("warning: ", raw_ostream::MAGENTA);
+  *ErrorOS << Msg << "\n";
+}
+
+void ErrorHandler::error(const Twine &Msg) {
+  std::lock_guard<std::mutex> Lock(Mu);
+  newline(ErrorOS, Msg);
+
+  if (ErrorLimit == 0 || ErrorCount < ErrorLimit) {
+    print("error: ", raw_ostream::RED);
+    *ErrorOS << Msg << "\n";
+  } else if (ErrorCount == ErrorLimit) {
+    print("error: ", raw_ostream::RED);
+    *ErrorOS << ErrorLimitExceededMsg << "\n";
+    if (ExitEarly)
+      exitLld(1);
+  }
+
+  ++ErrorCount;
+}
+
+void ErrorHandler::fatal(const Twine &Msg) {
+  error(Msg);
+  exitLld(1);
+}
+
+} // end namespace lld

Modified: lld/trunk/ELF/Arch/AArch64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AArch64.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AArch64.cpp (original)
+++ lld/trunk/ELF/Arch/AArch64.cpp Wed Oct 25 15:28:38 2017
@@ -7,11 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/Arch/AMDGPU.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AMDGPU.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AMDGPU.cpp (original)
+++ lld/trunk/ELF/Arch/AMDGPU.cpp Wed Oct 25 15:28:38 2017
@@ -7,10 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/Arch/ARM.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/ARM.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/ARM.cpp (original)
+++ lld/trunk/ELF/Arch/ARM.cpp Wed Oct 25 15:28:38 2017
@@ -7,12 +7,12 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/Arch/AVR.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/AVR.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/AVR.cpp (original)
+++ lld/trunk/ELF/Arch/AVR.cpp Wed Oct 25 15:28:38 2017
@@ -26,10 +26,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/Arch/Mips.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/Mips.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/Mips.cpp (original)
+++ lld/trunk/ELF/Arch/Mips.cpp Wed Oct 25 15:28:38 2017
@@ -7,13 +7,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/Arch/MipsArchTree.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/MipsArchTree.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/MipsArchTree.cpp (original)
+++ lld/trunk/ELF/Arch/MipsArchTree.cpp Wed Oct 25 15:28:38 2017
@@ -11,11 +11,11 @@
 //
 //===---------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "SymbolTable.h"
 #include "Writer.h"
 
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/MipsABIFlags.h"

Modified: lld/trunk/ELF/Arch/PPC.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC.cpp (original)
+++ lld/trunk/ELF/Arch/PPC.cpp Wed Oct 25 15:28:38 2017
@@ -7,9 +7,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "Symbols.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;

Modified: lld/trunk/ELF/Arch/PPC64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/PPC64.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/PPC64.cpp (original)
+++ lld/trunk/ELF/Arch/PPC64.cpp Wed Oct 25 15:28:38 2017
@@ -7,10 +7,10 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;

Modified: lld/trunk/ELF/Arch/SPARCV9.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/SPARCV9.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/SPARCV9.cpp (original)
+++ lld/trunk/ELF/Arch/SPARCV9.cpp Wed Oct 25 15:28:38 2017
@@ -7,11 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;

Modified: lld/trunk/ELF/Arch/X86.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86.cpp (original)
+++ lld/trunk/ELF/Arch/X86.cpp Wed Oct 25 15:28:38 2017
@@ -7,11 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Support/Endian.h"
 
 using namespace llvm;

Modified: lld/trunk/ELF/Arch/X86_64.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Arch/X86_64.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Arch/X86_64.cpp (original)
+++ lld/trunk/ELF/Arch/X86_64.cpp Wed Oct 25 15:28:38 2017
@@ -7,11 +7,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "Error.h"
 #include "InputFiles.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"
 

Modified: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt Wed Oct 25 15:28:38 2017
@@ -21,7 +21,6 @@ add_lld_library(lldELF
   Driver.cpp
   DriverUtils.cpp
   EhFrame.cpp
-  Error.cpp
   Filesystem.cpp
   GdbIndex.cpp
   ICF.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Wed Oct 25 15:28:38 2017
@@ -108,7 +108,6 @@ struct Configuration {
   bool AsNeeded = false;
   bool Bsymbolic;
   bool BsymbolicFunctions;
-  bool ColorDiagnostics = false;
   bool CompressDebugSections;
   bool DefineCommon;
   bool Demangle = true;
@@ -117,7 +116,6 @@ struct Configuration {
   bool EmitRelocs;
   bool EnableNewDtags;
   bool ExportDynamic;
-  bool FatalWarnings;
   bool GcSections;
   bool GdbIndex;
   bool GnuHash = false;
@@ -167,7 +165,6 @@ struct Configuration {
   ELFKind EKind = ELFNoneKind;
   uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
   uint16_t EMachine = llvm::ELF::EM_NONE;
-  uint64_t ErrorLimit = 20;
   llvm::Optional<uint64_t> ImageBase;
   uint64_t MaxPageSize;
   uint64_t ZStackSize;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Oct 25 15:28:38 2017
@@ -25,7 +25,6 @@
 
 #include "Driver.h"
 #include "Config.h"
-#include "Error.h"
 #include "Filesystem.h"
 #include "ICF.h"
 #include "InputFiles.h"
@@ -40,6 +39,7 @@
 #include "Target.h"
 #include "Writer.h"
 #include "lld/Common/Driver.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Threads.h"
 #include "lld/Common/Version.h"
 #include "llvm/ADT/StringExtras.h"
@@ -72,8 +72,12 @@ static void setConfigs();
 
 bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
                raw_ostream &Error) {
-  ErrorCount = 0;
-  ErrorOS = &Error;
+  errorHandler().LogName = Args[0];
+  errorHandler().ErrorLimitExceededMsg =
+      "too many errors emitted, stopping now (use "
+      "-error-limit=0 to see all errors)";
+  errorHandler().ErrorOS = &Error;
+  errorHandler().ColorDiagnostics = Error.has_colors();
   InputSections.clear();
   OutputSections.clear();
   Tar = nullptr;
@@ -95,10 +99,10 @@ bool elf::link(ArrayRef<const char *> Ar
   // This saves time because the overhead of calling destructors
   // for all globally-allocated objects is not negligible.
   if (Config->ExitEarly)
-    exitLld(ErrorCount ? 1 : 0);
+    exitLld(errorCount() ? 1 : 0);
 
   freeArena();
-  return !ErrorCount;
+  return !errorCount();
 }
 
 // Parses a linker -m option.
@@ -332,7 +336,7 @@ void LinkerDriver::main(ArrayRef<const c
   opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
 
   // Interpret this flag early because error() depends on them.
-  Config->ErrorLimit = getInteger(Args, OPT_error_limit, 20);
+  errorHandler().ErrorLimit = getInteger(Args, OPT_error_limit, 20);
 
   // Handle -help
   if (Args.hasArg(OPT_help)) {
@@ -365,6 +369,7 @@ void LinkerDriver::main(ArrayRef<const c
     return;
 
   Config->ExitEarly = CanExitEarly && !Args.hasArg(OPT_full_shutdown);
+  errorHandler().ExitEarly = Config->ExitEarly;
 
   if (const char *Path = getReproduceOption(Args)) {
     // Note that --reproduce is a debug option so you can ignore it
@@ -388,7 +393,7 @@ void LinkerDriver::main(ArrayRef<const c
   inferMachineType();
   setConfigs();
   checkOptions(Args);
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   switch (Config->EKind) {
@@ -645,7 +650,7 @@ void LinkerDriver::readConfigs(opt::Inpu
   Config->Entry = Args.getLastArgValue(OPT_entry);
   Config->ExportDynamic =
       Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
-  Config->FatalWarnings =
+  errorHandler().FatalWarnings =
       Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
   Config->FilterList = getArgs(Args, OPT_filter);
   Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
@@ -694,6 +699,7 @@ void LinkerDriver::readConfigs(opt::Inpu
   Config->Undefined = getArgs(Args, OPT_undefined);
   Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
   Config->Verbose = Args.hasArg(OPT_verbose);
+  errorHandler().Verbose = Config->Verbose;
   Config->WarnCommon = Args.hasArg(OPT_warn_common);
   Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
   Config->ZExecstack = hasZOption(Args, "execstack");
@@ -881,7 +887,7 @@ void LinkerDriver::createFiles(opt::Inpu
     }
   }
 
-  if (Files.empty() && ErrorCount == 0)
+  if (Files.empty() && errorCount() == 0)
     error("no input files");
 }
 
@@ -1009,7 +1015,7 @@ template <class ELFT> void LinkerDriver:
     error("cannot open output file " + Config->OutputFile + ": " + E.message());
   if (auto E = tryCreateFile(Config->MapFile))
     error("cannot open map file " + Config->MapFile + ": " + E.message());
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // Use default entry point name if no name was given via the command
@@ -1053,7 +1059,7 @@ template <class ELFT> void LinkerDriver:
   Symtab->fetchIfLazy<ELFT>(Config->Entry);
 
   // Return if there were name resolution errors.
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // Handle undefined symbols in DSOs.
@@ -1075,7 +1081,7 @@ template <class ELFT> void LinkerDriver:
     Symtab->addSymbolAlias<ELFT>(Def.first, Def.second);
 
   Symtab->addCombinedLTOObject<ELFT>();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // Apply symbol renames for -wrap and -defsym

Modified: lld/trunk/ELF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DriverUtils.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/DriverUtils.cpp (original)
+++ lld/trunk/ELF/DriverUtils.cpp Wed Oct 25 15:28:38 2017
@@ -14,8 +14,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "Driver.h"
-#include "Error.h"
 #include "Memory.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Reproduce.h"
 #include "lld/Common/Version.h"
 #include "llvm/ADT/Optional.h"
@@ -51,25 +51,26 @@ static const opt::OptTable::Info OptInfo
 
 ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
 
-// Parse -color-diagnostics={auto,always,never} or -no-color-diagnostics.
-static bool getColorDiagnostics(opt::InputArgList &Args) {
+// Set color diagnostics according to -color-diagnostics={auto,always,never}
+// or -no-color-diagnostics flags.
+static void handleColorDiagnostics(opt::InputArgList &Args) {
   auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
                               OPT_no_color_diagnostics);
   if (!Arg)
-    return ErrorOS->has_colors();
-  if (Arg->getOption().getID() == OPT_color_diagnostics)
-    return true;
-  if (Arg->getOption().getID() == OPT_no_color_diagnostics)
-    return false;
-
-  StringRef S = Arg->getValue();
-  if (S == "auto")
-    return ErrorOS->has_colors();
-  if (S == "always")
-    return true;
-  if (S != "never")
-    error("unknown option: -color-diagnostics=" + S);
-  return false;
+    return;
+  else if (Arg->getOption().getID() == OPT_color_diagnostics)
+    errorHandler().ColorDiagnostics = true;
+  else if (Arg->getOption().getID() == OPT_no_color_diagnostics)
+    errorHandler().ColorDiagnostics = false;
+  else {
+    StringRef S = Arg->getValue();
+    if (S == "always")
+      errorHandler().ColorDiagnostics = true;
+    else if (S == "never")
+      errorHandler().ColorDiagnostics = false;
+    else if (S != "auto")
+      error("unknown option: -color-diagnostics=" + S);
+  }
 }
 
 static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
@@ -103,9 +104,7 @@ opt::InputArgList ELFOptTable::parse(Arr
   cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
   Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
 
-  // Interpret -color-diagnostics early so that error messages
-  // for unknown flags are colored.
-  Config->ColorDiagnostics = getColorDiagnostics(Args);
+  handleColorDiagnostics(Args);
   if (MissingCount)
     error(Twine(Args.getArgString(MissingIndex)) + ": missing argument");
 

Modified: lld/trunk/ELF/EhFrame.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/EhFrame.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/EhFrame.cpp (original)
+++ lld/trunk/ELF/EhFrame.cpp Wed Oct 25 15:28:38 2017
@@ -17,11 +17,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "EhFrame.h"
-#include "Error.h"
 #include "InputSection.h"
 #include "Relocations.h"
 #include "Strings.h"
 
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/Object/ELF.h"
 #include "llvm/Support/Endian.h"

Removed: lld/trunk/ELF/Error.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.cpp?rev=316623&view=auto
==============================================================================
--- lld/trunk/ELF/Error.cpp (original)
+++ lld/trunk/ELF/Error.cpp (removed)
@@ -1,120 +0,0 @@
-//===- Error.cpp ----------------------------------------------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "Config.h"
-
-#include "lld/Common/Threads.h"
-
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/raw_ostream.h"
-#include <mutex>
-
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-#include <unistd.h>
-#endif
-
-using namespace llvm;
-
-using namespace lld;
-using namespace lld::elf;
-
-uint64_t elf::ErrorCount;
-raw_ostream *elf::ErrorOS;
-
-// The functions defined in this file can be called from multiple threads,
-// but outs() or errs() are not thread-safe. We protect them using a mutex.
-static std::mutex Mu;
-
-// Prints "\n" or does nothing, depending on Msg contents of
-// the previous call of this function.
-static void newline(const Twine &Msg) {
-  // True if the previous error message contained "\n".
-  // We want to separate multi-line error messages with a newline.
-  static bool Flag;
-
-  if (Flag)
-    *ErrorOS << "\n";
-  Flag = StringRef(Msg.str()).contains('\n');
-}
-
-static void print(StringRef S, raw_ostream::Colors C) {
-  *ErrorOS << Config->Argv[0] << ": ";
-  if (Config->ColorDiagnostics) {
-    ErrorOS->changeColor(C, true);
-    *ErrorOS << S;
-    ErrorOS->resetColor();
-  } else {
-    *ErrorOS << S;
-  }
-}
-
-void elf::log(const Twine &Msg) {
-  if (Config->Verbose) {
-    std::lock_guard<std::mutex> Lock(Mu);
-    outs() << Config->Argv[0] << ": " << Msg << "\n";
-    outs().flush();
-  }
-}
-
-void elf::message(const Twine &Msg) {
-  std::lock_guard<std::mutex> Lock(Mu);
-  outs() << Msg << "\n";
-  outs().flush();
-}
-
-void elf::warn(const Twine &Msg) {
-  if (Config->FatalWarnings) {
-    error(Msg);
-    return;
-  }
-
-  std::lock_guard<std::mutex> Lock(Mu);
-  newline(Msg);
-  print("warning: ", raw_ostream::MAGENTA);
-  *ErrorOS << Msg << "\n";
-}
-
-void elf::error(const Twine &Msg) {
-  std::lock_guard<std::mutex> Lock(Mu);
-  newline(Msg);
-
-  if (Config->ErrorLimit == 0 || ErrorCount < Config->ErrorLimit) {
-    print("error: ", raw_ostream::RED);
-    *ErrorOS << Msg << "\n";
-  } else if (ErrorCount == Config->ErrorLimit) {
-    print("error: ", raw_ostream::RED);
-    *ErrorOS << "too many errors emitted, stopping now"
-             << " (use -error-limit=0 to see all errors)\n";
-    if (Config->ExitEarly)
-      exitLld(1);
-  }
-
-  ++ErrorCount;
-}
-
-void elf::exitLld(int Val) {
-  waitForBackgroundThreads();
-
-  // Dealloc/destroy ManagedStatic variables before calling
-  // _exit(). In a non-LTO build, this is a nop. In an LTO
-  // build allows us to get the output of -time-passes.
-  llvm_shutdown();
-
-  outs().flush();
-  errs().flush();
-  _exit(Val);
-}
-
-void elf::fatal(const Twine &Msg) {
-  error(Msg);
-  exitLld(1);
-}

Removed: lld/trunk/ELF/Error.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.h?rev=316623&view=auto
==============================================================================
--- lld/trunk/ELF/Error.h (original)
+++ lld/trunk/ELF/Error.h (removed)
@@ -1,78 +0,0 @@
-//===- Error.h --------------------------------------------------*- C++ -*-===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// In LLD, we have three levels of errors: fatal, error or warn.
-//
-// Fatal makes the program exit immediately with an error message.
-// You shouldn't use it except for reporting a corrupted input file.
-//
-// Error prints out an error message and increment a global variable
-// ErrorCount to record the fact that we met an error condition. It does
-// not exit, so it is safe for a lld-as-a-library use case. It is generally
-// useful because it can report more than one error in a single run.
-//
-// Warn doesn't do anything but printing out a given message.
-//
-// It is not recommended to use llvm::outs() or llvm::errs() directly
-// in LLD because they are not thread-safe. The functions declared in
-// this file are mutually excluded, so you want to use them instead.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_ERROR_H
-#define LLD_ELF_ERROR_H
-
-#include "lld/Common/LLVM.h"
-
-#include "llvm/Support/Error.h"
-
-namespace lld {
-namespace elf {
-
-extern uint64_t ErrorCount;
-extern llvm::raw_ostream *ErrorOS;
-
-void log(const Twine &Msg);
-void message(const Twine &Msg);
-void warn(const Twine &Msg);
-void error(const Twine &Msg);
-LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
-
-LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
-
-// check() functions are convenient functions to strip errors
-// from error-or-value objects.
-template <class T> T check(ErrorOr<T> E) {
-  if (auto EC = E.getError())
-    fatal(EC.message());
-  return std::move(*E);
-}
-
-template <class T> T check(Expected<T> E) {
-  if (!E)
-    fatal(llvm::toString(E.takeError()));
-  return std::move(*E);
-}
-
-template <class T> T check(ErrorOr<T> E, const Twine &Prefix) {
-  if (auto EC = E.getError())
-    fatal(Prefix + ": " + EC.message());
-  return std::move(*E);
-}
-
-template <class T> T check(Expected<T> E, const Twine &Prefix) {
-  if (!E)
-    fatal(Prefix + ": " + toString(E.takeError()));
-  return std::move(*E);
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Wed Oct 25 15:28:38 2017
@@ -8,13 +8,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "InputFiles.h"
-#include "Error.h"
 #include "InputSection.h"
 #include "LinkerScript.h"
 #include "Memory.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/CodeGen/Analysis.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"

Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Wed Oct 25 15:28:38 2017
@@ -11,9 +11,9 @@
 #define LLD_ELF_INPUT_FILES_H
 
 #include "Config.h"
-#include "Error.h"
 #include "InputSection.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 
 #include "lld/Common/LLVM.h"
 #include "lld/Common/Reproduce.h"

Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Oct 25 15:28:38 2017
@@ -10,7 +10,6 @@
 #include "InputSection.h"
 #include "Config.h"
 #include "EhFrame.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "LinkerScript.h"
 #include "Memory.h"
@@ -19,6 +18,7 @@
 #include "SyntheticSections.h"
 #include "Target.h"
 #include "Thunks.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/Decompressor.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Compression.h"

Modified: lld/trunk/ELF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/LTO.cpp (original)
+++ lld/trunk/ELF/LTO.cpp Wed Oct 25 15:28:38 2017
@@ -9,11 +9,11 @@
 
 #include "LTO.h"
 #include "Config.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "LinkerScript.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"

Modified: lld/trunk/ELF/Relocations.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Relocations.cpp (original)
+++ lld/trunk/ELF/Relocations.cpp Wed Oct 25 15:28:38 2017
@@ -927,7 +927,7 @@ static void scanRelocs(InputSectionBase
       Expr = fromPlt(Expr);
 
     Expr = adjustExpr<ELFT>(Body, Expr, Type, Sec, Rel.r_offset);
-    if (ErrorCount)
+    if (errorCount())
       continue;
 
     // This relocation does not require got entry, but it is relative to got and

Modified: lld/trunk/ELF/ScriptLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptLexer.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptLexer.cpp (original)
+++ lld/trunk/ELF/ScriptLexer.cpp Wed Oct 25 15:28:38 2017
@@ -33,7 +33,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "ScriptLexer.h"
-#include "Error.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/Twine.h"
 
 using namespace llvm;
@@ -75,7 +75,7 @@ ScriptLexer::ScriptLexer(MemoryBufferRef
 
 // We don't want to record cascading errors. Keep only the first one.
 void ScriptLexer::setError(const Twine &Msg) {
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   std::string S = (getCurrentLocation() + ": " + Msg).str();
@@ -159,7 +159,7 @@ StringRef ScriptLexer::skipSpace(StringR
 }
 
 // An erroneous token is handled as if it were the last token before EOF.
-bool ScriptLexer::atEOF() { return ErrorCount || Tokens.size() == Pos; }
+bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }
 
 // Split a given string as an expression.
 // This function returns "3", "*" and "5" for "3*5" for example.
@@ -207,7 +207,7 @@ static std::vector<StringRef> tokenizeEx
 //
 // This function may split the current token into multiple tokens.
 void ScriptLexer::maybeSplitExpr() {
-  if (!InExpr || ErrorCount || atEOF())
+  if (!InExpr || errorCount() || atEOF())
     return;
 
   std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);
@@ -220,7 +220,7 @@ void ScriptLexer::maybeSplitExpr() {
 StringRef ScriptLexer::next() {
   maybeSplitExpr();
 
-  if (ErrorCount)
+  if (errorCount())
     return "";
   if (atEOF()) {
     setError("unexpected EOF");
@@ -231,7 +231,7 @@ StringRef ScriptLexer::next() {
 
 StringRef ScriptLexer::peek() {
   StringRef Tok = next();
-  if (ErrorCount)
+  if (errorCount())
     return "";
   Pos = Pos - 1;
   return Tok;
@@ -260,7 +260,7 @@ bool ScriptLexer::consumeLabel(StringRef
 void ScriptLexer::skip() { (void)next(); }
 
 void ScriptLexer::expect(StringRef Expect) {
-  if (ErrorCount)
+  if (errorCount())
     return;
   StringRef Tok = next();
   if (Tok != Expect)

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Wed Oct 25 15:28:38 2017
@@ -209,7 +209,7 @@ void ScriptParser::readVersionScriptComm
     return;
   }
 
-  while (!atEOF() && !ErrorCount && peek() != "}") {
+  while (!atEOF() && !errorCount() && peek() != "}") {
     StringRef VerStr = next();
     if (VerStr == "{") {
       setError("anonymous version definition is used in "
@@ -303,7 +303,7 @@ void ScriptParser::readAsNeeded() {
   expect("(");
   bool Orig = Config->AsNeeded;
   Config->AsNeeded = true;
-  while (!ErrorCount && !consume(")"))
+  while (!errorCount() && !consume(")"))
     addFile(unquote(next()));
   Config->AsNeeded = Orig;
 }
@@ -319,13 +319,13 @@ void ScriptParser::readEntry() {
 
 void ScriptParser::readExtern() {
   expect("(");
-  while (!ErrorCount && !consume(")"))
+  while (!errorCount() && !consume(")"))
     Config->Undefined.push_back(next());
 }
 
 void ScriptParser::readGroup() {
   expect("(");
-  while (!ErrorCount && !consume(")")) {
+  while (!errorCount() && !consume(")")) {
     if (consume("AS_NEEDED"))
       readAsNeeded();
     else
@@ -369,7 +369,7 @@ void ScriptParser::readOutput() {
 void ScriptParser::readOutputArch() {
   // OUTPUT_ARCH is ignored for now.
   expect("(");
-  while (!ErrorCount && !consume(")"))
+  while (!errorCount() && !consume(")"))
     skip();
 }
 
@@ -389,12 +389,12 @@ void ScriptParser::readOutputFormat() {
 void ScriptParser::readPhdrs() {
   expect("{");
 
-  while (!ErrorCount && !consume("}")) {
+  while (!errorCount() && !consume("}")) {
     PhdrsCommand Cmd;
     Cmd.Name = next();
     Cmd.Type = readPhdrType();
 
-    while (!ErrorCount && !consume(";")) {
+    while (!errorCount() && !consume(";")) {
       if (consume("FILEHDR"))
         Cmd.HasFilehdr = true;
       else if (consume("PHDRS"))
@@ -442,7 +442,7 @@ void ScriptParser::readSections() {
   Config->SingleRoRx = true;
 
   expect("{");
-  while (!ErrorCount && !consume("}")) {
+  while (!errorCount() && !consume("}")) {
     StringRef Tok = next();
     BaseCommand *Cmd = readProvideOrAssignment(Tok);
     if (!Cmd) {
@@ -467,7 +467,7 @@ static int precedence(StringRef Op) {
 
 StringMatcher ScriptParser::readFilePatterns() {
   std::vector<StringRef> V;
-  while (!ErrorCount && !consume(")"))
+  while (!errorCount() && !consume(")"))
     V.push_back(next());
   return StringMatcher(V);
 }
@@ -499,7 +499,7 @@ SortSectionPolicy ScriptParser::readSort
 // any file but a.o, and section .baz in any file but b.o.
 std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
   std::vector<SectionPattern> Ret;
-  while (!ErrorCount && peek() != ")") {
+  while (!errorCount() && peek() != ")") {
     StringMatcher ExcludeFilePat;
     if (consume("EXCLUDE_FILE")) {
       expect("(");
@@ -507,7 +507,7 @@ std::vector<SectionPattern> ScriptParser
     }
 
     std::vector<StringRef> V;
-    while (!ErrorCount && peek() != ")" && peek() != "EXCLUDE_FILE")
+    while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
       V.push_back(next());
 
     if (!V.empty())
@@ -534,7 +534,7 @@ ScriptParser::readInputSectionRules(Stri
   auto *Cmd = make<InputSectionDescription>(FilePattern);
   expect("(");
 
-  while (!ErrorCount && !consume(")")) {
+  while (!errorCount() && !consume(")")) {
     SortSectionPolicy Outer = readSortKind();
     SortSectionPolicy Inner = SortSectionPolicy::Default;
     std::vector<SectionPattern> V;
@@ -676,7 +676,7 @@ OutputSection *ScriptParser::readOutputS
     Cmd->Constraint = ConstraintKind::ReadWrite;
   expect("{");
 
-  while (!ErrorCount && !consume("}")) {
+  while (!errorCount() && !consume("}")) {
     StringRef Tok = next();
     if (Tok == ";") {
       // Empty commands are allowed. Do nothing here.
@@ -820,7 +820,7 @@ static Expr combine(StringRef Op, Expr L
 // This is a part of the operator-precedence parser. This function
 // assumes that the remaining token stream starts with an operator.
 Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {
-  while (!atEOF() && !ErrorCount) {
+  while (!atEOF() && !errorCount()) {
     // Read an operator and an expression.
     if (consume("?"))
       return readTernary(Lhs);
@@ -1098,7 +1098,7 @@ Expr ScriptParser::readParenExpr() {
 
 std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
   std::vector<StringRef> Phdrs;
-  while (!ErrorCount && peek().startswith(":")) {
+  while (!errorCount() && peek().startswith(":")) {
     StringRef Tok = next();
     Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1));
   }
@@ -1201,7 +1201,7 @@ ScriptParser::readSymbols() {
   std::vector<SymbolVersion> Globals;
   std::vector<SymbolVersion> *V = &Globals;
 
-  while (!ErrorCount) {
+  while (!errorCount()) {
     if (consume("}"))
       break;
     if (consumeLabel("local")) {
@@ -1235,7 +1235,7 @@ std::vector<SymbolVersion> ScriptParser:
   expect("{");
 
   std::vector<SymbolVersion> Ret;
-  while (!ErrorCount && peek() != "}") {
+  while (!errorCount() && peek() != "}") {
     StringRef Tok = next();
     bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok);
     Ret.push_back({unquote(Tok), IsCXX, HasWildcard});
@@ -1262,7 +1262,7 @@ uint64_t ScriptParser::readMemoryAssignm
 // MEMORY { name [(attr)] : ORIGIN = origin, LENGTH = len ... }
 void ScriptParser::readMemory() {
   expect("{");
-  while (!ErrorCount && !consume("}")) {
+  while (!errorCount() && !consume("}")) {
     StringRef Name = next();
 
     uint32_t Flags = 0;

Modified: lld/trunk/ELF/Strings.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Strings.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Strings.cpp (original)
+++ lld/trunk/ELF/Strings.cpp Wed Oct 25 15:28:38 2017
@@ -9,7 +9,7 @@
 
 #include "Strings.h"
 #include "Config.h"
-#include "Error.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Wed Oct 25 15:28:38 2017
@@ -16,10 +16,10 @@
 
 #include "SymbolTable.h"
 #include "Config.h"
-#include "Error.h"
 #include "LinkerScript.h"
 #include "Memory.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/STLExtras.h"
 
 using namespace llvm;
@@ -91,7 +91,7 @@ template <class ELFT> void SymbolTable::
   if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
     // DSOs are uniquified not by filename but by soname.
     F->parseSoName();
-    if (ErrorCount || !SoNames.insert(F->SoName).second)
+    if (errorCount() || !SoNames.insert(F->SoName).second)
       return;
     SharedFiles.push_back(F);
     F->parseRest();

Modified: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp Wed Oct 25 15:28:38 2017
@@ -8,7 +8,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "Symbols.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "InputSection.h"
 #include "OutputSections.h"
@@ -17,6 +16,7 @@
 #include "Target.h"
 #include "Writer.h"
 
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Path.h"
 #include <cstring>

Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Oct 25 15:28:38 2017
@@ -16,7 +16,6 @@
 
 #include "SyntheticSections.h"
 #include "Config.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "LinkerScript.h"
 #include "Memory.h"
@@ -25,6 +24,7 @@
 #include "SymbolTable.h"
 #include "Target.h"
 #include "Writer.h"
+#include "lld/Common/ErrorHandler.h"
 #include "lld/Common/Threads.h"
 #include "lld/Common/Version.h"
 #include "llvm/BinaryFormat/Dwarf.h"

Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Oct 25 15:28:38 2017
@@ -25,11 +25,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "Target.h"
-#include "Error.h"
 #include "InputFiles.h"
 #include "OutputSections.h"
 #include "SymbolTable.h"
 #include "Symbols.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 
 using namespace llvm;

Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Oct 25 15:28:38 2017
@@ -10,8 +10,8 @@
 #ifndef LLD_ELF_TARGET_H
 #define LLD_ELF_TARGET_H
 
-#include "Error.h"
 #include "InputSection.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/Object/ELF.h"
 
 namespace lld {

Modified: lld/trunk/ELF/Thunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Thunks.cpp (original)
+++ lld/trunk/ELF/Thunks.cpp Wed Oct 25 15:28:38 2017
@@ -23,13 +23,13 @@
 
 #include "Thunks.h"
 #include "Config.h"
-#include "Error.h"
 #include "InputSection.h"
 #include "Memory.h"
 #include "OutputSections.h"
 #include "Symbols.h"
 #include "SyntheticSections.h"
 #include "Target.h"
+#include "lld/Common/ErrorHandler.h"
 #include "llvm/BinaryFormat/ELF.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Endian.h"

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=316624&r1=316623&r2=316624&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Oct 25 15:28:38 2017
@@ -188,7 +188,7 @@ template <class ELFT> void Writer<ELFT>:
   // to the string table, and add entries to .got and .plt.
   // finalizeSections does that.
   finalizeSections();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // If -compressed-debug-sections is specified, we need to compress
@@ -218,11 +218,11 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   // It does not make sense try to open the file if we have error already.
-  if (ErrorCount)
+  if (errorCount())
     return;
   // Write the result down to a file.
   openFile();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   if (!Config->OFormatBinary) {
@@ -236,12 +236,12 @@ template <class ELFT> void Writer<ELFT>:
   // Backfill .note.gnu.build-id section content. This is done at last
   // because the content is usually a hash value of the entire output file.
   writeBuildId();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   // Handle -Map option.
   writeMapFile<ELFT>();
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   if (auto EC = Buffer->commit())
@@ -1287,7 +1287,7 @@ template <class ELFT> void Writer<ELFT>:
   }
 
   // Do not proceed if there was an undefined symbol.
-  if (ErrorCount)
+  if (errorCount())
     return;
 
   addPredefinedSections();

Added: lld/trunk/include/lld/Common/ErrorHandler.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Common/ErrorHandler.h?rev=316624&view=auto
==============================================================================
--- lld/trunk/include/lld/Common/ErrorHandler.h (added)
+++ lld/trunk/include/lld/Common/ErrorHandler.h Wed Oct 25 15:28:38 2017
@@ -0,0 +1,101 @@
+//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
+//
+//                             The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// In LLD, we have three levels of errors: fatal, error or warn.
+//
+// Fatal makes the program exit immediately with an error message.
+// You shouldn't use it except for reporting a corrupted input file.
+//
+// Error prints out an error message and increment a global variable
+// ErrorCount to record the fact that we met an error condition. It does
+// not exit, so it is safe for a lld-as-a-library use case. It is generally
+// useful because it can report more than one error in a single run.
+//
+// Warn doesn't do anything but printing out a given message.
+//
+// It is not recommended to use llvm::outs() or llvm::errs() directly
+// in LLD because they are not thread-safe. The functions declared in
+// this file are mutually excluded, so you want to use them instead.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_COMMON_ERRORHANDLER_H
+#define LLD_COMMON_ERRORHANDLER_H
+
+#include "lld/Common/LLVM.h"
+
+#include "llvm/Support/Error.h"
+
+namespace lld {
+
+class ErrorHandler {
+public:
+  uint64_t ErrorCount = 0;
+  uint64_t ErrorLimit = 20;
+  StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now";
+  StringRef LogName = "lld";
+  llvm::raw_ostream *ErrorOS = &llvm::errs();
+  bool ColorDiagnostics = llvm::errs().has_colors();
+  bool ExitEarly = true;
+  bool FatalWarnings = false;
+  bool Verbose = false;
+
+  void error(const Twine &Msg);
+  LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+  void log(const Twine &Msg);
+  void message(const Twine &Msg);
+  void warn(const Twine &Msg);
+
+private:
+  void print(StringRef S, raw_ostream::Colors C);
+};
+
+/// Returns the default error handler.
+ErrorHandler &errorHandler();
+
+inline void error(const Twine &Msg) { errorHandler().error(Msg); }
+inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) {
+  errorHandler().fatal(Msg);
+}
+inline void log(const Twine &Msg) { errorHandler().log(Msg); }
+inline void message(const Twine &Msg) { errorHandler().message(Msg); }
+inline void warn(const Twine &Msg) { errorHandler().warn(Msg); }
+inline uint64_t errorCount() { return errorHandler().ErrorCount; }
+
+LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);
+
+// check() functions are convenient functions to strip errors
+// from error-or-value objects.
+template <class T> T check(ErrorOr<T> E) {
+  if (auto EC = E.getError())
+    fatal(EC.message());
+  return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E) {
+  if (!E)
+    fatal(llvm::toString(E.takeError()));
+  return std::move(*E);
+}
+
+template <class T> T check(ErrorOr<T> E, const Twine &Prefix) {
+  if (auto EC = E.getError())
+    fatal(Prefix + ": " + EC.message());
+  return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E, const Twine &Prefix) {
+  if (!E)
+    fatal(Prefix + ": " + toString(E.takeError()));
+  return std::move(*E);
+}
+
+} // namespace lld
+
+#endif




More information about the llvm-commits mailing list