return;
SourceManager& SourceMgr = TU.getContext().getSourceManager();
- unsigned ID = SourceMgr.getMainFileID();
- assert (ID && "MainFileID not set!");
+ FileID ID = SourceMgr.getMainFileID();
+ assert(!ID.isInvalid() && "MainFileID not set!");
const FileEntry* FE = SourceMgr.getFileEntryForID(ID);
- assert (FE && "No FileEntry for main file.");
+ assert(FE && "No FileEntry for main file.");
// FIXME: This is not portable to Windows.
// FIXME: This logic should probably be moved elsewhere later.
const llvm::MemoryBuffer *B = C.getBuffer();
if (!B) continue;
- unsigned FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
- Lexer L(SourceLocation::getFileLoc(FID, 0), LOpts,
+ FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User);
+ Lexer L(SM.getLocForStartOfFile(FID), LOpts,
B->getBufferStart(), B->getBufferEnd(), B);
PM[FE] = LexTokens(L);
}
DiagList &ExpectedNotes) {
// Create a raw lexer to pull all the comments out of the main file. We don't
// want to look in #include'd headers for expected-error strings.
- unsigned FileID = PP.getSourceManager().getMainFileID();
+ FileID FID = PP.getSourceManager().getMainFileID();
std::pair<const char*,const char*> File =
- PP.getSourceManager().getBufferData(FileID);
+ PP.getSourceManager().getBufferData(FID);
// Create a lexer to lex all the tokens of the main file in raw mode.
- Lexer RawLex(SourceLocation::getFileLoc(FileID, 0),
+ Lexer RawLex(PP.getSourceManager().getLocForStartOfFile(FID),
PP.getLangOptions(), File.first, File.second);
// Return comments as tokens, this is how we find expected diagnostics.
return;
// Format the file.
- unsigned FileID = R.getSourceMgr().getMainFileID();
- const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FileID);
+ FileID FID = R.getSourceMgr().getMainFileID();
+ const FileEntry* Entry = R.getSourceMgr().getFileEntryForID(FID);
- html::AddLineNumbers(R, FileID);
- html::AddHeaderFooterInternalBuiltinCSS(R, FileID, Entry->getName());
+ html::AddLineNumbers(R, FID);
+ html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
// If we have a preprocessor, relex the file and syntax highlight.
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FileID, *PP);
- if (PPF) html::HighlightMacros(R, FileID, *PP);
- html::EscapeText(R, FileID, false, true);
+ if (PP) html::SyntaxHighlight(R, FID, *PP);
+ if (PPF) html::HighlightMacros(R, FID, *PP);
+ html::EscapeText(R, FID, false, true);
// Open the output.
FILE *OutputFILE;
}
// Emit the HTML.
- const RewriteBuffer &RewriteBuf = R.getEditBuffer(FileID);
+ const RewriteBuffer &RewriteBuf = R.getEditBuffer(FID);
char *Buffer = (char*)malloc(RewriteBuf.size());
std::copy(RewriteBuf.begin(), RewriteBuf.end(), Buffer);
fwrite(Buffer, 1, RewriteBuf.size(), OutputFILE);
ASTContext *Context;
SourceManager *SM;
- unsigned MainFileID;
+ FileID MainFileID;
const char *MainFileStart, *MainFileEnd;
// Block expressions.
Preamble += "__OBJC_RW_EXTERN void *_NSConcreteStackBlock;\n";
Preamble += "#endif\n";
- InsertText(SourceLocation::getFileLoc(MainFileID, 0),
+ InsertText(SM->getLocForStartOfFile(MainFileID),
Preamble.c_str(), Preamble.size());
}
// Create a lexer to lex all the tokens of the main file in raw mode. Even
// though it is in raw mode, it will not return comments.
- Lexer RawLex(SourceLocation::getFileLoc(SM.getMainFileID(), 0),
+ Lexer RawLex(SM.getLocForStartOfFile(SM.getMainFileID()),
PP.getLangOptions(), File.first, File.second);
// Switch on comment lexing because we really do want them.
ASTContext *Context;
SourceManager *SM;
TranslationUnitDecl *TUDecl;
- unsigned MainFileID;
+ FileID MainFileID;
const char *MainFileStart, *MainFileEnd;
SourceLocation LastIncLoc;
//===----------------------------------------------------------------------===//
void RewriteObjC::RewriteInclude() {
- SourceLocation LocStart = SourceLocation::getFileLoc(MainFileID, 0);
+ SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
const char *MainBufStart = MainBuf.first;
const char *MainBufEnd = MainBuf.second;
unsigned Spaces = 8-(VCol & 7);
// Get the location of the tab.
- SourceLocation TabLoc =
- SourceLocation::getFileLoc(MainFileID, BufPtr-MainBufStart);
+ SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID);
+ TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart);
// Rewrite the single tab character into a sequence of spaces.
ReplaceText(TabLoc, 1, " ", Spaces);
RewriteInclude();
- InsertText(SourceLocation::getFileLoc(MainFileID, 0),
+ InsertText(SM->getLocForStartOfFile(MainFileID),
Preamble.c_str(), Preamble.size(), false);
if (ClassImplementation.size() || CategoryImplementation.size())
if (InFile != "-") {
const FileEntry *File = FileMgr.getFile(InFile);
if (File) SourceMgr.createMainFileID(File, SourceLocation());
- if (SourceMgr.getMainFileID() == 0) {
+ if (SourceMgr.getMainFileID().isInvalid()) {
fprintf(stderr, "Error reading '%s'!\n",InFile.c_str());
return true;
}
} else {
llvm::MemoryBuffer *SB = llvm::MemoryBuffer::getSTDIN();
if (SB) SourceMgr.createMainFileIDForMemBuffer(SB);
- if (SourceMgr.getMainFileID() == 0) {
+ if (SourceMgr.getMainFileID().isInvalid()) {
fprintf(stderr, "Error reading standard input! Empty?\n");
return true;
}
std::pair<const char*,const char*> File =
SM.getBufferData(SM.getMainFileID());
// Start lexing the specified input file.
- Lexer RawLex(SourceLocation::getFileLoc(SM.getMainFileID(), 0),
+ Lexer RawLex(SM.getLocForStartOfFile(SM.getMainFileID()),
PP.getLangOptions(), File.first, File.second);
RawLex.SetKeepWhitespaceMode(true);
#include "llvm/Bitcode/SerializationFwd.h"
namespace llvm {
-class MemoryBuffer;
+ class MemoryBuffer;
+ template <typename T> struct DenseMapInfo;
}
namespace clang {
class SourceManager;
class FileEntry;
+
+/// FileID - This is an opaque identifier used by SourceManager which refers to
+/// a source file (MemoryBuffer) along with its #include path and #line data.
+///
+class FileID {
+ /// ID - Opaque identifier, 0 is "invalid".
+ unsigned ID;
+public:
+ FileID() : ID(0) {}
+
+ bool isInvalid() const { return ID == 0; }
+
+ bool operator==(const FileID &RHS) const { return ID == RHS.ID; }
+ bool operator<(const FileID &RHS) const { return ID < RHS.ID; }
+ bool operator<=(const FileID &RHS) const { return ID <= RHS.ID; }
+ bool operator!=(const FileID &RHS) const { return !(*this == RHS); }
+ bool operator>(const FileID &RHS) const { return RHS < *this; }
+ bool operator>=(const FileID &RHS) const { return RHS <= *this; }
+
+ static FileID getSentinel() { return Create(~0U); }
+ unsigned getHashValue() const { return ID; }
+
+private:
+ friend class SourceManager;
+ static FileID Create(unsigned V) {
+ FileID F;
+ F.ID = V;
+ return F;
+ }
+ unsigned getOpaqueValue() const { return ID; }
+};
+
/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
/// a full include stack, line and column number information for a position in
} // end namespace clang
+namespace llvm {
+ /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and
+ /// DenseSets.
+ template <>
+ struct DenseMapInfo<clang::FileID> {
+ static inline clang::FileID getEmptyKey() {
+ return clang::FileID();
+ }
+ static inline clang::FileID getTombstoneKey() {
+ return clang::FileID::getSentinel();
+ }
+
+ static unsigned getHashValue(clang::FileID S) {
+ return S.getHashValue();
+ }
+
+ static bool isEqual(clang::FileID LHS, clang::FileID RHS) {
+ return LHS == RHS;
+ }
+
+ static bool isPod() { return true; }
+ };
+
+} // end namespace llvm
+
#endif
/// LastLineNo - These ivars serve as a cache used in the getLineNumber
/// method which is used to speedup getLineNumber calls to nearby locations.
- mutable unsigned LastLineNoFileIDQuery;
+ mutable FileID LastLineNoFileIDQuery;
mutable SrcMgr::ContentCache *LastLineNoContentCache;
mutable unsigned LastLineNoFilePos;
mutable unsigned LastLineNoResult;
/// MainFileID - The file ID for the main source file of the translation unit.
- unsigned MainFileID;
+ FileID MainFileID;
// SourceManager doesn't support copy construction.
explicit SourceManager(const SourceManager&);
void operator=(const SourceManager&);
public:
- SourceManager() : LastLineNoFileIDQuery(~0U), MainFileID(0) {}
+ SourceManager() {}
~SourceManager() {}
void clearIDTables() {
- MainFileID = 0;
+ MainFileID = FileID();
FileIDs.clear();
MacroIDs.clear();
- LastLineNoFileIDQuery = ~0U;
+ LastLineNoFileIDQuery = FileID();
LastLineNoContentCache = 0;
}
/// getMainFileID - Returns the FileID of the main source file.
- unsigned getMainFileID() const { return MainFileID; }
+ FileID getMainFileID() const { return MainFileID; }
/// createFileID - Create a new FileID that represents the specified file
/// being #included from the specified IncludePosition. This returns 0 on
/// error and translates NULL into standard input.
- unsigned createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
+ FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter) {
const SrcMgr::ContentCache *IR = getContentCache(SourceFile);
- if (IR == 0) return 0; // Error opening file?
+ if (IR == 0) return FileID(); // Error opening file?
return createFileID(IR, IncludePos, FileCharacter);
}
/// createMainFileID - Create the FileID for the main source file.
- unsigned createMainFileID(const FileEntry *SourceFile,
+ FileID createMainFileID(const FileEntry *SourceFile,
SourceLocation IncludePos) {
- assert (MainFileID == 0 && "MainFileID already set!");
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileID(SourceFile, IncludePos, SrcMgr::C_User);
return MainFileID;
}
/// createFileIDForMemBuffer - Create a new FileID that represents the
/// specified memory buffer. This does no caching of the buffer and takes
/// ownership of the MemoryBuffer, so only pass a MemoryBuffer to this once.
- unsigned createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
+ FileID createFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
return createFileID(createMemBufferContentCache(Buffer), SourceLocation(),
SrcMgr::C_User);
}
/// createMainFileIDForMembuffer - Create the FileID for a memory buffer
/// that will represent the FileID for the main source. One example
/// of when this would be used is when the main source is read from STDIN.
- unsigned createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
- assert (MainFileID == 0 && "MainFileID already set!");
+ FileID createMainFileIDForMemBuffer(const llvm::MemoryBuffer *Buffer) {
+ assert(MainFileID.isInvalid() && "MainFileID already set!");
MainFileID = createFileIDForMemBuffer(Buffer);
return MainFileID;
}
+ /// getLocForStartOfFile - Return the source location corresponding to the
+ /// first byte of the specified file.
+ SourceLocation getLocForStartOfFile(FileID FID) const {
+ return SourceLocation::getFileLoc(FID.ID, 0);
+ }
+
+
/// getInstantiationLoc - Return a new SourceLocation that encodes the fact
/// that a token at Loc should actually be referenced from InstantiationLoc.
SourceLocation getInstantiationLoc(SourceLocation Loc,
/// getBuffer - Return the buffer for the specified FileID.
///
- const llvm::MemoryBuffer *getBuffer(unsigned FileID) const {
- return getContentCache(FileID)->getBuffer();
+ const llvm::MemoryBuffer *getBuffer(FileID FID) const {
+ return getContentCache(FID)->getBuffer();
+ }
+
+ const llvm::MemoryBuffer *getBuffer(SourceLocation Loc) const {
+ return getContentCacheForLoc(Loc)->getBuffer();
}
+
/// getBufferData - Return a pointer to the start and end of the character
/// data for the specified FileID.
- std::pair<const char*, const char*> getBufferData(unsigned FileID) const;
+ std::pair<const char*, const char*> getBufferData(SourceLocation Loc) const;
+ std::pair<const char*, const char*> getBufferData(FileID FID) const;
/// getIncludeLoc - Return the location of the #include for the specified
/// SourceLocation. If this is a macro expansion, this transparently figures
}
/// getFileEntryForID - Returns the FileEntry record for the provided FileID.
- const FileEntry* getFileEntryForID(unsigned id) const {
- return getContentCache(id)->Entry;
+ const FileEntry *getFileEntryForID(FileID FID) const {
+ return getContentCache(FID)->Entry;
}
/// getCanonicalFileID - Return the canonical FileID for a SourceLocation.
/// into multiple chunks. This method returns the unique FileID without
/// chunk information for a given SourceLocation. Use this method when
/// you want to compare FileIDs across SourceLocations.
- unsigned getCanonicalFileID(SourceLocation SpellingLoc) const {
+ FileID getCanonicalFileID(SourceLocation SpellingLoc) const {
return getDecomposedFileLoc(SpellingLoc).first;
}
/// getDecomposedFileLoc - Decompose the specified file location into a raw
/// FileID + Offset pair. The first element is the FileID, the second is the
/// offset from the start of the buffer of the location.
- std::pair<unsigned, unsigned> getDecomposedFileLoc(SourceLocation Loc) const {
+ std::pair<FileID, unsigned> getDecomposedFileLoc(SourceLocation Loc) const {
assert(Loc.isFileID() && "Isn't a File SourceLocation");
// TODO: Add a flag "is first chunk" to SLOC.
assert(Loc.getFileID() >= ChunkNo && "Unexpected offset");
- return std::make_pair(Loc.getFileID()-ChunkNo, Offset);
+ return std::make_pair(FileID::Create(Loc.getFileID()-ChunkNo), Offset);
}
/// getFullFilePos - This (efficient) method returns the offset from the start
SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const {
return getFIDInfo(getSpellingLoc(Loc).getFileID())->getFileCharacteristic();
}
- SrcMgr::CharacteristicKind getFileCharacteristic(unsigned FileID) const {
- return getFIDInfo(FileID)->getFileCharacteristic();
+ SrcMgr::CharacteristicKind getFileCharacteristic(FileID FID) const {
+ return getFIDInfo(FID)->getFileCharacteristic();
}
// Iterators over FileInfos.
/// createFileID - Create a new fileID for the specified ContentCache and
/// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source.
- unsigned createFileID(const SrcMgr::ContentCache* File,
- SourceLocation IncludePos,
- SrcMgr::CharacteristicKind DirCharacter);
+ FileID createFileID(const SrcMgr::ContentCache* File,
+ SourceLocation IncludePos,
+ SrcMgr::CharacteristicKind DirCharacter);
/// getContentCache - Create or return a cached ContentCache for the specified
/// file. This returns null on failure.
- const SrcMgr::ContentCache* getContentCache(const FileEntry* SourceFile);
+ const SrcMgr::ContentCache* getContentCache(const FileEntry *SourceFile);
/// createMemBufferContentCache - Create a new ContentCache for the specified
/// memory buffer.
const SrcMgr::ContentCache*
- createMemBufferContentCache(const llvm::MemoryBuffer* Buf);
+ createMemBufferContentCache(const llvm::MemoryBuffer *Buf);
- const SrcMgr::FileIDInfo* getFIDInfo(unsigned FileID) const {
- assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
- return &FileIDs[FileID-1];
+ const SrcMgr::FileIDInfo *getFIDInfo(unsigned FID) const {
+ assert(FID-1 < FileIDs.size() && "Invalid FileID!");
+ return &FileIDs[FID-1];
+ }
+ const SrcMgr::FileIDInfo *getFIDInfo(FileID FID) const {
+ return getFIDInfo(FID.ID);
}
- const SrcMgr::ContentCache *getContentCache(unsigned FileID) const {
- return getContentCache(getFIDInfo(FileID));
+ const SrcMgr::ContentCache *getContentCache(FileID FID) const {
+ return getContentCache(getFIDInfo(FID.ID));
}
/// Return the ContentCache structure for the specified FileID.
class PTHSpellingSearch;
class PTHLexer : public PreprocessorLexer {
-private:
- /// FileID - The SourceManager FileID for the original source file.
- unsigned FileID;
+ SourceLocation FileStartLoc;
/// TokBuf - Buffer from PTH file containing raw token data.
const char* TokBuf;
friend class PTHManager;
/// Create a PTHLexer for the specified token stream.
- PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
- const char* ppcond,
- PTHSpellingSearch& mySpellingSrch,
- PTHManager& PM);
+ PTHLexer(Preprocessor& pp, FileID FID, const char *D, const char* ppcond,
+ PTHSpellingSearch& mySpellingSrch, PTHManager &PM);
public:
~PTHLexer() {}
const llvm::MemoryBuffer* Buf;
/// A map from FileIDs to SpellingSearch objects.
- llvm::DenseMap<unsigned,PTHSpellingSearch*> SpellingMap;
+ llvm::DenseMap<FileID, PTHSpellingSearch*> SpellingMap;
/// Alloc - Allocator used for IdentifierInfo objects.
llvm::BumpPtrAllocator Alloc;
/// Unlike the version in IdentifierTable, this returns a pointer instead
/// of a reference. If the pointer is NULL then the IdentifierInfo cannot
/// be found.
- IdentifierInfo* get(const char *NameStart, const char *NameEnd);
+ IdentifierInfo *get(const char *NameStart, const char *NameEnd);
/// Create - This method creates PTHManager objects. The 'file' argument
/// is the name of the PTH file. This method returns NULL upon failure.
- static PTHManager* Create(const std::string& file);
+ static PTHManager *Create(const std::string& file);
- void setPreprocessor(Preprocessor* pp) { PP = pp; }
+ void setPreprocessor(Preprocessor *pp) { PP = pp; }
/// CreateLexer - Return a PTHLexer that "lexes" the cached tokens for the
/// specified file. This method returns NULL if no cached tokens exist.
/// It is the responsibility of the caller to 'delete' the returned object.
- PTHLexer* CreateLexer(unsigned FileID, const FileEntry* FE);
+ PTHLexer *CreateLexer(FileID FID, const FileEntry *FE);
- unsigned getSpelling(unsigned FileID, unsigned fpos, const char *& Buffer);
+ unsigned getSpelling(SourceLocation Loc, const char *&Buffer);
+private:
+ unsigned getSpelling(FileID FID, unsigned fpos, const char *& Buffer);
};
} // end namespace clang
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. If isMainFile
/// is true, this is the main file for the translation unit.
- void EnterSourceFile(unsigned CurFileID, const DirectoryLookup *Dir);
+ void EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir);
/// EnterMacro - Add a Macro to the top of the include stack and start lexing
/// tokens from it instead of the current buffer. Args specifies the
char getSpelledCharacterAt(SourceLocation SL) const {
if (PTH) {
SL = SourceMgr.getSpellingLoc(SL);
- unsigned FID = SourceMgr.getCanonicalFileID(SL);
- unsigned FPos = SourceMgr.getFullFilePos(SL);
const char *Data;
- if (PTH->getSpelling(FID, FPos, Data))
+ if (PTH->getSpelling(SL, Data))
return *Data;
}
protected:
Preprocessor *PP; // Preprocessor object controlling lexing.
- /// The SourceManager fileID corresponding to the file being lexed.
- const unsigned FileID;
+ /// The SourceManager FileID corresponding to the file being lexed.
+ const FileID FID;
//===--------------------------------------------------------------------===//
// Context-specific lexing flags set by the preprocessor.
void operator=(const PreprocessorLexer&); // DO NOT IMPLEMENT
friend class Preprocessor;
- PreprocessorLexer(Preprocessor* pp, SourceLocation L);
-
+ PreprocessorLexer(Preprocessor *pp, FileID fid)
+ : PP(pp), FID(fid), ParsingPreprocessorDirective(false),
+ ParsingFilename(false), LexingRawMode(false) {}
+
PreprocessorLexer()
- : PP(0), FileID(0),
+ : PP(0),
ParsingPreprocessorDirective(false),
ParsingFilename(false),
LexingRawMode(false) {}
- virtual ~PreprocessorLexer();
+ virtual ~PreprocessorLexer() {}
virtual void IndirectLex(Token& Result) = 0;
/// getPP - Return the preprocessor object for this lexer.
Preprocessor *getPP() const { return PP; }
- unsigned getFileID() const {
+ FileID getFileID() const {
assert(PP &&
"PreprocessorLexer::getFileID() should only be used with a Preprocessor");
- return FileID;
+ return FID;
}
+
+ /// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+ /// getFileID(), this only works for lexers with attached preprocessors.
+ const FileEntry *getFileEntry() const;
};
} // end namespace clang
#ifndef LLVM_CLANG_SCRATCHBUFFER_H
#define LLVM_CLANG_SCRATCHBUFFER_H
+#include "clang/Basic/SourceLocation.h"
+
namespace clang {
class SourceManager;
- class SourceLocation;
/// ScratchBuffer - This class exposes a simple interface for the dynamic
/// construction of tokens. This is used for builtin macros (e.g. __LINE__) as
class ScratchBuffer {
SourceManager &SourceMgr;
char *CurBuffer;
- unsigned FileID;
+ SourceLocation BufferStartLoc;
unsigned BytesUsed;
public:
ScratchBuffer(SourceManager &SM);
/// EscapeText - HTMLize a specified file so that special characters are
/// are translated so that they are not interpreted as HTML tags.
- void EscapeText(Rewriter& R, unsigned FileID,
+ void EscapeText(Rewriter& R, FileID FID,
bool EscapeSpaces = false, bool ReplacesTabs = true);
/// EscapeText - HTMLized the provided string so that special characters
std::string EscapeText(const std::string& s,
bool EscapeSpaces = false, bool ReplaceTabs = true);
- void AddLineNumbers(Rewriter& R, unsigned FileID);
+ void AddLineNumbers(Rewriter& R, FileID FID);
- void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID,
+ void AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
const char *title = NULL);
/// SyntaxHighlight - Relex the specified FileID and annotate the HTML with
/// information about keywords, comments, etc.
- void SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP);
+ void SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP);
/// HighlightMacros - This uses the macro table state from the end of the
/// file, to reexpand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
- void HighlightMacros(Rewriter &R, unsigned FileID, Preprocessor &PP);
-
-
- void HighlightMacros(Rewriter &R, unsigned FileID, PreprocessorFactory &PPF);
-
-
-
-
-
-
+ void HighlightMacros(Rewriter &R, FileID FID, Preprocessor &PP);
+ void HighlightMacros(Rewriter &R, FileID FID, PreprocessorFactory &PPF);
} // end html namespace
} // end clang namespace
class Rewriter {
SourceManager *SourceMgr;
- std::map<unsigned, RewriteBuffer> RewriteBuffers;
+ std::map<FileID, RewriteBuffer> RewriteBuffers;
public:
explicit Rewriter(SourceManager &SM) : SourceMgr(&SM) {}
explicit Rewriter() : SourceMgr(0) {}
/// getRewriteBufferFor - Return the rewrite buffer for the specified FileID.
/// If no modification has been made to it, return null.
- const RewriteBuffer *getRewriteBufferFor(unsigned FileID) const {
- std::map<unsigned, RewriteBuffer>::const_iterator I =
- RewriteBuffers.find(FileID);
+ const RewriteBuffer *getRewriteBufferFor(FileID FID) const {
+ std::map<FileID, RewriteBuffer>::const_iterator I =
+ RewriteBuffers.find(FID);
return I == RewriteBuffers.end() ? 0 : &I->second;
}
/// buffer, and allows you to write on it directly. This is useful if you
/// want efficient low-level access to apis for scribbling on one specific
/// FileID's buffer.
- RewriteBuffer &getEditBuffer(unsigned FileID);
+ RewriteBuffer &getEditBuffer(FileID FID);
private:
- unsigned getLocationOffsetAndFileID(SourceLocation Loc,
- unsigned &FileID) const;
+ unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const;
};
} // end namespace clang
public:
/// TokenRewriter - This creates a TokenRewriter for the file with the
/// specified FileID.
- TokenRewriter(unsigned FileID, SourceManager &SM, const LangOptions &LO);
+ TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO);
~TokenRewriter();
typedef std::list<Token>::const_iterator token_iterator;
const llvm::MemoryBuffer* FullSourceLoc::getBuffer() const {
assert(isValid());
- return SrcMgr->getBuffer(getFileID());
+ return SrcMgr->getBuffer(*this);
}
void FullSourceLoc::dump() const {
/// createFileID - Create a new fileID for the specified ContentCache and
/// include position. This works regardless of whether the ContentCache
/// corresponds to a file or some other input source.
-unsigned SourceManager::createFileID(const ContentCache *File,
+FileID SourceManager::createFileID(const ContentCache *File,
SourceLocation IncludePos,
SrcMgr::CharacteristicKind FileCharacter) {
// If FileEnt is really large (e.g. it's a large .i file), we may not be able
FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File, FileCharacter));
assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
"Ran out of file ID's!");
- return FileIDs.size();
+ return FileID::Create(FileIDs.size());
}
// Create one FileID for each chunk of the file.
assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
"Ran out of file ID's!");
- return Result;
+ return FileID::Create(Result);
}
/// getInstantiationLoc - Return a new SourceLocation that encodes the fact
}
/// getBufferData - Return a pointer to the start and end of the character
-/// data for the specified FileID.
+/// data for the specified location.
std::pair<const char*, const char*>
-SourceManager::getBufferData(unsigned FileID) const {
- const llvm::MemoryBuffer *Buf = getBuffer(FileID);
+SourceManager::getBufferData(SourceLocation Loc) const {
+ const llvm::MemoryBuffer *Buf = getBuffer(Loc);
return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
}
+std::pair<const char*, const char*>
+SourceManager::getBufferData(FileID FID) const {
+ const llvm::MemoryBuffer *Buf = getBuffer(FID);
+ return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
+}
+
+
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate MemoryBuffer.
// heavily used by -E mode.
SL = getSpellingLoc(SL);
+ std::pair<FileID, unsigned> LocInfo = getDecomposedFileLoc(SL);
+
// Note that calling 'getBuffer()' may lazily page in a source file.
- return getContentCache(SL.getFileID())->getBuffer()->getBufferStart() +
- getFullFilePos(SL);
+ return getContentCache(LocInfo.first)->getBuffer()->getBufferStart() +
+ LocInfo.second;
}
/// this is significantly cheaper to compute than the line number. This returns
/// zero if the column number isn't known.
unsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
- unsigned FileID = Loc.getFileID();
- if (FileID == 0) return 0;
+ if (Loc.getFileID() == 0) return 0;
+
+ std::pair<FileID, unsigned> LocInfo = getDecomposedFileLoc(Loc);
+ unsigned FilePos = LocInfo.second;
- unsigned FilePos = getFullFilePos(Loc);
- const MemoryBuffer *Buffer = getBuffer(FileID);
- const char *Buf = Buffer->getBufferStart();
+ const char *Buf = getBuffer(LocInfo.first)->getBufferStart();
unsigned LineStart = FilePos;
while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
/// the SourceLocation specifies. This can be modified with #line directives,
/// etc.
const char *SourceManager::getSourceName(SourceLocation Loc) const {
- unsigned FileID = Loc.getFileID();
- if (FileID == 0) return "";
+ if (Loc.getFileID() == 0) return "";
// To get the source name, first consult the FileEntry (if one exists) before
// the MemBuffer as this will avoid unnecessarily paging in the MemBuffer.
- const SrcMgr::ContentCache* C = getContentCache(FileID);
+ const SrcMgr::ContentCache *C = getContentCacheForLoc(Loc);
return C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
}
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned SourceManager::getLineNumber(SourceLocation Loc) const {
- unsigned FileID = Loc.getFileID();
- if (FileID == 0) return 0;
+ if (Loc.getFileID() == 0) return 0;
- ContentCache* Content;
+ ContentCache *Content;
+
+ std::pair<FileID, unsigned> LocInfo = getDecomposedFileLoc(Loc);
- if (LastLineNoFileIDQuery == FileID)
+ if (LastLineNoFileIDQuery == LocInfo.first)
Content = LastLineNoContentCache;
else
- Content = const_cast<ContentCache*>(getContentCache(FileID));
+ Content = const_cast<ContentCache*>(getContentCache(LocInfo.first));
// If this is the first use of line information for this buffer, compute the
/// SourceLineCache for it on demand.
unsigned *SourceLineCacheStart = SourceLineCache;
unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
- unsigned QueriedFilePos = getFullFilePos(Loc)+1;
+ unsigned QueriedFilePos = LocInfo.second+1;
// If the previous query was to the same file, we know both the file pos from
// that query and the line number returned. This allows us to narrow the
// search space from the entire file to something near the match.
- if (LastLineNoFileIDQuery == FileID) {
+ if (LastLineNoFileIDQuery == LocInfo.first) {
if (QueriedFilePos >= LastLineNoFilePos) {
SourceLineCache = SourceLineCache+LastLineNoResult-1;
= std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
unsigned LineNo = Pos-SourceLineCacheStart;
- LastLineNoFileIDQuery = FileID;
+ LastLineNoFileIDQuery = LocInfo.first;
LastLineNoContentCache = Content;
LastLineNoFilePos = QueriedFilePos;
LastLineNoResult = LineNo;
void SourceManager::Emit(llvm::Serializer& S) const {
S.EnterBlock();
S.EmitPtr(this);
- S.EmitInt(MainFileID);
+ S.EmitInt(MainFileID.getOpaqueValue());
// Emit: FileInfos. Just emit the file name.
S.EnterBlock();
D.RegisterPtr(M);
// Read: the FileID of the main source file of the translation unit.
- M->MainFileID = D.ReadInt();
+ M->MainFileID = FileID::Create(D.ReadInt());
std::vector<char> Buf;
virtual void HandlePathDiagnostic(const PathDiagnostic* D);
- void HandlePiece(Rewriter& R, unsigned BugFileID,
+ void HandlePiece(Rewriter& R, FileID BugFileID,
const PathDiagnosticPiece& P, unsigned num, unsigned max);
- void HighlightRange(Rewriter& R, unsigned BugFileID, SourceRange Range);
+ void HighlightRange(Rewriter& R, FileID BugFileID, SourceRange Range);
void ReportDiag(const PathDiagnostic& D);
};
return;
SourceManager &SMgr = D.begin()->getLocation().getManager();
- unsigned FileID = 0;
- bool FileIDInitialized = false;
+ FileID FID;
// Verify that the entire path is from the same FileID.
for (PathDiagnostic::const_iterator I = D.begin(), E = D.end(); I != E; ++I) {
FullSourceLoc L = I->getLocation().getInstantiationLoc();
- if (!FileIDInitialized) {
- FileID = SMgr.getCanonicalFileID(L);
- FileIDInitialized = true;
- } else if (SMgr.getCanonicalFileID(L) != FileID)
+ if (FID.isInvalid()) {
+ FID = SMgr.getCanonicalFileID(L);
+ } else if (SMgr.getCanonicalFileID(L) != FID)
return; // FIXME: Emit a warning?
// Check the source ranges.
if (!L.isFileID())
return; // FIXME: Emit a warning?
- if (SMgr.getCanonicalFileID(L) != FileID)
+ if (SMgr.getCanonicalFileID(L) != FID)
return; // FIXME: Emit a warning?
L = SMgr.getInstantiationLoc(RI->getEnd());
if (!L.isFileID())
return; // FIXME: Emit a warning?
- if (SMgr.getCanonicalFileID(L) != FileID)
+ if (SMgr.getCanonicalFileID(L) != FID)
return; // FIXME: Emit a warning?
}
}
- if (!FileIDInitialized)
+ if (FID.isInvalid())
return; // FIXME: Emit a warning?
// Create a new rewriter to generate HTML.
for (PathDiagnostic::const_reverse_iterator I=D.rbegin(), E=D.rend();
I!=E; ++I, --n) {
- HandlePiece(R, FileID, *I, n, max);
+ HandlePiece(R, FID, *I, n, max);
}
// Add line numbers, header, footer, etc.
- // unsigned FileID = R.getSourceMgr().getMainFileID();
- html::EscapeText(R, FileID);
- html::AddLineNumbers(R, FileID);
+ // unsigned FID = R.getSourceMgr().getMainFileID();
+ html::EscapeText(R, FID);
+ html::AddLineNumbers(R, FID);
// If we have a preprocessor, relex the file and syntax highlight.
// We might not have a preprocessor if we come from a deserialized AST file,
// for example.
- if (PP) html::SyntaxHighlight(R, FileID, *PP);
+ if (PP) html::SyntaxHighlight(R, FID, *PP);
// FIXME: We eventually want to use PPF to create a fresh Preprocessor,
// once we have worked out the bugs.
//
- // if (PPF) html::HighlightMacros(R, FileID, *PPF);
+ // if (PPF) html::HighlightMacros(R, FID, *PPF);
//
- if (PP) html::HighlightMacros(R, FileID, *PP);
+ if (PP) html::HighlightMacros(R, FID, *PP);
// Get the full directory name of the analyzed file.
- const FileEntry* Entry = SMgr.getFileEntryForID(FileID);
+ const FileEntry* Entry = SMgr.getFileEntryForID(FID);
// This is a cludge; basically we want to append either the full
// working directory if we have no directory information. This is
os << "</table>\n<!-- REPORTSUMMARYEXTRA -->\n"
"<h3>Annotated Source Code</h3>\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
// Embed meta-data tags.
std::string s;
llvm::raw_string_ostream os(s);
os << "\n<!-- BUGDESC " << BugDesc << " -->\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
const std::string& BugCategory = D.getCategory();
std::string s;
llvm::raw_string_ostream os(s);
os << "\n<!-- BUGCATEGORY " << BugCategory << " -->\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
{
std::string s;
llvm::raw_string_ostream os(s);
os << "\n<!-- BUGFILE " << DirName << Entry->getName() << " -->\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
{
llvm::raw_string_ostream os(s);
os << "\n<!-- BUGLINE "
<< D.back()->getLocation().getInstantiationLineNumber() << " -->\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
{
std::string s;
llvm::raw_string_ostream os(s);
os << "\n<!-- BUGPATHLENGTH " << D.size() << " -->\n";
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, 0), os.str());
+ R.InsertStrBefore(SMgr.getLocForStartOfFile(FID), os.str());
}
// Add CSS, header, and footer.
- html::AddHeaderFooterInternalBuiltinCSS(R, FileID, Entry->getName());
+ html::AddHeaderFooterInternalBuiltinCSS(R, FID, Entry->getName());
// Get the rewrite buffer.
- const RewriteBuffer *Buf = R.getRewriteBufferFor(FileID);
+ const RewriteBuffer *Buf = R.getRewriteBufferFor(FID);
if (!Buf) {
llvm::cerr << "warning: no diagnostics generated for main file.\n";
os << *I;
}
-void HTMLDiagnostics::HandlePiece(Rewriter& R, unsigned BugFileID,
+void HTMLDiagnostics::HandlePiece(Rewriter& R, FileID BugFileID,
const PathDiagnosticPiece& P,
unsigned num, unsigned max) {
// For now, just draw a box above the line in question, and emit the
// warning.
-
FullSourceLoc Pos = P.getLocation();
if (!Pos.isValid())
return;
- SourceManager& SM = R.getSourceMgr();
+ SourceManager &SM = R.getSourceMgr();
FullSourceLoc LPos = Pos.getInstantiationLoc();
- unsigned FileID = SM.getCanonicalFileID(LPos);
-
- assert (&LPos.getManager() == &SM && "SourceManagers are different!");
+ FileID FID = SM.getCanonicalFileID(LPos);
+ assert(&LPos.getManager() == &SM && "SourceManagers are different!");
if (SM.getCanonicalFileID(LPos) != BugFileID)
return;
- const llvm::MemoryBuffer *Buf = SM.getBuffer(FileID);
+ const llvm::MemoryBuffer *Buf = SM.getBuffer(FID);
const char* FileStart = Buf->getBufferStart();
// Compute the column number. Rewind from the current position to the start
os << html::EscapeText(Msg) << "</div></td></tr>";
// Insert the new html.
- unsigned DisplayPos = 0;
-
+ unsigned DisplayPos;
switch (P.getDisplayHint()) {
- case PathDiagnosticPiece::Above:
- DisplayPos = LineStart - FileStart;
- break;
- case PathDiagnosticPiece::Below:
- DisplayPos = LineEnd - FileStart;
- break;
- default:
- assert (false && "Unhandled hint.");
+ default: assert(0 && "Unhandled hint.");
+ case PathDiagnosticPiece::Above:
+ DisplayPos = LineStart - FileStart;
+ break;
+ case PathDiagnosticPiece::Below:
+ DisplayPos = LineEnd - FileStart;
+ break;
}
-
- R.InsertStrBefore(SourceLocation::getFileLoc(FileID, DisplayPos), os.str());
+
+ SourceLocation Loc =
+ SM.getLocForStartOfFile(FID).getFileLocWithOffset(DisplayPos);
+ R.InsertStrBefore(Loc, os.str());
}
// Now highlight the ranges.
for (const SourceRange *I = P.ranges_begin(), *E = P.ranges_end();
I != E; ++I)
- HighlightRange(R, FileID, *I);
+ HighlightRange(R, FID, *I);
}
-void HTMLDiagnostics::HighlightRange(Rewriter& R, unsigned BugFileID,
+void HTMLDiagnostics::HighlightRange(Rewriter& R, FileID BugFileID,
SourceRange Range) {
SourceManager& SM = R.getSourceMgr();
#include "llvm/System/Path.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
-
using namespace clang;
-typedef llvm::DenseMap<unsigned,unsigned> FIDMap;
+
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
namespace clang {
class Preprocessor;
return new PlistDiagnostics(s);
}
-static void AddFID(FIDMap& FIDs,
- llvm::SmallVectorImpl<unsigned>& V,
+static void AddFID(FIDMap &FIDs,
+ llvm::SmallVectorImpl<FileID> &V,
SourceManager& SM, SourceLocation L) {
- unsigned fid = SM.getCanonicalFileID(SM.getInstantiationLoc(L));
- FIDMap::iterator I = FIDs.find(fid);
+ FileID FID = SM.getCanonicalFileID(SM.getInstantiationLoc(L));
+ FIDMap::iterator I = FIDs.find(FID);
if (I != FIDs.end()) return;
- FIDs[fid] = V.size();
- V.push_back(fid);
+ FIDs[FID] = V.size();
+ V.push_back(FID);
}
static unsigned GetFID(const FIDMap& FIDs,
SourceManager& SM, SourceLocation L) {
- unsigned fid = SM.getCanonicalFileID(SM.getInstantiationLoc(L));
- FIDMap::const_iterator I = FIDs.find(fid);
- assert (I != FIDs.end());
+ FileID FID = SM.getCanonicalFileID(SM.getInstantiationLoc(L));
+ FIDMap::const_iterator I = FIDs.find(FID);
+ assert(I != FIDs.end());
return I->second;
}
static llvm::raw_ostream& Indent(llvm::raw_ostream& o, const unsigned indent) {
- for (unsigned i = 0; i < indent; ++i) o << ' ';
+ for (unsigned i = 0; i < indent; ++i)
+ o << ' ';
return o;
}
// Build up a set of FIDs that we use by scanning the locations and
// ranges of the diagnostics.
FIDMap FM;
- llvm::SmallVector<unsigned, 10> Fids;
+ llvm::SmallVector<FileID, 10> Fids;
for (PathDiagnostic::const_iterator I=D->begin(), E=D->end(); I != E; ++I) {
AddFID(FM, Fids, SM, I->getLocation());
" <key>files</key>\n"
" <array>\n";
- for (llvm::SmallVectorImpl<unsigned>::iterator I=Fids.begin(), E=Fids.end();
+ for (llvm::SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
I!=E; ++I)
o << " <string>" << SM.getFileEntryForID(*I)->getName() << "</string>\n";
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the associated file buffer and Preprocessor objects will
/// outlive it, so it doesn't take ownership of either of them.
-Lexer::Lexer(SourceLocation fileloc, Preprocessor &pp,
+Lexer::Lexer(SourceLocation fileloc, Preprocessor &PP,
const char *BufStart, const char *BufEnd)
- : PreprocessorLexer(&pp, fileloc), FileLoc(fileloc),
- Features(pp.getLangOptions()) {
+// FIXME: This is really horrible and only needed for _Pragma lexers, split this
+// out of the main lexer path!
+ : PreprocessorLexer(&PP,
+ PP.getSourceManager().getCanonicalFileID(
+ PP.getSourceManager().getSpellingLoc(fileloc))),
+ FileLoc(fileloc),
+ Features(PP.getLangOptions()) {
- SourceManager &SourceMgr = PP->getSourceManager();
- unsigned InputFileID = SourceMgr.getSpellingLoc(FileLoc).getFileID();
- const llvm::MemoryBuffer *InputFile = SourceMgr.getBuffer(InputFileID);
+ SourceManager &SourceMgr = PP.getSourceManager();
+ const llvm::MemoryBuffer *InputFile = SourceMgr.getBuffer(getFileID());
Is_PragmaLexer = false;
InitCharacterInfo();
// Default to keeping comments if the preprocessor wants them.
ExtendedTokenMode = 0;
- SetCommentRetentionState(PP->getCommentRetentionState());
+ SetCommentRetentionState(PP.getCommentRetentionState());
}
/// Lexer constructor - Create a new raw lexer object. This object is only
// all obviously single-char tokens. This could use
// Lexer::isObviouslySimpleCharacter for example to handle identifiers or
// something.
-
-
- const char *BufEnd = SM.getBufferData(Loc.getFileID()).second;
+ const char *BufEnd = SM.getBufferData(Loc).second;
// Create a langops struct and enable trigraphs. This is sufficient for
// measuring tokens.
if (FileLoc.isFileID())
return SourceLocation::getFileLoc(FileLoc.getFileID(), CharNo);
+ // Otherwise, this is the _Pragma lexer case, which pretends that all of the
+ // tokens are lexed from where the _Pragma was defined.
assert(PP && "This doesn't work on raw lexers");
return GetMappedTokenLoc(*PP, FileLoc, CharNo);
}
// info about where the current file is.
const FileEntry *CurFileEnt = 0;
if (!FromDir) {
- unsigned FileID = getCurrentFileLexer()->getFileID();
- CurFileEnt = SourceMgr.getFileEntryForID(FileID);
+ FileID FID = getCurrentFileLexer()->getFileID();
+ CurFileEnt = SourceMgr.getFileEntryForID(FID);
}
// Do a standard file entry lookup.
SourceMgr.getFileCharacteristic(getCurrentFileLexer()->getFileID()));
// Look up the file, create a File ID for it.
- unsigned FileID = SourceMgr.createFileID(File, FilenameTok.getLocation(),
- FileCharacter);
- if (FileID == 0) {
+ FileID FID = SourceMgr.createFileID(File, FilenameTok.getLocation(),
+ FileCharacter);
+ if (FID.isInvalid()) {
Diag(FilenameTok, diag::err_pp_file_not_found)
<< std::string(FilenameStart, FilenameEnd);
return;
}
// Finally, if all is good, enter the new file!
- EnterSourceFile(FileID, CurDir);
+ EnterSourceFile(FID, CurDir);
}
/// HandleIncludeNextDirective - Implements #include_next.
/// EnterSourceFile - Add a source file to the top of the include stack and
/// start lexing tokens from it instead of the current buffer. Return true
/// on failure.
-void Preprocessor::EnterSourceFile(unsigned FileID,
- const DirectoryLookup *CurDir) {
+void Preprocessor::EnterSourceFile(FileID FID, const DirectoryLookup *CurDir) {
assert(CurTokenLexer == 0 && "Cannot #include a file inside a macro!");
++NumEnteredSourceFiles;
MaxIncludeStackDepth = IncludeMacroStack.size();
if (PTH) {
- PTHLexer* PL =
- PTH->CreateLexer(FileID, getSourceManager().getFileEntryForID(FileID));
+ PTHLexer *PL = PTH->CreateLexer(FID, SourceMgr.getFileEntryForID(FID));
if (PL) {
EnterSourceFileWithPTH(PL, CurDir);
}
}
- Lexer *TheLexer = new Lexer(SourceLocation::getFileLoc(FileID, 0), *this);
+ Lexer *TheLexer = new Lexer(SourceMgr.getLocForStartOfFile(FID), *this);
EnterSourceFileWithLexer(TheLexer, CurDir);
}
// Notify the client, if desired, that we are in a new source file.
if (Callbacks) {
- unsigned FileID = CurPPLexer->getFileID();
- SrcMgr::CharacteristicKind FileType =
- SourceMgr.getFileCharacteristic(CurPPLexer->getFileID());
- Callbacks->FileChanged(SourceLocation::getFileLoc(FileID, 0),
+ FileID FID = CurPPLexer->getFileID();
+ SrcMgr::CharacteristicKind FileType = SourceMgr.getFileCharacteristic(FID);
+ Callbacks->FileChanged(SourceMgr.getLocForStartOfFile(FID),
PPCallbacks::EnterFile, FileType);
}
}
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/OwningPtr.h"
-
using namespace clang;
#define DISK_TOKEN_SIZE (1+1+3+4+2)
// PTHLexer methods.
//===----------------------------------------------------------------------===//
-PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
- const char* ppcond,
- PTHSpellingSearch& mySpellingSrch,
- PTHManager& PM)
- : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
+PTHLexer::PTHLexer(Preprocessor &PP, FileID FID, const char *D,
+ const char *ppcond,
+ PTHSpellingSearch &mySpellingSrch, PTHManager &PM)
+ : PreprocessorLexer(&PP, FID), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
PPCond(ppcond), CurPPCondPtr(ppcond), MySpellingSrch(mySpellingSrch),
- PTHMgr(PM)
-{
- FileID = fileloc.getFileID();
+ PTHMgr(PM) {
+
+ FileStartLoc = PP.getSourceManager().getLocForStartOfFile(FID);
}
void PTHLexer::Lex(Token& Tok) {
Tok.setFlag(flags);
assert(!LexingRawMode);
Tok.setIdentifierInfo(perID ? PTHMgr.GetIdentifierInfo(perID-1) : 0);
- Tok.setLocation(SourceLocation::getFileLoc(FileID, FileOffset));
+ Tok.setLocation(FileStartLoc.getFileLocWithOffset(FileOffset));
Tok.setLength(Len);
//===--------------------------------------==//
| (((uint32_t) ((uint8_t) p[1])) << 8)
| (((uint32_t) ((uint8_t) p[2])) << 16)
| (((uint32_t) ((uint8_t) p[3])) << 24);
- return SourceLocation::getFileLoc(FileID, offset);
+ return FileStartLoc.getFileLocWithOffset(offset);
}
//===----------------------------------------------------------------------===//
// getSpelling() - Use cached data in PTH files for getSpelling().
//===----------------------------------------------------------------------===//
-unsigned PTHManager::getSpelling(unsigned FileID, unsigned fpos,
- const char *& Buffer) {
-
- llvm::DenseMap<unsigned,PTHSpellingSearch*>::iterator I =
- SpellingMap.find(FileID);
+unsigned PTHManager::getSpelling(FileID FID, unsigned FPos,
+ const char *&Buffer) {
+ llvm::DenseMap<FileID, PTHSpellingSearch*>::iterator I =SpellingMap.find(FID);
if (I == SpellingMap.end())
return 0;
- return I->second->getSpellingBinarySearch(fpos, Buffer);
+ return I->second->getSpellingBinarySearch(FPos, Buffer);
+}
+
+unsigned PTHManager::getSpelling(SourceLocation Loc, const char *&Buffer) {
+ std::pair<FileID, unsigned> LocInfo =
+ PP->getSourceManager().getDecomposedFileLoc(Loc);
+ return getSpelling(LocInfo.first, LocInfo.second, Buffer);
}
unsigned PTHManager::getSpellingAtPTHOffset(unsigned PTHOffset,
return 0;
}
-unsigned PTHLexer::getSpelling(SourceLocation sloc, const char *&Buffer) {
- SourceManager& SM = PP->getSourceManager();
- sloc = SM.getSpellingLoc(sloc);
- unsigned fid = SM.getCanonicalFileID(sloc);
- unsigned fpos = SM.getFullFilePos(sloc);
+unsigned PTHLexer::getSpelling(SourceLocation Loc, const char *&Buffer) {
+ SourceManager &SM = PP->getSourceManager();
+ Loc = SM.getSpellingLoc(Loc);
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedFileLoc(Loc);
+
+ FileID FID = LocInfo.first;
+ unsigned FPos = LocInfo.second;
- return (fid == FileID ) ? MySpellingSrch.getSpellingLinearSearch(fpos, Buffer)
- : PTHMgr.getSpelling(fid, fpos, Buffer);
+ if (FID == getFileID())
+ return MySpellingSrch.getSpellingLinearSearch(FPos, Buffer);
+ return PTHMgr.getSpelling(FID, FPos, Buffer);
}
//===----------------------------------------------------------------------===//
}
-PTHLexer* PTHManager::CreateLexer(unsigned FileID, const FileEntry* FE) {
-
+PTHLexer* PTHManager::CreateLexer(FileID FID, const FileEntry* FE) {
if (!FE)
return 0;
// Lookup the FileEntry object in our file lookup data structure. It will
// return a variant that indicates whether or not there is an offset within
// the PTH file that contains cached tokens.
- PTHFileLookup::Val FileData = ((PTHFileLookup*) FileLookup)->Lookup(FE);
+ PTHFileLookup::Val FileData = ((PTHFileLookup*)FileLookup)->Lookup(FE);
if (!FileData.isValid()) // No tokens available.
return 0;
// Create the SpellingSearch object for this FileID.
PTHSpellingSearch* ss = new PTHSpellingSearch(*this, len, spellingTable);
- SpellingMap[FileID] = ss;
+ SpellingMap[FID] = ss;
assert(PP && "No preprocessor set yet!");
- return new PTHLexer(*PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond,
- *ss, *this);
+ return new PTHLexer(*PP, FID, data, ppcond, *ss, *this);
}
}
// Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
- unsigned FileID = getCurrentFileLexer()->getFileID();
-
// Mark the file as a once-only file now.
- HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForID(FileID));
+ HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
}
void Preprocessor::HandlePragmaMark() {
PreprocessorLexer *TheLexer = getCurrentFileLexer();
// Mark the file as a system header.
- const FileEntry *File = SourceMgr.getFileEntryForID(TheLexer->getFileID());
- HeaderInfo.MarkFileSystemHeader(File);
+ HeaderInfo.MarkFileSystemHeader(TheLexer->getFileEntry());
// Notify the client, if desired, that we are in a new source file.
if (Callbacks)
return;
}
- unsigned FileID = getCurrentFileLexer()->getFileID();
- const FileEntry *CurFile = SourceMgr.getFileEntryForID(FileID);
+ const FileEntry *CurFile = getCurrentFileLexer()->getFileEntry();
// If this file is older than the file it depends on, emit a diagnostic.
if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
if (PTH) {
SourceLocation SLoc = SourceMgr.getSpellingLoc(Tok.getLocation());
- unsigned fid = SourceMgr.getCanonicalFileID(SLoc);
- unsigned fpos = SourceMgr.getFullFilePos(SLoc);
- if (unsigned Len = PTH->getSpelling(fid, fpos, TokStart)) {
+ if (unsigned Len = PTH->getSpelling(SLoc, TokStart)) {
assert(!Tok.needsCleaning());
return std::string(TokStart, TokStart+Len);
}
if (CurPTHLexer) {
Len = CurPTHLexer.get()->getSpelling(Tok.getLocation(), Buffer);
} else {
- SourceLocation SLoc = SourceMgr.getSpellingLoc(Tok.getLocation());
- unsigned FID = SourceMgr.getCanonicalFileID(SLoc);
- unsigned FPos = SourceMgr.getFullFilePos(SLoc);
- Len = PTH->getSpelling(FID, FPos, Buffer);
+ Len = PTH->getSpelling(SourceMgr.getSpellingLoc(Tok.getLocation()),
+ Buffer);
}
// Did we find a spelling? If so return its length. Otherwise fall
/// which implicitly adds the builtin defines etc.
void Preprocessor::EnterMainSourceFile() {
- unsigned MainFileID = SourceMgr.getMainFileID();
+ FileID MainFileID = SourceMgr.getMainFileID();
// Enter the main file source buffer.
EnterSourceFile(MainFileID, 0);
// Tell the header info that the main file was entered. If the file is later
// #imported, it won't be re-entered.
- if (const FileEntry *FE =
- SourceMgr.getFileEntryForLoc(SourceLocation::getFileLoc(MainFileID, 0)))
+ if (const FileEntry *FE = SourceMgr.getFileEntryForID(MainFileID))
HeaderInfo.IncrementIncludeCount(FE);
std::vector<char> PrologFile;
llvm::MemoryBuffer::getMemBufferCopy(&PrologFile.front(),&PrologFile.back(),
"<predefines>");
assert(SB && "Cannot fail to create predefined source buffer");
- unsigned FileID = SourceMgr.createFileIDForMemBuffer(SB);
- assert(FileID && "Could not create FileID for predefines?");
+ FileID FID = SourceMgr.createFileIDForMemBuffer(SB);
+ assert(!FID.isInvalid() && "Could not create FileID for predefines?");
// Start parsing the predefines.
- EnterSourceFile(FileID, 0);
+ EnterSourceFile(FID, 0);
}
#include "clang/Basic/SourceManager.h"
using namespace clang;
-PreprocessorLexer::PreprocessorLexer(Preprocessor* pp, SourceLocation L)
- : PP(pp), FileID(pp->getSourceManager().getSpellingLoc(L).getFileID()),
- ParsingPreprocessorDirective(false),
- ParsingFilename(false),
- LexingRawMode(false) {}
-
-PreprocessorLexer::~PreprocessorLexer() {}
-
/// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
/// (potentially) macro expand the filename.
void PreprocessorLexer::LexIncludeFilename(Token &FilenameTok) {
if (FilenameTok.is(tok::eom))
PP->Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename);
}
+
+/// getFileEntry - Return the FileEntry corresponding to this FileID. Like
+/// getFileID(), this only works for lexers with attached preprocessors.
+const FileEntry *PreprocessorLexer::getFileEntry() const {
+ return PP->getSourceManager().getFileEntryForID(getFileID());
+}
ScratchBuffer::ScratchBuffer(SourceManager &SM) : SourceMgr(SM), CurBuffer(0) {
// Set BytesUsed so that the first call to getToken will require an alloc.
BytesUsed = ScratchBufSize;
- FileID = 0;
}
/// getToken - Splat the specified text into a temporary MemoryBuffer and
assert(BytesUsed-Len < (1 << SourceLocation::FilePosBits) &&
"Out of range file position!");
- return SourceLocation::getFileLoc(FileID, BytesUsed-Len);
+ return BufferStartLoc.getFileLocWithOffset(BytesUsed-Len);
}
llvm::MemoryBuffer *Buf =
llvm::MemoryBuffer::getNewMemBuffer(RequestLen, "<scratch space>");
- FileID = SourceMgr.createFileIDForMemBuffer(Buf);
+ FileID FID = SourceMgr.createFileIDForMemBuffer(Buf);
+ BufferStartLoc = SourceMgr.getLocForStartOfFile(FID);
CurBuffer = const_cast<char*>(Buf->getBufferStart());
BytesUsed = 0;
}
SourceManager &SourceMgr = PP.getSourceManager();
const char *ResultStrData = SourceMgr.getCharacterData(ResultTokLoc);
- const llvm::MemoryBuffer *Buffer =
- SourceMgr.getBuffer(ResultTokLoc.getFileID());
+ const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ResultTokLoc);
// Make a lexer object so that we lex and expand the paste result.
Lexer TL(ResultTokLoc, PP.getLangOptions(), ResultStrData,
SourceManager &SM = R.getSourceMgr();
B = SM.getInstantiationLoc(B);
E = SM.getInstantiationLoc(E);
- unsigned FileID = SM.getCanonicalFileID(B);
- assert(SM.getCanonicalFileID(E) == FileID && "B/E not in the same file!");
+ FileID FID = SM.getCanonicalFileID(B);
+ assert(SM.getCanonicalFileID(E) == FID && "B/E not in the same file!");
unsigned BOffset = SM.getFullFilePos(B);
unsigned EOffset = SM.getFullFilePos(E);
// Include the whole end token in the range.
EOffset += Lexer::MeasureTokenLength(E, R.getSourceMgr());
- HighlightRange(R.getEditBuffer(FileID), BOffset, EOffset,
- SM.getBufferData(FileID).first, StartTag, EndTag);
+ HighlightRange(R.getEditBuffer(FID), BOffset, EOffset,
+ SM.getBufferData(FID).first, StartTag, EndTag);
}
/// HighlightRange - This is the same as the above method, but takes
}
}
-void html::EscapeText(Rewriter& R, unsigned FileID,
+void html::EscapeText(Rewriter &R, FileID FID,
bool EscapeSpaces, bool ReplaceTabs) {
- const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
const char* C = Buf->getBufferStart();
const char* FileEnd = Buf->getBufferEnd();
assert (C <= FileEnd);
- RewriteBuffer &RB = R.getEditBuffer(FileID);
+ RewriteBuffer &RB = R.getEditBuffer(FID);
unsigned ColNo = 0;
for (unsigned FilePos = 0; C != FileEnd ; ++C, ++FilePos) {
}
}
-void html::AddLineNumbers(Rewriter& R, unsigned FileID) {
+void html::AddLineNumbers(Rewriter& R, FileID FID) {
- const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
const char* FileBeg = Buf->getBufferStart();
const char* FileEnd = Buf->getBufferEnd();
const char* C = FileBeg;
- RewriteBuffer &RB = R.getEditBuffer(FileID);
+ RewriteBuffer &RB = R.getEditBuffer(FID);
assert (C <= FileEnd);
RB.InsertTextAfter(FileEnd - FileBeg, "</table>", strlen("</table>"));
}
-void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, unsigned FileID,
+void html::AddHeaderFooterInternalBuiltinCSS(Rewriter& R, FileID FID,
const char *title) {
- const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FileID);
+ const llvm::MemoryBuffer *Buf = R.getSourceMgr().getBuffer(FID);
const char* FileStart = Buf->getBufferStart();
const char* FileEnd = Buf->getBufferEnd();
- SourceLocation StartLoc = SourceLocation::getFileLoc(FileID, 0);
- SourceLocation EndLoc = SourceLocation::getFileLoc(FileID, FileEnd-FileStart);
+ SourceLocation StartLoc = R.getSourceMgr().getLocForStartOfFile(FID);
+ SourceLocation EndLoc = StartLoc.getFileLocWithOffset(FileEnd-FileStart);
std::string s;
llvm::raw_string_ostream os(s);
/// information about keywords, macro expansions etc. This uses the macro
/// table state from the end of the file, so it won't be perfectly perfect,
/// but it will be reasonably close.
-void html::SyntaxHighlight(Rewriter &R, unsigned FileID, Preprocessor &PP) {
- RewriteBuffer &RB = R.getEditBuffer(FileID);
+void html::SyntaxHighlight(Rewriter &R, FileID FID, Preprocessor &PP) {
+ RewriteBuffer &RB = R.getEditBuffer(FID);
const SourceManager &SourceMgr = PP.getSourceManager();
- std::pair<const char*, const char*> File = SourceMgr.getBufferData(FileID);
+ std::pair<const char*, const char*> File = SourceMgr.getBufferData(FID);
const char *BufferStart = File.first;
- Lexer L(SourceLocation::getFileLoc(FileID, 0), PP.getLangOptions(),
- File.first, File.second);
+ Lexer L(SourceMgr.getLocForStartOfFile(FID),
+ PP.getLangOptions(), File.first, File.second);
// Inform the preprocessor that we want to retain comments as tokens, so we
// can highlight them.
/// file, to reexpand macros and insert (into the HTML) information about the
/// macro expansions. This won't be perfectly perfect, but it will be
/// reasonably close.
-void html::HighlightMacros(Rewriter &R, unsigned FileID, Preprocessor& PP) {
+void html::HighlightMacros(Rewriter &R, FileID FID, Preprocessor& PP) {
- RewriteBuffer &RB = R.getEditBuffer(FileID);
+ RewriteBuffer &RB = R.getEditBuffer(FID);
// Inform the preprocessor that we don't want comments.
PP.SetCommentRetentionState(false, false);
// Ignore tokens whose instantiation location was not the main file.
SourceLocation LLoc = SourceMgr.getInstantiationLoc(Tok.getLocation());
- std::pair<unsigned, unsigned> LLocInfo =
+ std::pair<FileID, unsigned> LLocInfo =
SourceMgr.getDecomposedFileLoc(LLoc);
- if (LLocInfo.first != FileID) {
+ if (LLocInfo.first != FID) {
PP.Lex(Tok);
continue;
}
}
}
-void html::HighlightMacros(Rewriter &R, unsigned FileID,
+void html::HighlightMacros(Rewriter &R, FileID FID,
PreprocessorFactory &PPF) {
llvm::OwningPtr<Preprocessor> PP(PPF.CreatePreprocessor());
- HighlightMacros(R, FileID, *PP);
+ HighlightMacros(R, FID, *PP);
}
if (!isRewritable(Range.getBegin()) ||
!isRewritable(Range.getEnd())) return -1;
- unsigned StartOff, StartFileID;
- unsigned EndOff , EndFileID;
+ FileID StartFileID, EndFileID;
+ unsigned StartOff, EndOff;
StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
// If edits have been made to this buffer, the delta between the range may
// have changed.
- std::map<unsigned, RewriteBuffer>::const_iterator I =
+ std::map<FileID, RewriteBuffer>::const_iterator I =
RewriteBuffers.find(StartFileID);
if (I != RewriteBuffers.end()) {
const RewriteBuffer &RB = I->second;
!isRewritable(Range.getEnd()))
return "";
- unsigned StartOff, StartFileID;
- unsigned EndOff , EndFileID;
+ FileID StartFileID, EndFileID;
+ unsigned StartOff, EndOff;
StartOff = getLocationOffsetAndFileID(Range.getBegin(), StartFileID);
EndOff = getLocationOffsetAndFileID(Range.getEnd(), EndFileID);
// If edits have been made to this buffer, the delta between the range may
// have changed.
- std::map<unsigned, RewriteBuffer>::const_iterator I =
+ std::map<FileID, RewriteBuffer>::const_iterator I =
RewriteBuffers.find(StartFileID);
if (I == RewriteBuffers.end()) {
// If the buffer hasn't been rewritten, just return the text from the input.
}
unsigned Rewriter::getLocationOffsetAndFileID(SourceLocation Loc,
- unsigned &FileID) const {
+ FileID &FID) const {
assert(Loc.isValid() && "Invalid location");
- std::pair<unsigned,unsigned> V = SourceMgr->getDecomposedFileLoc(Loc);
- FileID = V.first;
+ std::pair<FileID,unsigned> V = SourceMgr->getDecomposedFileLoc(Loc);
+ FID = V.first;
return V.second;
}
/// getEditBuffer - Get or create a RewriteBuffer for the specified FileID.
///
-RewriteBuffer &Rewriter::getEditBuffer(unsigned FileID) {
- std::map<unsigned, RewriteBuffer>::iterator I =
- RewriteBuffers.lower_bound(FileID);
- if (I != RewriteBuffers.end() && I->first == FileID)
+RewriteBuffer &Rewriter::getEditBuffer(FileID FID) {
+ std::map<FileID, RewriteBuffer>::iterator I =
+ RewriteBuffers.lower_bound(FID);
+ if (I != RewriteBuffers.end() && I->first == FID)
return I->second;
- I = RewriteBuffers.insert(I, std::make_pair(FileID, RewriteBuffer()));
+ I = RewriteBuffers.insert(I, std::make_pair(FID, RewriteBuffer()));
- std::pair<const char*, const char*> MB = SourceMgr->getBufferData(FileID);
+ std::pair<const char*, const char*> MB = SourceMgr->getBufferData(FID);
I->second.Initialize(MB.first, MB.second);
return I->second;
bool Rewriter::InsertText(SourceLocation Loc, const char *StrData,
unsigned StrLen, bool InsertAfter) {
if (!isRewritable(Loc)) return true;
- unsigned FileID;
- unsigned StartOffs = getLocationOffsetAndFileID(Loc, FileID);
- getEditBuffer(FileID).InsertText(StartOffs, StrData, StrLen, InsertAfter);
+ FileID FID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Loc, FID);
+ getEditBuffer(FID).InsertText(StartOffs, StrData, StrLen, InsertAfter);
return false;
}
/// RemoveText - Remove the specified text region.
bool Rewriter::RemoveText(SourceLocation Start, unsigned Length) {
if (!isRewritable(Start)) return true;
- unsigned FileID;
- unsigned StartOffs = getLocationOffsetAndFileID(Start, FileID);
- getEditBuffer(FileID).RemoveText(StartOffs, Length);
+ FileID FID;
+ unsigned StartOffs = getLocationOffsetAndFileID(Start, FID);
+ getEditBuffer(FID).RemoveText(StartOffs, Length);
return false;
}
bool Rewriter::ReplaceText(SourceLocation Start, unsigned OrigLength,
const char *NewStr, unsigned NewLength) {
if (!isRewritable(Start)) return true;
- unsigned StartFileID;
+ FileID StartFileID;
unsigned StartOffs = getLocationOffsetAndFileID(Start, StartFileID);
getEditBuffer(StartFileID).ReplaceText(StartOffs, OrigLength,
#include "clang/Basic/SourceManager.h"
using namespace clang;
-TokenRewriter::TokenRewriter(unsigned FileID, SourceManager &SM,
+TokenRewriter::TokenRewriter(FileID FID, SourceManager &SM,
const LangOptions &LangOpts) {
ScratchBuf.reset(new ScratchBuffer(SM));
- std::pair<const char*,const char*> File = SM.getBufferData(FileID);
+ std::pair<const char*,const char*> File = SM.getBufferData(FID);
// Create a lexer to lex all the tokens of the main file in raw mode.
- Lexer RawLex(SourceLocation::getFileLoc(FileID, 0),
+ Lexer RawLex(SM.getLocForStartOfFile(FID),
LangOpts, File.first, File.second);
// Return all comments and whitespace as tokens.