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