Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // We designed lld's error handlers with the following goals in mind:
  10. //
  11. //  - Errors can occur at any place where we handle user input, but we don't
  12. //    want them to affect the normal execution path too much. Ideally,
  13. //    handling errors should be as simple as reporting them and exit (but
  14. //    without actually doing exit).
  15. //
  16. //    In particular, the design to wrap all functions that could fail with
  17. //    ErrorOr<T> is rejected because otherwise we would have to wrap a large
  18. //    number of functions in lld with ErrorOr. With that approach, if some
  19. //    function F can fail, not only F but all functions that transitively call
  20. //    F have to be wrapped with ErrorOr. That seemed too much.
  21. //
  22. //  - Finding only one error at a time is not sufficient. We want to find as
  23. //    many errors as possible with one execution of the linker. That means the
  24. //    linker needs to keep running after a first error and give up at some
  25. //    checkpoint (beyond which it would find cascading, false errors caused by
  26. //    the previous errors).
  27. //
  28. //  - We want a simple interface to report errors. Unlike Clang, the data we
  29. //    handle is compiled binary, so we don't need an error reporting mechanism
  30. //    that's as sophisticated as the one that Clang has.
  31. //
  32. // The current lld's error handling mechanism is simple:
  33. //
  34. //  - When you find an error, report it using error() and continue as far as
  35. //    you can. An internal error counter is incremented by one every time you
  36. //    call error().
  37. //
  38. //    A common idiom to handle an error is calling error() and then returning
  39. //    a reasonable default value. For example, if your function handles a
  40. //    user-supplied alignment value, and if you find an invalid alignment
  41. //    (e.g. 17 which is not 2^n), you may report it using error() and continue
  42. //    as if it were alignment 1 (which is the simplest reasonable value).
  43. //
  44. //    Note that you should not continue with an invalid value; that breaks the
  45. //    internal consistency. You need to maintain all variables have some sane
  46. //    value even after an error occurred. So, when you have to continue with
  47. //    some value, always use a dummy value.
  48. //
  49. //  - Find a reasonable checkpoint at where you want to stop the linker, and
  50. //    add code to return from the function if errorCount() > 0. In most cases,
  51. //    a checkpoint already exists, so you don't need to do anything for this.
  52. //
  53. // This interface satisfies all the goals that we mentioned above.
  54. //
  55. // You should never call fatal() except for reporting a corrupted input file.
  56. // fatal() immediately terminates the linker, so the function is not desirable
  57. // if you are using lld as a subroutine in other program, and with that you
  58. // can find only one error at a time.
  59. //
  60. // warn() doesn't do anything but printing out a given message.
  61. //
  62. // It is not recommended to use llvm::outs() or lld::errs() directly in lld
  63. // because they are not thread-safe. The functions declared in this file are
  64. // thread-safe.
  65. //
  66. //===----------------------------------------------------------------------===//
  67.  
  68. #ifndef LLD_COMMON_ERRORHANDLER_H
  69. #define LLD_COMMON_ERRORHANDLER_H
  70.  
  71. #include "lld/Common/LLVM.h"
  72.  
  73. #include "llvm/ADT/STLExtras.h"
  74. #include "llvm/Support/Error.h"
  75. #include "llvm/Support/FileOutputBuffer.h"
  76. #include <mutex>
  77.  
  78. namespace llvm {
  79. class DiagnosticInfo;
  80. class raw_ostream;
  81. }
  82.  
  83. namespace lld {
  84.  
  85. llvm::raw_ostream &outs();
  86. llvm::raw_ostream &errs();
  87.  
  88. enum class ErrorTag { LibNotFound, SymbolNotFound };
  89.  
  90. class ErrorHandler {
  91. public:
  92.   ~ErrorHandler();
  93.  
  94.   void initialize(llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS,
  95.                   bool exitEarly, bool disableOutput);
  96.  
  97.   uint64_t errorCount = 0;
  98.   uint64_t errorLimit = 20;
  99.   StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
  100.   StringRef errorHandlingScript;
  101.   StringRef logName = "lld";
  102.   bool exitEarly = true;
  103.   bool fatalWarnings = false;
  104.   bool suppressWarnings = false;
  105.   bool verbose = false;
  106.   bool vsDiagnostics = false;
  107.   bool disableOutput = false;
  108.   std::function<void()> cleanupCallback;
  109.  
  110.   void error(const Twine &msg);
  111.   void error(const Twine &msg, ErrorTag tag, ArrayRef<StringRef> args);
  112.   [[noreturn]] void fatal(const Twine &msg);
  113.   void log(const Twine &msg);
  114.   void message(const Twine &msg, llvm::raw_ostream &s);
  115.   void warn(const Twine &msg);
  116.  
  117.   raw_ostream &outs();
  118.   raw_ostream &errs();
  119.   void flushStreams();
  120.  
  121.   std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
  122.  
  123. private:
  124.   using Colors = raw_ostream::Colors;
  125.  
  126.   std::string getLocation(const Twine &msg);
  127.   void reportDiagnostic(StringRef location, Colors c, StringRef diagKind,
  128.                         const Twine &msg);
  129.  
  130.   // We want to separate multi-line messages with a newline. `sep` is "\n"
  131.   // if the last messages was multi-line. Otherwise "".
  132.   llvm::StringRef sep;
  133.  
  134.   // We wrap stdout and stderr so that you can pass alternative stdout/stderr as
  135.   // arguments to lld::*::link() functions. Since lld::outs() or lld::errs() can
  136.   // be indirectly called from multiple threads, we protect them using a mutex.
  137.   // In the future, we plan on supporting several concurrent linker contexts,
  138.   // which explains why the mutex is not a global but part of this context.
  139.   std::mutex mu;
  140.   llvm::raw_ostream *stdoutOS{};
  141.   llvm::raw_ostream *stderrOS{};
  142. };
  143.  
  144. /// Returns the default error handler.
  145. ErrorHandler &errorHandler();
  146.  
  147. void error(const Twine &msg);
  148. void error(const Twine &msg, ErrorTag tag, ArrayRef<StringRef> args);
  149. [[noreturn]] void fatal(const Twine &msg);
  150. void log(const Twine &msg);
  151. void message(const Twine &msg, llvm::raw_ostream &s = outs());
  152. void warn(const Twine &msg);
  153. uint64_t errorCount();
  154.  
  155. [[noreturn]] void exitLld(int val);
  156.  
  157. void diagnosticHandler(const llvm::DiagnosticInfo &di);
  158. void checkError(Error e);
  159.  
  160. // check functions are convenient functions to strip errors
  161. // from error-or-value objects.
  162. template <class T> T check(ErrorOr<T> e) {
  163.   if (auto ec = e.getError())
  164.     fatal(ec.message());
  165.   return std::move(*e);
  166. }
  167.  
  168. template <class T> T check(Expected<T> e) {
  169.   if (!e)
  170.     fatal(llvm::toString(e.takeError()));
  171.   return std::move(*e);
  172. }
  173.  
  174. // Don't move from Expected wrappers around references.
  175. template <class T> T &check(Expected<T &> e) {
  176.   if (!e)
  177.     fatal(llvm::toString(e.takeError()));
  178.   return *e;
  179. }
  180.  
  181. template <class T>
  182. T check2(ErrorOr<T> e, llvm::function_ref<std::string()> prefix) {
  183.   if (auto ec = e.getError())
  184.     fatal(prefix() + ": " + ec.message());
  185.   return std::move(*e);
  186. }
  187.  
  188. template <class T>
  189. T check2(Expected<T> e, llvm::function_ref<std::string()> prefix) {
  190.   if (!e)
  191.     fatal(prefix() + ": " + toString(e.takeError()));
  192.   return std::move(*e);
  193. }
  194.  
  195. inline std::string toString(const Twine &s) { return s.str(); }
  196.  
  197. // To evaluate the second argument lazily, we use C macro.
  198. #define CHECK(E, S) check2((E), [&] { return toString(S); })
  199.  
  200. } // namespace lld
  201.  
  202. #endif
  203.