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