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