#include <algorithm>
#include <iostream>
#include <fcntl.h>
-
using namespace clang;
using namespace SrcMgr;
using llvm::MemoryBuffer;
// FilePos field.
unsigned FileSize = File->second.Buffer->getBufferSize();
if (FileSize+1 < (1 << SourceLocation::FilePosBits)) {
- FileIDs.push_back(FileIDInfo::getNormalBuffer(IncludePos, 0, File));
+ FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File));
assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) &&
"Ran out of file ID's!");
return FileIDs.size();
unsigned ChunkNo = 0;
while (1) {
- FileIDs.push_back(FileIDInfo::getNormalBuffer(IncludePos, ChunkNo++, File));
+ FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File));
if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break;
FileSize -= (1 << SourceLocation::FilePosBits);
// Resolve InstantLoc down to a real logical location.
InstantLoc = getLogicalLoc(InstantLoc);
+ // FIXME: intelligently cache macroid's.
+ MacroIDs.push_back(MacroIDInfo::get(InstantLoc, PhysLoc));
+
+ return SourceLocation::getMacroLoc(MacroIDs.size()-1, 0, 0);
+
+#if 0
unsigned InstantiationFileID;
+
// If this is the same instantiation as was requested last time, return this
// immediately.
if (PhysLoc.getFileID() == LastInstantiationLoc_MacroFID &&
LastInstantiationLoc_InstantLoc = InstantLoc;
LastInstantiationLoc_Result = InstantiationFileID;
}
- return SourceLocation(InstantiationFileID, PhysLoc.getRawFilePos());
+ return SourceLocation::getMacroLoc(InstantiationFileID,
+ PhysLoc.getRawFilePos());
+#endif
}
const char *SourceManager::getCharacterData(SourceLocation SL) const {
// Note that this is a hot function in the getSpelling() path, which is
// heavily used by -E mode.
- unsigned FileID = SL.getFileID();
- assert(FileID && "Invalid source location!");
+ SL = getPhysicalLoc(SL);
- return getFileInfo(FileID)->Buffer->getBufferStart() + getFilePos(SL);
+ return getFileInfo(SL.getFileID())->Buffer->getBufferStart() +
+ getFullFilePos(SL);
}
-/// getIncludeLoc - Return the location of the #include for the specified
-/// FileID.
-SourceLocation SourceManager::getIncludeLoc(unsigned FileID) const {
- const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(FileID);
-
- // For Macros, the physical loc is specified by the MacroTokenFileID.
- if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
- FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
-
- return FIDInfo->IncludeLoc;
-}
-
-/// getColumnNumber - Return the column # for the specified include position.
+/// getColumnNumber - Return the column # for the specified file position.
/// 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 {
- Loc = getLogicalLoc(Loc);
unsigned FileID = Loc.getFileID();
if (FileID == 0) return 0;
- unsigned FilePos = getFilePos(Loc);
+ unsigned FilePos = getFullFilePos(Loc);
const MemoryBuffer *Buffer = getBuffer(FileID);
const char *Buf = Buffer->getBufferStart();
/// the SourceLocation specifies. This can be modified with #line directives,
/// etc.
std::string SourceManager::getSourceName(SourceLocation Loc) {
- Loc = getLogicalLoc(Loc);
unsigned FileID = Loc.getFileID();
if (FileID == 0) return "";
return getFileInfo(FileID)->Buffer->getBufferIdentifier();
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned SourceManager::getLineNumber(SourceLocation Loc) {
- Loc = getLogicalLoc(Loc);
unsigned FileID = Loc.getFileID();
if (FileID == 0) return 0;
FileInfo *FileInfo = getFileInfo(FileID);
// type approaches to make good (tight?) initial guesses based on the
// assumption that all lines are the same average size.
unsigned *Pos = std::lower_bound(SourceLineCache, SourceLineCache+NumLines,
- getFilePos(Loc)+1);
+ getFullFilePos(Loc)+1);
return Pos-SourceLineCache;
}
-/// getSourceFilePos - This method returns the *logical* offset from the start
-/// of the file that the specified SourceLocation represents. This returns
-/// the location of the *logical* character data, not the physical file
-/// position. In the case of macros, for example, this returns where the
-/// macro was instantiated, not where the characters for the macro can be
-/// found.
-unsigned SourceManager::getSourceFilePos(SourceLocation Loc) const {
-
- // If this is a macro, we need to get the instantiation location.
- const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
- while (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion) {
- Loc = FIDInfo->IncludeLoc;
- FIDInfo = getFIDInfo(Loc.getFileID());
- }
-
- return getFilePos(Loc);
-}
-
/// PrintStats - Print statistics to stderr.
///
void SourceManager::PrintStats() const {
std::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
<< " mem buffers mapped, " << FileIDs.size()
<< " file ID's allocated.\n";
- unsigned NumBuffers = 0, NumMacros = 0;
- for (unsigned i = 0, e = FileIDs.size(); i != e; ++i) {
- if (FileIDs[i].IDType == FileIDInfo::NormalBuffer)
- ++NumBuffers;
- else if (FileIDs[i].IDType == FileIDInfo::MacroExpansion)
- ++NumMacros;
- else
- assert(0 && "Unknown FileID!");
- }
- std::cerr << " " << NumBuffers << " normal buffer FileID's, "
- << NumMacros << " macro expansion FileID's.\n";
+ std::cerr << " " << FileIDs.size() << " normal buffer FileID's, "
+ << MacroIDs.size() << " macro expansion FileID's.\n";
if (OpenDiag == std::string::npos) {
fprintf(stderr,
"oops:%d: Cannot find beginning of expected error string\n",
- SourceMgr.getLineNumber(Pos));
+ SourceMgr.getLogicalLineNumber(Pos));
break;
}
if (CloseDiag == std::string::npos) {
fprintf(stderr,
"oops:%d: Cannot find end of expected error string\n",
- SourceMgr.getLineNumber(Pos));
+ SourceMgr.getLogicalLineNumber(Pos));
break;
}
for (const_diag_iterator I = diag_begin, E = diag_end; I != E; ++I)
fprintf(stderr, " Line %d: %s\n",
- SourceMgr.getLineNumber(I->first),
+ SourceMgr.getLogicalLineNumber(I->first),
I->second.c_str());
return true;
DiagList DiffList;
for (const_diag_iterator I = d1_begin, E = d1_end; I != E; ++I) {
- unsigned LineNo1 = SourceMgr.getLineNumber(I->first);
+ unsigned LineNo1 = SourceMgr.getLogicalLineNumber(I->first);
const std::string &Diag1 = I->second;
bool Found = false;
for (const_diag_iterator II = d2_begin, IE = d2_end; II != IE; ++II) {
- unsigned LineNo2 = SourceMgr.getLineNumber(II->first);
+ unsigned LineNo2 = SourceMgr.getLogicalLineNumber(II->first);
if (LineNo1 != LineNo2) continue;
const std::string &Diag2 = II->second;
return;
}
- unsigned LineNo = PP.getSourceManager().getLineNumber(Loc);
+ unsigned LineNo = PP.getSourceManager().getLogicalLineNumber(Loc);
// If this line is "close enough" to the original line, just print newlines,
// otherwise print a #line directive.
// #include directive was at.
SourceManager &SourceMgr = PP.getSourceManager();
if (Reason == PPCallbacks::EnterFile) {
- MoveToLine(SourceMgr.getIncludeLoc(Loc.getFileID()));
+ MoveToLine(SourceMgr.getIncludeLoc(Loc));
} else if (Reason == PPCallbacks::SystemHeaderPragma) {
MoveToLine(Loc);
// strange behavior.
}
+ Loc = SourceMgr.getLogicalLoc(Loc);
CurLine = SourceMgr.getLineNumber(Loc);
CurFilename = '"' + Lexer::Stringify(SourceMgr.getSourceName(Loc)) + '"';
FileType = FileType;
// Print out space characters so that the first token on a line is
// indented for easy reading.
- unsigned ColNo =
- PP.getSourceManager().getColumnNumber(Tok.getLocation());
+ const SourceManager &SourceMgr = PP.getSourceManager();
+ unsigned ColNo = SourceMgr.getLogicalColumnNumber(Tok.getLocation());
// This hack prevents stuff like:
// #define HASH #
void TextDiagnosticPrinter::
PrintIncludeStack(SourceLocation Pos) {
- unsigned FileID = Pos.getFileID();
- if (FileID == 0) return;
-
+ if (Pos.isInvalid()) return;
+
+ Pos = SourceMgr.getLogicalLoc(Pos);
+
// Print out the other include frames first.
- PrintIncludeStack(SourceMgr.getIncludeLoc(FileID));
-
+ PrintIncludeStack(SourceMgr.getIncludeLoc(Pos));
unsigned LineNo = SourceMgr.getLineNumber(Pos);
- const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
- std::cerr << "In file included from " << Buffer->getBufferIdentifier()
+ std::cerr << "In file included from " << SourceMgr.getSourceName(Pos)
<< ":" << LineNo << ":\n";
}
"Expect a correspondence between source and carat line!");
if (!R.isValid()) return;
- unsigned StartLineNo = SourceMgr.getLineNumber(R.Begin());
+ unsigned StartLineNo = SourceMgr.getLogicalLineNumber(R.Begin());
if (StartLineNo > LineNo) return; // No intersection.
- unsigned EndLineNo = SourceMgr.getLineNumber(R.End());
+ unsigned EndLineNo = SourceMgr.getLogicalLineNumber(R.End());
if (EndLineNo < LineNo) return; // No intersection.
// Compute the column number of the start.
unsigned StartColNo = 0;
if (StartLineNo == LineNo) {
- StartColNo = SourceMgr.getColumnNumber(R.Begin());
+ StartColNo = SourceMgr.getLogicalColumnNumber(R.Begin());
if (StartColNo) --StartColNo; // Zero base the col #.
}
// Compute the column number of the end.
unsigned EndColNo = CaratLine.size();
if (EndLineNo == LineNo) {
- EndColNo = SourceMgr.getColumnNumber(R.End());
+ EndColNo = SourceMgr.getLogicalColumnNumber(R.End());
if (EndColNo) {
--EndColNo; // Zero base the col #.
unsigned FileID = Loc.getFileID();
// Create a lexer starting at the beginning of this token.
- Lexer TheLexer(SourceMgr.getBuffer(FileID), FileID,
- *ThePreprocessor, StrData);
+ Lexer TheLexer(SourceMgr.getBuffer(FileID), Loc,
+ *ThePreprocessor, StrData);
LexerToken TheTok;
TheLexer.LexRawToken(TheTok);
unsigned NumStrs,
const SourceRange *Ranges,
unsigned NumRanges) {
- unsigned LineNo = 0, FilePos = 0, FileID = 0, ColNo = 0;
- unsigned LineStart = 0, LineEnd = 0;
- const llvm::MemoryBuffer *Buffer = 0;
+ unsigned LineNo = 0, ColNo = 0;
+ const char *LineStart = 0, *LineEnd = 0;
if (Pos.isValid()) {
- LineNo = SourceMgr.getLineNumber(Pos);
- FileID = SourceMgr.getLogicalLoc(Pos).getFileID();
+ SourceLocation LPos = SourceMgr.getLogicalLoc(Pos);
+ LineNo = SourceMgr.getLineNumber(LPos);
// First, if this diagnostic is not in the main file, print out the
// "included from" lines.
- if (LastWarningLoc != SourceMgr.getIncludeLoc(FileID)) {
- LastWarningLoc = SourceMgr.getIncludeLoc(FileID);
+ if (LastWarningLoc != SourceMgr.getIncludeLoc(LPos)) {
+ LastWarningLoc = SourceMgr.getIncludeLoc(LPos);
PrintIncludeStack(LastWarningLoc);
}
// Compute the column number. Rewind from the current position to the start
// of the line.
- ColNo = SourceMgr.getColumnNumber(Pos);
- FilePos = SourceMgr.getSourceFilePos(Pos);
- LineStart = FilePos-ColNo+1; // Column # is 1-based
+ ColNo = SourceMgr.getColumnNumber(LPos);
+ const char *TokLogicalPtr = SourceMgr.getCharacterData(LPos);
+ LineStart = TokLogicalPtr-ColNo+1; // Column # is 1-based
// Compute the line end. Scan forward from the error position to the end of
// the line.
- Buffer = SourceMgr.getBuffer(FileID);
- const char *Buf = Buffer->getBufferStart();
+ const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(LPos.getFileID());
const char *BufEnd = Buffer->getBufferEnd();
- LineEnd = FilePos;
- while (Buf+LineEnd != BufEnd &&
- Buf[LineEnd] != '\n' && Buf[LineEnd] != '\r')
+ LineEnd = TokLogicalPtr;
+ while (LineEnd != BufEnd &&
+ *LineEnd != '\n' && *LineEnd != '\r')
++LineEnd;
std::cerr << Buffer->getBufferIdentifier()
if (!NoCaretDiagnostics && Pos.isValid()) {
// Get the line of the source file.
- const char *Buf = Buffer->getBufferStart();
- std::string SourceLine(Buf+LineStart, Buf+LineEnd);
+ std::string SourceLine(LineStart, LineEnd);
// Create a line for the carat that is filled with spaces that is the same
// length as the line of source code.
// diagnostic.
if (Level == Diagnostic::Warning ||
Level == Diagnostic::Note) {
- SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(Pos);
- const FileEntry *F = SourceMgr.getFileEntryForFileID(PhysLoc.getFileID());
- if (F) {
+ if (const FileEntry *F = SourceMgr.getFileEntryForLoc(Pos)) {
DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
if (DirInfo == DirectoryLookup::SystemHeaderDir ||
DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
#include "llvm/Support/MemoryBuffer.h"
#include <cctype>
using namespace clang;
static void InitCharacterInfo();
-Lexer::Lexer(const llvm::MemoryBuffer *File, unsigned fileid, Preprocessor &pp,
- const char *BufStart, const char *BufEnd)
+Lexer::Lexer(const llvm::MemoryBuffer *File, SourceLocation fileloc,
+ Preprocessor &pp, const char *BufStart, const char *BufEnd)
: BufferEnd(BufEnd ? BufEnd : File->getBufferEnd()),
- InputFile(File), CurFileID(fileid), PP(pp), Features(PP.getLangOptions()) {
+ InputFile(File), FileLoc(fileloc), PP(pp), Features(PP.getLangOptions()) {
Is_PragmaLexer = false;
IsMainFile = false;
InitCharacterInfo();
SourceLocation Lexer::getSourceLocation(const char *Loc) const {
assert(Loc >= InputFile->getBufferStart() && Loc <= BufferEnd &&
"Location out of range for this buffer!");
- return SourceLocation(CurFileID, Loc-InputFile->getBufferStart());
+
+ // In the normal case, we're just lexing from a simple file buffer, return
+ // the file id from FileLoc with the offset specified.
+ unsigned CharNo = Loc-InputFile->getBufferStart();
+ if (FileLoc.isFileID())
+ return SourceLocation::getFileLoc(FileLoc.getFileID(), CharNo);
+
+ // Otherwise, we're lexing "mapped tokens". This is used for things like
+ // _Pragma handling. Combine the instantiation location of FileLoc with the
+ // physical location.
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // Create a new SLoc which is expanded from logical(FileLoc) but whose
+ // characters come from phys(FileLoc)+Offset.
+ SourceLocation VirtLoc = SourceMgr.getLogicalLoc(FileLoc);
+ SourceLocation PhysLoc = SourceMgr.getPhysicalLoc(FileLoc);
+ PhysLoc = SourceLocation::getFileLoc(PhysLoc.getFileID(), CharNo);
+ return SourceMgr.getInstantiationLoc(PhysLoc, VirtLoc);
}
assert(FileID && "Could not get FileID for paste?");
// Make a lexer object so that we lex and expand the paste result.
- Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, PP,
+ Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID),
+ SourceLocation::getFileLoc(FileID, 0), PP,
ResultStrData,
ResultStrData+LHSLen+RHSLen /*don't include null*/);
SourceLocation TokLoc = CreateString(&StrVal[0], StrVal.size(), StrLoc);
const char *StrData = SourceMgr.getCharacterData(TokLoc);
- unsigned FileID = TokLoc.getFileID();
+ unsigned FileID = SourceMgr.getPhysicalLoc(TokLoc).getFileID();
assert(FileID && "Could not get FileID for _Pragma?");
// Make and enter a lexer object so that we lex and expand the tokens just
// like any others.
- Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), FileID, *this,
+ Lexer *TL = new Lexer(SourceMgr.getBuffer(FileID), TokLoc, *this,
StrData, StrData+StrVal.size()-1 /* no null */);
// Ensure that the lexer thinks it is inside a directive, so that end \n will
}
// Get the current file lexer we're looking at. Ignore _Pragma 'files' etc.
- unsigned FileID = getCurrentFileLexer()->getCurFileID();
+ SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
// Mark the file as a once-only file now.
- HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForFileID(FileID));
+ HeaderInfo.MarkFileIncludeOnce(SourceMgr.getFileEntryForLoc(FileLoc));
}
/// HandlePragmaPoison - Handle #pragma GCC poison. PoisonTok is the 'poison'.
Lexer *TheLexer = getCurrentFileLexer();
// Mark the file as a system header.
- const FileEntry *File =
- SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
+ const FileEntry *File = SourceMgr.getFileEntryForLoc(TheLexer->getFileLoc());
HeaderInfo.MarkFileSystemHeader(File);
// Notify the client, if desired, that we are in a new source file.
return Diag(FilenameTok, diag::err_pp_file_not_found,
std::string(FilenameStart, FilenameEnd));
- unsigned FileID = getCurrentFileLexer()->getCurFileID();
- const FileEntry *CurFile = SourceMgr.getFileEntryForFileID(FileID);
+ SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
+ const FileEntry *CurFile = SourceMgr.getFileEntryForLoc(FileLoc);
// If this file is older than the file it depends on, emit a diagnostic.
if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
/// token, return a new location that specifies a character within the token.
SourceLocation Preprocessor::AdvanceToTokenCharacter(SourceLocation TokStart,
unsigned CharNo) {
- // If they request the first char of the token, we're trivially done.
- if (CharNo == 0) return TokStart;
+ // If they request the first char of the token, we're trivially done. If this
+ // is a macro expansion, it doesn't make sense to point to a character within
+ // the instantiation point (the name). We could point to the source
+ // character, but without also pointing to instantiation info, this is
+ // confusing.
+ if (CharNo == 0 || TokStart.isMacroID()) return TokStart;
// Figure out how many physical characters away the specified logical
// character is. This needs to take into consideration newlines and
// trigraphs.
- const char *TokStartPtr = SourceMgr.getCharacterData(TokStart);
- const char *TokPtr = TokStartPtr;
+ const char *TokPtr = SourceMgr.getCharacterData(TokStart);
+ unsigned PhysOffset = 0;
// The usual case is that tokens don't contain anything interesting. Skip
// over the uninteresting characters. If a token only consists of simple
// chars, this method is extremely fast.
while (CharNo && Lexer::isObviouslySimpleCharacter(*TokPtr))
- ++TokPtr, --CharNo;
+ ++TokPtr, --CharNo, ++PhysOffset;
// If we have a character that may be a trigraph or escaped newline, create a
// lexer to parse it correctly.
- unsigned FileID = TokStart.getFileID();
- const llvm::MemoryBuffer *SrcBuf = SourceMgr.getBuffer(FileID);
if (CharNo != 0) {
// Create a lexer starting at this token position.
- Lexer TheLexer(SrcBuf, FileID, *this, TokPtr);
+ const llvm::MemoryBuffer *SrcBuf =SourceMgr.getBuffer(TokStart.getFileID());
+ Lexer TheLexer(SrcBuf, TokStart, *this, TokPtr);
LexerToken Tok;
// Skip over characters the remaining characters.
+ const char *TokStartPtr = TokPtr;
for (; CharNo; --CharNo)
TheLexer.getAndAdvanceChar(TokPtr, Tok);
+
+ PhysOffset += TokPtr-TokStartPtr;
}
- return SourceLocation(FileID, TokPtr-SrcBuf->getBufferStart());
+
+ return TokStart.getFileLocWithOffset(PhysOffset);
}
// info about where the current file is.
const FileEntry *CurFileEnt = 0;
if (!FromDir) {
- unsigned TheFileID = getCurrentFileLexer()->getCurFileID();
- CurFileEnt = SourceMgr.getFileEntryForFileID(TheFileID);
+ SourceLocation FileLoc = getCurrentFileLexer()->getFileLoc();
+ CurFileEnt = SourceMgr.getFileEntryForLoc(FileLoc);
}
// Do a standard file entry lookup.
// to one of the headers on the #include stack. Walk the list of the current
// headers on the #include stack and pass them to HeaderInfo.
if (CurLexer && !CurLexer->Is_PragmaLexer) {
- CurFileEnt = SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID());
+ CurFileEnt = SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc());
if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, FilenameEnd,
CurFileEnt)))
return FE;
for (unsigned i = 0, e = IncludeMacroStack.size(); i != e; ++i) {
IncludeStackInfo &ISEntry = IncludeMacroStack[e-i-1];
if (ISEntry.TheLexer && !ISEntry.TheLexer->Is_PragmaLexer) {
- CurFileEnt =
- SourceMgr.getFileEntryForFileID(ISEntry.TheLexer->getCurFileID());
+ CurFileEnt = SourceMgr.getFileEntryForLoc(ISEntry.TheLexer->getFileLoc());
if ((FE = HeaderInfo.LookupSubframeworkHeader(FilenameStart, FilenameEnd,
CurFileEnt)))
return FE;
MaxIncludeStackDepth = IncludeMacroStack.size();
const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FileID);
- Lexer *TheLexer = new Lexer(Buffer, FileID, *this);
+ Lexer *TheLexer = new Lexer(Buffer, SourceLocation::getFileLoc(FileID, 0),
+ *this);
if (isMainFile) TheLexer->setIsMainFile();
EnterSourceFileWithLexer(TheLexer, CurDir);
}
// Get the file entry for the current file.
if (const FileEntry *FE =
- SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+ SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
FileType = HeaderInfo.getFileDirFlavor(FE);
- Callbacks->FileChanged(SourceLocation(CurLexer->getCurFileID(), 0),
+ Callbacks->FileChanged(CurLexer->getFileLoc(),
PPCallbacks::EnterFile, FileType);
}
}
if (II == Ident__LINE__) {
// __LINE__ expands to a simple numeric value.
- sprintf(TmpBuffer, "%u", SourceMgr.getLineNumber(Tok.getLocation()));
+ sprintf(TmpBuffer, "%u", SourceMgr.getLogicalLineNumber(Tok.getLocation()));
unsigned Length = strlen(TmpBuffer);
Tok.setKind(tok::numeric_constant);
Tok.setLength(Length);
SourceLocation Loc = Tok.getLocation();
if (II == Ident__BASE_FILE__) {
Diag(Tok, diag::ext_pp_base_file);
- SourceLocation NextLoc = SourceMgr.getIncludeLoc(Loc.getFileID());
- while (NextLoc.getFileID() != 0) {
+ SourceLocation NextLoc = SourceMgr.getIncludeLoc(Loc);
+ while (NextLoc.isValid()) {
Loc = NextLoc;
- NextLoc = SourceMgr.getIncludeLoc(Loc.getFileID());
+ NextLoc = SourceMgr.getIncludeLoc(Loc);
}
}
// Escape this filename. Turn '\' -> '\\' '"' -> '\"'
- std::string FN = SourceMgr.getSourceName(Loc);
+ std::string FN = SourceMgr.getSourceName(SourceMgr.getLogicalLoc(Loc));
FN = '"' + Lexer::Stringify(FN) + '"';
Tok.setKind(tok::string_literal);
Tok.setLength(FN.size());
// Compute the include depth of this token.
unsigned Depth = 0;
- SourceLocation Loc = SourceMgr.getIncludeLoc(Tok.getLocation().getFileID());
- for (; Loc.getFileID() != 0; ++Depth)
- Loc = SourceMgr.getIncludeLoc(Loc.getFileID());
+ SourceLocation Loc = SourceMgr.getIncludeLoc(Tok.getLocation());
+ for (; Loc.isValid(); ++Depth)
+ Loc = SourceMgr.getIncludeLoc(Loc);
// __INCLUDE_LEVEL__ expands to a simple numeric value.
sprintf(TmpBuffer, "%u", Depth);
Lexer *TheLexer = getCurrentFileLexer();
if (TheLexer)
- CurFile = SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
+ CurFile = SourceMgr.getFileEntryForLoc(TheLexer->getFileLoc());
// If this file is older than the file it depends on, emit a diagnostic.
const char *Result;
CurLexer->MIOpt.GetControllingMacroAtEndOfFile()) {
// Okay, this has a controlling macro, remember in PerFileInfo.
if (const FileEntry *FE =
- SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+ SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
HeaderInfo.SetFileControllingMacro(FE, ControllingMacro);
}
}
// Get the file entry for the current file.
if (const FileEntry *FE =
- SourceMgr.getFileEntryForFileID(CurLexer->getCurFileID()))
+ SourceMgr.getFileEntryForLoc(CurLexer->getFileLoc()))
FileType = HeaderInfo.getFileDirFlavor(FE);
Callbacks->FileChanged(CurLexer->getSourceLocation(CurLexer->BufferPtr),
assert(BytesUsed-Len < (1 << SourceLocation::FilePosBits) &&
"Out of range file position!");
- return SourceLocation(FileID, BytesUsed-Len);
+ return SourceLocation::getFileLoc(FileID, BytesUsed-Len);
}
#ifndef LLVM_CLANG_SOURCELOCATION_H
#define LLVM_CLANG_SOURCELOCATION_H
+#include <cassert>
+
namespace clang {
/// SourceLocation - This is a carefully crafted 32-bit identifier that encodes
public:
enum {
FileIDBits = 14,
- FilePosBits = 32-FileIDBits
+ FilePosBits = 32-1-FileIDBits,
+
+ MacroIDBits = 23,
+ MacroPhysOffsBits = 5,
+ MacroLogOffBits = 3
};
SourceLocation() : ID(0) {} // 0 is an invalid FileID.
- /// SourceLocation constructor - Create a new SourceLocation object with the
- /// specified FileID and FilePos.
- SourceLocation(unsigned FileID, unsigned FilePos) {
+ bool isFileID() const { return (ID >> 31) == 0; }
+ bool isMacroID() const { return (ID >> 31) != 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 >= (1 << FilePosBits)) {
if (FileID >= (1 << FileIDBits))
FileID = (1 << FileIDBits)-1;
- ID = (FileID << FilePosBits) | FilePos;
+ L.ID = (FileID << FilePosBits) | FilePos;
+ return L;
}
+ static SourceLocation getMacroLoc(unsigned MacroID, unsigned PhysOffs,
+ unsigned LogOffs) {
+ SourceLocation L;
+
+ assert(MacroID < (1 << MacroIDBits) && "Too many macros!");
+ assert(PhysOffs < (1 << MacroPhysOffsBits) && "Physoffs too large!");
+ assert(LogOffs < (1 << MacroLogOffBits) && "Logical offs too large!");
+
+ L.ID = (1 << 31) | (MacroID << (MacroPhysOffsBits+MacroLogOffBits)) |
+ (PhysOffs << MacroLogOffBits) | LogOffs;
+ return L;
+ }
+
+
/// 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; }
/// 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 { return ID >> FilePosBits; }
+ 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::getFilePos. This method will be incorrect for large files.
- unsigned getRawFilePos() const { return ID & ((1 << FilePosBits)-1); }
+ unsigned getRawFilePos() const {
+ assert(isFileID() && "can't get the file id of a non-file sloc!");
+ return ID & ((1 << FilePosBits)-1);
+ }
+
+ unsigned getMacroID() const {
+ assert(isMacroID() && "Is not a macro id!");
+ return (ID >> (MacroPhysOffsBits+MacroLogOffBits)) & ((1 << MacroIDBits)-1);
+ }
+
+ unsigned getMacroPhysOffs() const {
+ assert(isMacroID() && "Is not a macro id!");
+ return (ID >> MacroLogOffBits) & ((1 << MacroPhysOffsBits)-1);
+ }
+
+ unsigned getMacroLogOffs() const {
+ assert(isMacroID() && "Is not a macro id!");
+ return ID & ((1 << MacroPhysOffsBits)-1);
+ }
+ /// getFileLocWithOffset - Return a source location with the specified offset
+ /// from this file SourceLocation.
+ SourceLocation getFileLocWithOffset(unsigned Offset) const {
+ return getFileLoc(getFileID(), getRawFilePos()+Offset);
+ }
/// getRawEncoding - When a SourceLocation itself cannot be used, this returns
/// an (opaque) 32-bit integer encoding for it. This should only be passed
/// from MacroTokenFileID.
///
struct FileIDInfo {
- enum FileIDType {
- NormalBuffer,
- MacroExpansion
- };
-
- /// The type of this FileID.
- FileIDType IDType;
-
+ private:
/// IncludeLoc - The location of the #include that brought in this file.
- /// This SourceLocation object has a FileId of 0 for the main file.
+ /// This SourceLocation object has an invalid SLOC for the main file.
SourceLocation IncludeLoc;
- /// This union is discriminated by IDType.
+ /// ChunkNo - Really large buffers are broken up into chunks that are
+ /// each (1 << SourceLocation::FilePosBits) in size. This specifies the
+ /// chunk number of this FileID.
+ unsigned ChunkNo;
+
+ /// FileInfo - Information about the source buffer itself.
///
- union {
- struct NormalBufferInfo {
- /// ChunkNo - Really large buffers are broken up into chunks that are
- /// each (1 << SourceLocation::FilePosBits) in size. This specifies the
- /// chunk number of this FileID.
- unsigned ChunkNo;
-
- /// FileInfo - Information about the source buffer itself.
- ///
- const InfoRec *Info;
- } NormalBuffer;
-
- /// MacroTokenFileID - This is the File ID that contains the characters
- /// that make up the expanded token.
- unsigned MacroTokenFileID;
- } u;
+ const InfoRec *Info;
+ public:
- /// getNormalBuffer - Return a FileIDInfo object for a normal buffer
- /// reference.
- static FileIDInfo getNormalBuffer(SourceLocation IL, unsigned CN,
- const InfoRec *Inf) {
+ /// get - Return a FileIDInfo object.
+ static FileIDInfo get(SourceLocation IL, unsigned CN, const InfoRec *Inf) {
FileIDInfo X;
- X.IDType = NormalBuffer;
X.IncludeLoc = IL;
- X.u.NormalBuffer.ChunkNo = CN;
- X.u.NormalBuffer.Info = Inf;
+ X.ChunkNo = CN;
+ X.Info = Inf;
return X;
}
- /// getMacroExpansion - Return a FileID for a macro expansion. IL specifies
- /// the instantiation location, and MacroFID specifies the FileID that the
- /// token's characters come from.
- static FileIDInfo getMacroExpansion(SourceLocation IL,
- unsigned MacroFID) {
- FileIDInfo X;
- X.IDType = MacroExpansion;
- X.IncludeLoc = IL;
- X.u.MacroTokenFileID = MacroFID;
- return X;
- }
+ SourceLocation getIncludeLoc() const { return IncludeLoc; }
+ unsigned getChunkNo() const { return ChunkNo; }
+ const InfoRec *getInfo() const { return Info; }
+ };
+
+ class MacroIDInfo {
+ SourceLocation InstantiationLoc, PhysicalLoc;
+ public:
+ SourceLocation getInstantiationLoc() const { return InstantiationLoc; }
+ SourceLocation getPhysicalLoc() const { return PhysicalLoc; }
- unsigned getNormalBufferChunkNo() const {
- assert(IDType == NormalBuffer && "Not a normal buffer!");
- return u.NormalBuffer.ChunkNo;
- }
-
- const InfoRec *getNormalBufferInfo() const {
- assert(IDType == NormalBuffer && "Not a normal buffer!");
- return u.NormalBuffer.Info;
+ /// get - Return a MacroID for a macro expansion. IL specifies
+ /// the instantiation location, and PL specifies the physical location
+ /// (where the characters from the token come from). Both IL and PL refer
+ /// to normal File SLocs.
+ static MacroIDInfo get(SourceLocation IL, SourceLocation PL) {
+ MacroIDInfo X;
+ X.InstantiationLoc = IL;
+ X.PhysicalLoc = PL;
+ return X;
}
};
} // end SrcMgr namespace.
/// entries are off by one.
std::vector<SrcMgr::FileIDInfo> FileIDs;
+ /// MacroIDs - Information about each MacroID.
+ std::vector<SrcMgr::MacroIDInfo> MacroIDs;
+
/// LastInstantiationLoc_* - Cache the last instantiation request for fast
/// lookup. Macros often want many tokens instantated at the same location.
SourceLocation LastInstantiationLoc_InstantLoc;
}
/// getIncludeLoc - Return the location of the #include for the specified
- /// FileID.
- SourceLocation getIncludeLoc(unsigned FileID) const;
-
- /// getFilePos - This (efficient) method returns the offset from the start of
- /// the file that the specified SourceLocation represents. This returns the
- /// location of the physical character data, not the logical file position.
- unsigned getFilePos(SourceLocation Loc) const {
- const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
-
- // For Macros, the physical loc is specified by the MacroTokenFileID.
- if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
- FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
-
- // If this file has been split up into chunks, factor in the chunk number
- // that the FileID references.
- unsigned ChunkNo = FIDInfo->getNormalBufferChunkNo();
- return Loc.getRawFilePos() + (ChunkNo << SourceLocation::FilePosBits);
+ /// SourceLocation. If this is a macro expansion, this transparently figures
+ /// out which file includes the file being expanded into.
+ SourceLocation getIncludeLoc(SourceLocation ID) const {
+ return getFIDInfo(getLogicalLoc(ID).getFileID())->getIncludeLoc();
}
/// getCharacterData - Return a pointer to the start of the specified location
/// in the appropriate MemoryBuffer.
const char *getCharacterData(SourceLocation SL) const;
- /// getColumnNumber - Return the column # for the specified include position.
- /// this is significantly cheaper to compute than the line number. This
- /// returns zero if the column number isn't known.
+ /// getColumnNumber - Return the column # for the specified file position.
+ /// This is significantly cheaper to compute than the line number. This
+ /// returns zero if the column number isn't known. This may only be called on
+ /// a file sloc, so you must choose a physical or logical location before
+ /// calling this method.
unsigned getColumnNumber(SourceLocation Loc) const;
+ unsigned getPhysicalColumnNumber(SourceLocation Loc) const {
+ return getColumnNumber(getPhysicalLoc(Loc));
+ }
+ unsigned getLogicalColumnNumber(SourceLocation Loc) const {
+ return getColumnNumber(getLogicalLoc(Loc));
+ }
+
+
/// getLineNumber - Given a SourceLocation, return the physical line number
/// for the position indicated. This requires building and caching a table of
/// line offsets for the MemoryBuffer, so this is not cheap: use only when
/// about to emit a diagnostic.
unsigned getLineNumber(SourceLocation Loc);
+
+ unsigned getLogicalLineNumber(SourceLocation Loc) {
+ return getLineNumber(getLogicalLoc(Loc));
+ }
+ unsigned getPhysicalLineNumber(SourceLocation Loc) {
+ return getLineNumber(getPhysicalLoc(Loc));
+ }
- /// getSourceFilePos - This method returns the *logical* offset from the start
- /// of the file that the specified SourceLocation represents. This returns
- /// the location of the *logical* character data, not the physical file
- /// position. In the case of macros, for example, this returns where the
- /// macro was instantiated, not where the characters for the macro can be
- /// found.
- unsigned getSourceFilePos(SourceLocation Loc) const;
-
/// getSourceName - This method returns the name of the file or buffer that
/// the SourceLocation specifies. This can be modified with #line directives,
/// etc.
std::string getSourceName(SourceLocation Loc);
- /// getFileEntryForFileID - Return the FileEntry record for the specified
- /// FileID if one exists.
- const FileEntry *getFileEntryForFileID(unsigned FileID) const {
- assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
- return FileIDs[FileID-1].getNormalBufferInfo()->first;
- }
-
/// Given a SourceLocation object, return the logical location referenced by
/// the ID. This logical location is subject to #line directives, etc.
SourceLocation getLogicalLoc(SourceLocation Loc) const {
- if (Loc.getFileID() == 0) return Loc;
-
- const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
- if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
- return FIDInfo->IncludeLoc;
- return Loc;
+ // File locations are both physical and logical.
+ if (Loc.isFileID()) return Loc;
+
+ SourceLocation ILoc = MacroIDs[Loc.getMacroID()].getInstantiationLoc();
+ return ILoc.getFileLocWithOffset(Loc.getMacroLogOffs());
}
/// getPhysicalLoc - Given a SourceLocation object, return the physical
/// location referenced by the ID.
SourceLocation getPhysicalLoc(SourceLocation Loc) const {
- if (Loc.getFileID() == 0) return Loc;
+ // File locations are both physical and logical.
+ if (Loc.isFileID()) return Loc;
- // For Macros, the physical loc is specified by the MacroTokenFileID.
- const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(Loc.getFileID());
- if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
- return SourceLocation(FIDInfo->u.MacroTokenFileID,
- Loc.getRawFilePos());
- return Loc;
+ SourceLocation ILoc = MacroIDs[Loc.getMacroID()].getPhysicalLoc();
+ return ILoc.getFileLocWithOffset(Loc.getMacroPhysOffs());
+ }
+
+ /// getFileEntryForLoc - Return the FileEntry record for the physloc of the
+ /// specified SourceLocation, if one exists.
+ const FileEntry *getFileEntryForLoc(SourceLocation Loc) const {
+ Loc = getPhysicalLoc(Loc);
+ unsigned FileID = Loc.getFileID();
+ assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
+ return FileIDs[FileID-1].getInfo()->first;
}
/// PrintStats - Print statistics to stderr.
assert(FileID-1 < FileIDs.size() && "Invalid FileID!");
return &FileIDs[FileID-1];
}
-
- /// Return the InfoRec structure for the specified FileID. This is always the
- /// physical reference for the ID.
- const SrcMgr::InfoRec *getInfoRec(const SrcMgr::FileIDInfo *FIDInfo) const {
- // For Macros, the physical loc is specified by the MacroTokenFileID.
- if (FIDInfo->IDType == SrcMgr::FileIDInfo::MacroExpansion)
- FIDInfo = &FileIDs[FIDInfo->u.MacroTokenFileID-1];
- return FIDInfo->getNormalBufferInfo();
- }
+
const SrcMgr::InfoRec *getInfoRec(unsigned FileID) const {
return getInfoRec(getFIDInfo(FileID));
}
- SrcMgr::FileInfo *getFileInfo(const SrcMgr::FileIDInfo *FIDInfo) const {
- if (const SrcMgr::InfoRec *IR = getInfoRec(FIDInfo))
- return const_cast<SrcMgr::FileInfo *>(&IR->second);
- return 0;
- }
SrcMgr::FileInfo *getFileInfo(unsigned FileID) const {
if (const SrcMgr::InfoRec *IR = getInfoRec(FileID))
return const_cast<SrcMgr::FileInfo *>(&IR->second);
return 0;
}
- SrcMgr::FileInfo *getFileInfo(const FileEntry *SourceFile) {
- if (const SrcMgr::InfoRec *IR = getInfoRec(SourceFile))
- return const_cast<SrcMgr::FileInfo *>(&IR->second);
- return 0;
+
+ /// Return the InfoRec structure for the specified FileID. This is always the
+ /// physical reference for the ID.
+ const SrcMgr::InfoRec *getInfoRec(const SrcMgr::FileIDInfo *FIDInfo) const {
+ return FIDInfo->getInfo();
+ }
+
+
+ /// getFullFilePos - This (efficient) method returns the offset from the start
+ /// of the file that the specified physical SourceLocation represents. This
+ /// returns the location of the physical character data, not the logical file
+ /// position.
+ unsigned getFullFilePos(SourceLocation PhysLoc) const {
+ // TODO: Add a flag "is first chunk" to SLOC.
+ const SrcMgr::FileIDInfo *FIDInfo = getFIDInfo(PhysLoc.getFileID());
+
+ // If this file has been split up into chunks, factor in the chunk number
+ // that the FileID references.
+ unsigned ChunkNo = FIDInfo->getChunkNo();
+ return PhysLoc.getRawFilePos() + (ChunkNo << SourceLocation::FilePosBits);
}
};
// Constant configuration values for this lexer.
const char * const BufferEnd; // End of the buffer.
const llvm::MemoryBuffer *InputFile; // The file we are reading from.
- unsigned CurFileID; // FileID for the current input file.
+ SourceLocation FileLoc; // Location for start of file.
Preprocessor &PP; // Preprocessor object controlling lexing.
LangOptions Features; // Features enabled by this language (cache).
bool Is_PragmaLexer; // True if lexer for _Pragma handling.
/// with the specified preprocessor managing the lexing process. This lexer
/// assumes that the specified MemoryBuffer and Preprocessor objects will
/// outlive it, but doesn't take ownership of either pointer.
- Lexer(const llvm::MemoryBuffer *InBuffer, unsigned CurFileID,
- Preprocessor &PP, const char *BufStart = 0, const char *BufEnd = 0);
+ Lexer(const llvm::MemoryBuffer *InBuffer, SourceLocation FileLoc,
+ Preprocessor &PP, const char *BufStart = 0, const char *BufEnd = 0);
/// getFeatures - Return the language features currently enabled. NOTE: this
/// lexer modifies features as a file is parsed!
const LangOptions &getFeatures() const { return Features; }
- /// getCurFileID - Return the FileID for the file we are lexing out of. This
- /// implicitly encodes the include path to get to the file.
- unsigned getCurFileID() const { return CurFileID; }
+ /// getFileLoc - Return the File Location for the file we are lexing out of.
+ /// The physical location encodes the location where the characters come from,
+ /// the virtual location encodes where we should *claim* the characters came
+ /// from. Currently this is only used by _Pragma handling.
+ SourceLocation getFileLoc() const { return FileLoc; }
/// setIsMainFile - Mark this lexer as being the lexer for the top-level
/// source file.