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/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 /// \brief 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() != 0; }
     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 0;
     61   }
     62 
     63   explicit Logger(llvm::StringRef name, bool trace)
     64     : Name(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 /// \brief 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) if (LogRef Log = clang::cxindex::Logger::make(NAME))
     99 #define LOG_FUNC_SECTION LOG_SECTION(LLVM_FUNCTION_NAME)
    100 
    101 #endif
    102