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