//===--- SourceManager.cpp - Track and cache source files -----------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the SourceManager interface.
//
//===----------------------------------------------------------------------===//
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/SourceManagerInternals.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/FileManager.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"
#include <algorithm>
#include <string>
#include <cstring>
using namespace clang;
using namespace SrcMgr;
using llvm::MemoryBuffer;
//===----------------------------------------------------------------------===//
// SourceManager Helper Classes
//===----------------------------------------------------------------------===//
ContentCache::~ContentCache() {
if (shouldFreeBuffer())
delete Buffer.getPointer();
}
/// getSizeBytesMapped - Returns the number of bytes actually mapped for
/// this ContentCache. This can be 0 if the MemBuffer was not actually
/// instantiated.
unsigned ContentCache::getSizeBytesMapped() const {
return Buffer.getPointer() ? Buffer.getPointer()->getBufferSize() : 0;
}
/// getSize - Returns the size of the content encapsulated by this ContentCache.
/// This can be the size of the source file or the size of an arbitrary
/// scratch buffer. If the ContentCache encapsulates a source file, that
/// file is not lazily brought in from disk to satisfy this query.
unsigned ContentCache::getSize() const {
return Buffer.getPointer() ? (unsigned) Buffer.getPointer()->getBufferSize()
: (unsigned) Entry->getSize();
}
void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B,
bool DoNotFree) {
assert(B != Buffer.getPointer());
if (shouldFreeBuffer())
delete Buffer.getPointer();
Buffer.setPointer(B);
Buffer.setInt(DoNotFree? DoNotFreeFlag : 0);
}
const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag,
const SourceManager &SM,
SourceLocation Loc,
bool *Invalid) const {
if (Invalid)
*Invalid = false;
// Lazily create the Buffer for ContentCaches that wrap files.
if (!Buffer.getPointer() && Entry) {
std::string ErrorStr;
Buffer.setPointer(SM.getFileManager().getBufferForFile(Entry, &ErrorStr));
// If we were unable to open the file, then we are in an inconsistent
// situation where the content cache referenced a file which no longer
// exists. Most likely, we were using a stat cache with an invalid entry but
// the file could also have been removed during processing. Since we can't
// really deal with this situation, just create an empty buffer.
//
// FIXME: This is definitely not ideal, but our immediate clients can't
// currently handle returning a null entry here. Ideally we should detect
// that we are in an inconsistent situation and error out as quickly as
// possible.
if (!Buffer.getPointer()) {
const