//===- CIndexHigh.cpp - Higher level API functions ------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "IndexingContext.h"
#include "CIndexDiagnostic.h"
#include "CIndexer.h"
#include "CLog.h"
#include "CXCursor.h"
#include "CXSourceLocation.h"
#include "CXString.h"
#include "CXTranslationUnit.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/FrontendAction.h"
#include "clang/Frontend/Utils.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/PPCallbacks.h"
#include "clang/Lex/PPConditionalDirectiveRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/MutexGuard.h"
using namespace clang;
using namespace cxtu;
using namespace cxindex;
static void indexDiagnostics(CXTranslationUnit TU, IndexingContext &IdxCtx);
namespace {
//===----------------------------------------------------------------------===//
// Skip Parsed Bodies
//===----------------------------------------------------------------------===//
#ifdef LLVM_ON_WIN32
// FIXME: On windows it is disabled since current implementation depends on
// file inodes.
class SessionSkipBodyData { };
class TUSkipBodyControl {
public:
TUSkipBodyControl(SessionSkipBodyData &sessionData,
PPConditionalDirectiveRecord &ppRec,
Preprocessor &pp) { }
bool isParsed(SourceLocation Loc, FileID FID, const FileEntry *FE) {
return false;
}
void finished() { }
};
#else
/// \brief A "region" in source code identified by the file/offset of the
/// preprocessor conditional directive that it belongs to.
/// Multiple, non-consecutive ranges can be parts of the same region.
///
/// As an example of different regions separated by preprocessor directives:
///
/// \code
/// #1
/// #ifdef BLAH
/// #2
/// #ifdef CAKE
/// #3
/// #endif
/// #2
/// #endif
/// #1
/// \endcode
///
/// There are 3 regions, with non-consecutive parts:
/// #1 is identified as the beginning of the file
/// #2 is identified as the location of "#ifdef BLAH"
/// #3 is identified as the location of "#ifdef CAKE"
///
class PPRegion {
ino_t ino;
time_t ModTime;
dev_t dev;
unsigned Offset;
public:
PPRegion() : ino(), ModTime(), dev(), Offset() {}
PPRegion(dev_t dev, ino_t ino, unsigned offset, time_t modTime)
: ino(ino), ModTime(modTime), dev(dev), Offset(offset) {}
ino_t getIno() const { return ino; }
dev_t getDev() const { return dev; }
unsigned getOffset() const { return Offset; }
time_t getModTime() const { return ModTime; }
bool isInvalid() const { return *this == PPRegion(); }
friend bool operator==(const PPRegion &lhs, const PPRegion &rhs) {
return lhs.dev == rhs.dev && lhs.ino == rhs.ino &&
lhs.Offset == rhs.Offset && lhs.ModTime == rhs.ModTime;
}
};
typedef llvm::DenseSet<PPRegion> PPRegionSetTy;
} // end anonymous namespace
namespace llvm {
template <> struct isPodLike<PPRegion> {
static const bool value = true;
};
template <>
struct DenseMapInfo<PPRegion> {
static inline PPRegion getEmptyKey() {
return PPRegion(0, 0, unsigned(-1), 0);
}
static inline PPRegion getTombstoneKey() {
return PPRegion(0, 0, unsigned(-2), 0);
}
static unsigned getHashValue(const PPRegion &S) {
llvm::FoldingSetNodeID ID;
ID.AddInteger(S.getIno());
ID.AddInteger(S.getDev());
ID.AddInteger(S.getOffset());
ID.AddInteger(S.getModTime());
return ID.ComputeHash();
}
static bool isEqual(const PPRegion &LHS, const PPRegion &RHS) {
return LHS == RHS