CLog.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. //===- CLog.h - Logging Interface -------------------------------*- 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. #ifndef LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H
  9. #define LLVM_CLANG_TOOLS_LIBCLANG_CLOG_H
  10. #include "clang-c/Index.h"
  11. #include "clang/Basic/LLVM.h"
  12. #include "llvm/ADT/IntrusiveRefCntPtr.h"
  13. #include "llvm/ADT/SmallString.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/Support/Compiler.h"
  16. #include "llvm/Support/raw_ostream.h"
  17. #include <string>
  18. namespace llvm {
  19. class format_object_base;
  20. }
  21. namespace clang {
  22. class FileEntry;
  23. namespace cxindex {
  24. class Logger;
  25. typedef IntrusiveRefCntPtr<Logger> LogRef;
  26. /// Collects logging output and writes it to stderr when it's destructed.
  27. /// Common use case:
  28. /// \code
  29. /// if (LogRef Log = Logger::make(__func__)) {
  30. /// *Log << "stuff";
  31. /// }
  32. /// \endcode
  33. class Logger : public RefCountedBase<Logger> {
  34. std::string Name;
  35. bool Trace;
  36. SmallString<64> Msg;
  37. llvm::raw_svector_ostream LogOS;
  38. public:
  39. static const char *getEnvVar() {
  40. static const char *sCachedVar = ::getenv("LIBCLANG_LOGGING");
  41. return sCachedVar;
  42. }
  43. static bool isLoggingEnabled() { return getEnvVar() != nullptr; }
  44. static bool isStackTracingEnabled() {
  45. if (const char *EnvOpt = Logger::getEnvVar())
  46. return llvm::StringRef(EnvOpt) == "2";
  47. return false;
  48. }
  49. static LogRef make(llvm::StringRef name,
  50. bool trace = isStackTracingEnabled()) {
  51. if (isLoggingEnabled())
  52. return new Logger(name, trace);
  53. return nullptr;
  54. }
  55. explicit Logger(llvm::StringRef name, bool trace)
  56. : Name(std::string(name)), Trace(trace), LogOS(Msg) {}
  57. ~Logger();
  58. Logger &operator<<(CXTranslationUnit);
  59. Logger &operator<<(const FileEntry *FE);
  60. Logger &operator<<(CXCursor cursor);
  61. Logger &operator<<(CXSourceLocation);
  62. Logger &operator<<(CXSourceRange);
  63. Logger &operator<<(CXString);
  64. Logger &operator<<(llvm::StringRef Str) { LogOS << Str; return *this; }
  65. Logger &operator<<(const char *Str) {
  66. if (Str)
  67. LogOS << Str;
  68. return *this;
  69. }
  70. Logger &operator<<(unsigned long N) { LogOS << N; return *this; }
  71. Logger &operator<<(long N) { LogOS << N ; return *this; }
  72. Logger &operator<<(unsigned int N) { LogOS << N; return *this; }
  73. Logger &operator<<(int N) { LogOS << N; return *this; }
  74. Logger &operator<<(char C) { LogOS << C; return *this; }
  75. Logger &operator<<(unsigned char C) { LogOS << C; return *this; }
  76. Logger &operator<<(signed char C) { LogOS << C; return *this; }
  77. Logger &operator<<(const llvm::format_object_base &Fmt);
  78. };
  79. }
  80. }
  81. /// Macros to automate common uses of Logger. Like this:
  82. /// \code
  83. /// LOG_FUNC_SECTION {
  84. /// *Log << "blah";
  85. /// }
  86. /// \endcode
  87. #define LOG_SECTION(NAME) \
  88. if (clang::cxindex::LogRef Log = clang::cxindex::Logger::make(NAME))
  89. #define LOG_FUNC_SECTION LOG_SECTION(__func__)
  90. #endif