зеркало из https://github.com/microsoft/clang-1.git
264 строки
8.1 KiB
C++
264 строки
8.1 KiB
C++
//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file defines the SourceLocation class.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_SOURCELOCATION_H
|
|
#define LLVM_CLANG_SOURCELOCATION_H
|
|
|
|
#include <cassert>
|
|
#include "llvm/Bitcode/SerializationFwd.h"
|
|
|
|
namespace llvm {
|
|
class MemoryBuffer;
|
|
}
|
|
|
|
namespace clang {
|
|
|
|
class SourceManager;
|
|
class FileEntry;
|
|
|
|
/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
|
|
/// a full include stack, line and column number information for a position in
|
|
/// an input translation unit.
|
|
class SourceLocation {
|
|
unsigned ID;
|
|
public:
|
|
enum {
|
|
// FileID Layout:
|
|
// bit 31: 0 -> FileID, 1 -> MacroID (invalid for FileID)
|
|
// 30...17 -> FileID of source location, index into SourceManager table.
|
|
FileIDBits = 14,
|
|
// 0...16 -> Index into the chunk of the specified FileID.
|
|
FilePosBits = 32-1-FileIDBits,
|
|
|
|
// MacroID Layout:
|
|
// bit 31: 1 -> MacroID, 0 -> FileID (invalid for MacroID)
|
|
|
|
// bit 29,30: unused.
|
|
|
|
// bits 28...9 -> MacroID number.
|
|
MacroIDBits = 20,
|
|
// bits 8...0 -> Macro Physical offset
|
|
MacroPhysOffsBits = 9,
|
|
|
|
|
|
// Useful constants.
|
|
ChunkSize = (1 << FilePosBits)
|
|
};
|
|
|
|
SourceLocation() : ID(0) {} // 0 is an invalid FileID.
|
|
|
|
bool isFileID() const { return (ID >> 31) == 0; }
|
|
bool isMacroID() const { return (ID >> 31) != 0; }
|
|
|
|
/// isValid - Return true if this is a valid SourceLocation object. Invalid
|
|
/// SourceLocations are often used when events have no corresponding location
|
|
/// in the source (e.g. a diagnostic is required for a command line option).
|
|
///
|
|
bool isValid() const { return ID != 0; }
|
|
bool isInvalid() const { return ID == 0; }
|
|
|
|
static SourceLocation getFileLoc(unsigned FileID, unsigned FilePos) {
|
|
SourceLocation L;
|
|
// If a FilePos is larger than (1<<FilePosBits), the SourceManager makes
|
|
// enough consequtive FileIDs that we have one for each chunk.
|
|
if (FilePos >= ChunkSize) {
|
|
FileID += FilePos >> FilePosBits;
|
|
FilePos &= ChunkSize-1;
|
|
}
|
|
|
|
// FIXME: Find a way to handle out of FileID bits! Maybe MaxFileID is an
|
|
// escape of some sort?
|
|
assert(FileID < (1 << FileIDBits) && "Out of fileid's");
|
|
|
|
L.ID = (FileID << FilePosBits) | FilePos;
|
|
return L;
|
|
}
|
|
|
|
static bool isValidMacroPhysOffs(int Val) {
|
|
if (Val >= 0)
|
|
return Val < (1 << (MacroPhysOffsBits-1));
|
|
return -Val < (1 << (MacroPhysOffsBits-1));
|
|
}
|
|
|
|
static SourceLocation getMacroLoc(unsigned MacroID, int PhysOffs){
|
|
assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
|
|
assert(isValidMacroPhysOffs(PhysOffs) && "Physoffs too large!");
|
|
|
|
// Mask off sign bits.
|
|
PhysOffs &= (1 << MacroPhysOffsBits)-1;
|
|
|
|
SourceLocation L;
|
|
L.ID = (1 << 31) |
|
|
(MacroID << MacroPhysOffsBits) |
|
|
PhysOffs;
|
|
return L;
|
|
}
|
|
|
|
|
|
/// getFileID - Return the file identifier for this SourceLocation. This
|
|
/// FileID can be used with the SourceManager object to obtain an entire
|
|
/// include stack for a file position reference.
|
|
unsigned getFileID() const {
|
|
assert(isFileID() && "can't get the file id of a non-file sloc!");
|
|
return ID >> FilePosBits;
|
|
}
|
|
|
|
/// getRawFilePos - Return the byte offset from the start of the file-chunk
|
|
/// referred to by FileID. This method should not be used to get the offset
|
|
/// from the start of the file, instead you should use
|
|
/// SourceManager::getDecomposedFileLoc. This method will be
|
|
// incorrect for large files.
|
|
unsigned getRawFilePos() const {
|
|
assert(isFileID() && "can't get the file id of a non-file sloc!");
|
|
return ID & (ChunkSize-1);
|
|
}
|
|
|
|
unsigned getMacroID() const {
|
|
assert(isMacroID() && "Is not a macro id!");
|
|
return (ID >> MacroPhysOffsBits) & ((1 << MacroIDBits)-1);
|
|
}
|
|
|
|
int getMacroPhysOffs() const {
|
|
assert(isMacroID() && "Is not a macro id!");
|
|
int Val = ID & ((1 << MacroPhysOffsBits)-1);
|
|
// Sign extend it properly.
|
|
unsigned ShAmt = sizeof(int)*8 - MacroPhysOffsBits;
|
|
return (Val << ShAmt) >> ShAmt;
|
|
}
|
|
|
|
/// getFileLocWithOffset - Return a source location with the specified offset
|
|
/// from this file SourceLocation.
|
|
SourceLocation getFileLocWithOffset(int Offset) const {
|
|
unsigned FileID = getFileID();
|
|
Offset += getRawFilePos();
|
|
// Handle negative offsets correctly.
|
|
while (Offset < 0) {
|
|
--FileID;
|
|
Offset += ChunkSize;
|
|
}
|
|
return getFileLoc(FileID, Offset);
|
|
}
|
|
|
|
/// getRawEncoding - When a SourceLocation itself cannot be used, this returns
|
|
/// an (opaque) 32-bit integer encoding for it. This should only be passed
|
|
/// to SourceLocation::getFromRawEncoding, it should not be inspected
|
|
/// directly.
|
|
unsigned getRawEncoding() const { return ID; }
|
|
|
|
/// getFromRawEncoding - Turn a raw encoding of a SourceLocation object into
|
|
/// a real SourceLocation.
|
|
static SourceLocation getFromRawEncoding(unsigned Encoding) {
|
|
SourceLocation X;
|
|
X.ID = Encoding;
|
|
return X;
|
|
}
|
|
|
|
/// Emit - Emit this SourceLocation object to Bitcode.
|
|
void Emit(llvm::Serializer& S) const;
|
|
|
|
/// ReadVal - Read a SourceLocation object from Bitcode.
|
|
static SourceLocation ReadVal(llvm::Deserializer& D);
|
|
};
|
|
|
|
inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
|
|
return LHS.getRawEncoding() == RHS.getRawEncoding();
|
|
}
|
|
|
|
inline bool operator!=(const SourceLocation &LHS, const SourceLocation &RHS) {
|
|
return !(LHS == RHS);
|
|
}
|
|
|
|
/// SourceRange - a trival tuple used to represent a source range.
|
|
class SourceRange {
|
|
SourceLocation B;
|
|
SourceLocation E;
|
|
public:
|
|
SourceRange(): B(SourceLocation()), E(SourceLocation()) {}
|
|
SourceRange(SourceLocation loc) : B(loc), E(loc) {}
|
|
SourceRange(SourceLocation begin, SourceLocation end) : B(begin), E(end) {}
|
|
|
|
SourceLocation getBegin() const { return B; }
|
|
SourceLocation getEnd() const { return E; }
|
|
|
|
void setBegin(SourceLocation b) { B = b; }
|
|
void setEnd(SourceLocation e) { E = e; }
|
|
|
|
bool isValid() const { return B.isValid() && E.isValid(); }
|
|
|
|
/// Emit - Emit this SourceRange object to Bitcode.
|
|
void Emit(llvm::Serializer& S) const;
|
|
|
|
/// ReadVal - Read a SourceRange object from Bitcode.
|
|
static SourceRange ReadVal(llvm::Deserializer& D);
|
|
};
|
|
|
|
/// FullSourceLoc - A tuple containing both a SourceLocation
|
|
/// and its associated SourceManager. Useful for argument passing to functions
|
|
/// that expect both objects.
|
|
class FullSourceLoc {
|
|
SourceLocation Loc;
|
|
SourceManager* SrcMgr;
|
|
public:
|
|
// Creates a FullSourceLoc where isValid() returns false.
|
|
explicit FullSourceLoc()
|
|
: Loc(SourceLocation()), SrcMgr((SourceManager*) 0) {}
|
|
|
|
explicit FullSourceLoc(SourceLocation loc, SourceManager& smgr)
|
|
: Loc(loc), SrcMgr(&smgr) {}
|
|
|
|
bool isValid() const { return Loc.isValid(); }
|
|
bool isInvalid() const { return Loc.isInvalid(); }
|
|
|
|
SourceLocation getLocation() const { return Loc; }
|
|
|
|
SourceManager& getManager() {
|
|
assert (SrcMgr && "SourceManager is NULL.");
|
|
return *SrcMgr;
|
|
}
|
|
|
|
const SourceManager& getManager() const {
|
|
assert (SrcMgr && "SourceManager is NULL.");
|
|
return *SrcMgr;
|
|
}
|
|
|
|
FullSourceLoc getLogicalLoc();
|
|
FullSourceLoc getIncludeLoc();
|
|
|
|
unsigned getLineNumber() const;
|
|
unsigned getColumnNumber() const;
|
|
|
|
unsigned getLogicalLineNumber() const;
|
|
unsigned getLogicalColumnNumber() const;
|
|
|
|
const char *getCharacterData() const;
|
|
|
|
const llvm::MemoryBuffer* getBuffer() const;
|
|
|
|
const char* getSourceName() const;
|
|
const FileEntry* getFileEntryForLoc() const;
|
|
|
|
bool isFileID() const { return Loc.isFileID(); }
|
|
|
|
bool operator==(const FullSourceLoc& RHS) const {
|
|
return SrcMgr == RHS.SrcMgr && Loc == RHS.Loc;
|
|
}
|
|
|
|
bool operator!=(const FullSourceLoc& RHS) const {
|
|
return SrcMgr != RHS.SrcMgr || Loc != RHS.Loc;
|
|
}
|
|
};
|
|
|
|
} // end namespace clang
|
|
|
|
#endif
|