blob: 9a883b01722a09ee56caad2555acff4ce4cabc80 [file] [log] [blame]
Ted Kremenek274b2082008-11-12 21:37:15 +00001//===--- PTHLexer.cpp - Lex from a token stream ---------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the PTHLexer interface.
11//
12//===----------------------------------------------------------------------===//
13
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000014#include "clang/Basic/TokenKinds.h"
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/IdentifierTable.h"
Ted Kremenek274b2082008-11-12 21:37:15 +000017#include "clang/Lex/PTHLexer.h"
18#include "clang/Lex/Preprocessor.h"
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000019#include "clang/Lex/PTHManager.h"
20#include "clang/Lex/Token.h"
21#include "clang/Lex/Preprocessor.h"
22#include "llvm/Support/Compiler.h"
23#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/OwningPtr.h"
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000026
Ted Kremenek274b2082008-11-12 21:37:15 +000027using namespace clang;
28
Ted Kremenek268ee702008-12-12 18:34:08 +000029#define DISK_TOKEN_SIZE (2+3*4)
30
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000031PTHLexer::PTHLexer(Preprocessor& pp, SourceLocation fileloc, const char* D,
Ted Kremenek268ee702008-12-12 18:34:08 +000032 const char* ppcond, PTHManager& PM)
Ted Kremenekcd223442008-12-11 22:41:47 +000033 : PreprocessorLexer(&pp, fileloc), TokBuf(D), CurPtr(D), LastHashTokPtr(0),
Ted Kremenek268ee702008-12-12 18:34:08 +000034 PPCond(ppcond), CurPPCondPtr(ppcond), PTHMgr(PM), NeedsFetching(true) {
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000035 // Make sure the EofToken is completely clean.
36 EofToken.startToken();
37 }
Ted Kremenek274b2082008-11-12 21:37:15 +000038
Ted Kremenek0c6a77b2008-12-03 00:38:03 +000039Token PTHLexer::GetToken() {
40 // Read the next token, or if we haven't advanced yet, get the last
41 // token read.
42 if (NeedsFetching) {
43 NeedsFetching = false;
44 ReadToken(LastFetched);
45 }
46
47 Token Tok = LastFetched;
Ted Kremenek89d7ee92008-11-20 19:49:00 +000048
49 // If we are in raw mode, zero out identifier pointers. This is
50 // needed for 'pragma poison'. Note that this requires that the Preprocessor
51 // can go back to the original source when it calls getSpelling().
52 if (LexingRawMode && Tok.is(tok::identifier))
53 Tok.setIdentifierInfo(0);
54
55 return Tok;
56}
57
Ted Kremenek274b2082008-11-12 21:37:15 +000058void PTHLexer::Lex(Token& Tok) {
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000059LexNextToken:
Ted Kremenek31aba422008-11-20 16:32:22 +000060 Tok = GetToken();
Ted Kremenek274b2082008-11-12 21:37:15 +000061
Ted Kremenekcd4e2ae2008-11-21 00:58:35 +000062 if (AtLastToken()) {
63 Preprocessor *PPCache = PP;
64
65 if (LexEndOfFile(Tok))
66 return;
67
68 assert(PPCache && "Raw buffer::LexEndOfFile should return a token");
69 return PPCache->Lex(Tok);
70 }
71
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000072 // Don't advance to the next token yet. Check if we are at the
73 // start of a new line and we're processing a directive. If so, we
74 // consume this token twice, once as an tok::eom.
75 if (Tok.isAtStartOfLine() && ParsingPreprocessorDirective) {
76 ParsingPreprocessorDirective = false;
77 Tok.setKind(tok::eom);
Ted Kremenek274b2082008-11-12 21:37:15 +000078 MIOpt.ReadToken();
Ted Kremenek274b2082008-11-12 21:37:15 +000079 return;
80 }
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000081
82 // Advance to the next token.
Ted Kremenek31aba422008-11-20 16:32:22 +000083 AdvanceToken();
Ted Kremenek274b2082008-11-12 21:37:15 +000084
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000085 if (Tok.is(tok::hash)) {
Ted Kremenek268ee702008-12-12 18:34:08 +000086 if (Tok.isAtStartOfLine()) {
87 LastHashTokPtr = CurPtr - DISK_TOKEN_SIZE;
88 if (!LexingRawMode) {
89 PP->HandleDirective(Tok);
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000090
Ted Kremenek268ee702008-12-12 18:34:08 +000091 if (PP->isCurrentLexer(this))
92 goto LexNextToken;
93
94 return PP->Lex(Tok);
95 }
Ted Kremenekd6f53dc2008-11-20 07:58:05 +000096 }
97 }
98
Ted Kremenek274b2082008-11-12 21:37:15 +000099 MIOpt.ReadToken();
Ted Kremenekd6f53dc2008-11-20 07:58:05 +0000100
101 if (Tok.is(tok::identifier)) {
102 if (LexingRawMode) return;
103 return PP->HandleIdentifier(Tok);
104 }
Ted Kremenek274b2082008-11-12 21:37:15 +0000105}
106
Ted Kremenekcd4e2ae2008-11-21 00:58:35 +0000107bool PTHLexer::LexEndOfFile(Token &Tok) {
108
109 if (ParsingPreprocessorDirective) {
110 ParsingPreprocessorDirective = false;
111 Tok.setKind(tok::eom);
112 MIOpt.ReadToken();
113 return true; // Have a token.
114 }
115
116 if (LexingRawMode) {
117 MIOpt.ReadToken();
118 return true; // Have an eof token.
119 }
120
121 // FIXME: Issue diagnostics similar to Lexer.
122 return PP->HandleEndOfFile(Tok, false);
123}
124
Ted Kremenek274b2082008-11-12 21:37:15 +0000125void PTHLexer::setEOF(Token& Tok) {
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000126 assert(!EofToken.is(tok::eof));
127 Tok = EofToken;
Ted Kremenek274b2082008-11-12 21:37:15 +0000128}
Ted Kremenek17ff58a2008-11-19 22:21:33 +0000129
130void PTHLexer::DiscardToEndOfLine() {
131 assert(ParsingPreprocessorDirective && ParsingFilename == false &&
132 "Must be in a preprocessing directive!");
Ted Kremenek4d35da22008-11-20 01:16:50 +0000133
134 // Already at end-of-file?
Ted Kremenek31aba422008-11-20 16:32:22 +0000135 if (AtLastToken())
Ted Kremenek4d35da22008-11-20 01:16:50 +0000136 return;
137
138 // Find the first token that is not the start of the *current* line.
Ted Kremenekd2bdeed2008-11-21 23:28:56 +0000139 Token T;
140 for (Lex(T); !AtLastToken(); Lex(T))
Ted Kremenek31aba422008-11-20 16:32:22 +0000141 if (GetToken().isAtStartOfLine())
Ted Kremenek4d35da22008-11-20 01:16:50 +0000142 return;
Ted Kremenek17ff58a2008-11-19 22:21:33 +0000143}
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000144
145//===----------------------------------------------------------------------===//
146// Utility methods for reading from the mmap'ed PTH file.
147//===----------------------------------------------------------------------===//
148
149static inline uint8_t Read8(const char*& data) {
150 return (uint8_t) *(data++);
151}
152
153static inline uint32_t Read32(const char*& data) {
154 uint32_t V = (uint32_t) Read8(data);
155 V |= (((uint32_t) Read8(data)) << 8);
156 V |= (((uint32_t) Read8(data)) << 16);
157 V |= (((uint32_t) Read8(data)) << 24);
158 return V;
159}
160
Ted Kremenek268ee702008-12-12 18:34:08 +0000161/// SkipBlock - Used by Preprocessor to skip the current conditional block.
162bool PTHLexer::SkipBlock() {
163 assert(CurPPCondPtr && "No cached PP conditional information.");
164 assert(LastHashTokPtr && "No known '#' token.");
165
Ted Kremenek41a26602008-12-12 22:05:38 +0000166 const char* HashEntryI = 0;
Ted Kremenek268ee702008-12-12 18:34:08 +0000167 uint32_t Offset;
168 uint32_t TableIdx;
169
170 do {
Ted Kremenek41a26602008-12-12 22:05:38 +0000171 // Read the token offset from the side-table.
Ted Kremenek268ee702008-12-12 18:34:08 +0000172 Offset = Read32(CurPPCondPtr);
Ted Kremenek41a26602008-12-12 22:05:38 +0000173
174 // Read the target table index from the side-table.
Ted Kremenek268ee702008-12-12 18:34:08 +0000175 TableIdx = Read32(CurPPCondPtr);
Ted Kremenek41a26602008-12-12 22:05:38 +0000176
177 // Compute the actual memory address of the '#' token data for this entry.
178 HashEntryI = TokBuf + Offset;
179
180 // Optmization: "Sibling jumping". #if...#else...#endif blocks can
181 // contain nested blocks. In the side-table we can jump over these
182 // nested blocks instead of doing a linear search if the next "sibling"
183 // entry is not at a location greater than LastHashTokPtr.
184 if (HashEntryI < LastHashTokPtr && TableIdx) {
185 // In the side-table we are still at an entry for a '#' token that
186 // is earlier than the last one we saw. Check if the location we would
187 // stride gets us closer.
188 const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2);
189 assert(NextPPCondPtr >= CurPPCondPtr);
190 // Read where we should jump to.
191 uint32_t TmpOffset = Read32(NextPPCondPtr);
192 const char* HashEntryJ = TokBuf + TmpOffset;
193
194 if (HashEntryJ <= LastHashTokPtr) {
195 // Jump directly to the next entry in the side table.
196 HashEntryI = HashEntryJ;
197 Offset = TmpOffset;
198 TableIdx = Read32(NextPPCondPtr);
199 CurPPCondPtr = NextPPCondPtr;
200 }
201 }
Ted Kremenek268ee702008-12-12 18:34:08 +0000202 }
Ted Kremenek41a26602008-12-12 22:05:38 +0000203 while (HashEntryI < LastHashTokPtr);
204 assert(HashEntryI == LastHashTokPtr && "No PP-cond entry found for '#'");
Ted Kremenek268ee702008-12-12 18:34:08 +0000205 assert(TableIdx && "No jumping from #endifs.");
206
207 // Update our side-table iterator.
208 const char* NextPPCondPtr = PPCond + TableIdx*(sizeof(uint32_t)*2);
209 assert(NextPPCondPtr >= CurPPCondPtr);
210 CurPPCondPtr = NextPPCondPtr;
211
212 // Read where we should jump to.
Ted Kremenek41a26602008-12-12 22:05:38 +0000213 HashEntryI = TokBuf + Read32(NextPPCondPtr);
Ted Kremenek268ee702008-12-12 18:34:08 +0000214 uint32_t NextIdx = Read32(NextPPCondPtr);
215
216 // By construction NextIdx will be zero if this is a #endif. This is useful
217 // to know to obviate lexing another token.
218 bool isEndif = NextIdx == 0;
219 NeedsFetching = true;
220
221 // This case can occur when we see something like this:
222 //
223 // #if ...
224 // /* a comment or nothing */
225 // #elif
226 //
227 // If we are skipping the first #if block it will be the case that CurPtr
228 // already points 'elif'. Just return.
229
Ted Kremenek41a26602008-12-12 22:05:38 +0000230 if (CurPtr > HashEntryI) {
231 assert(CurPtr == HashEntryI + DISK_TOKEN_SIZE);
Ted Kremenek268ee702008-12-12 18:34:08 +0000232 // Did we reach a #endif? If so, go ahead and consume that token as well.
233 if (isEndif)
234 CurPtr += DISK_TOKEN_SIZE;
235 else
Ted Kremenek41a26602008-12-12 22:05:38 +0000236 LastHashTokPtr = HashEntryI;
Ted Kremenek268ee702008-12-12 18:34:08 +0000237
238 return isEndif;
239 }
240
241 // Otherwise, we need to advance. Update CurPtr to point to the '#' token.
Ted Kremenek41a26602008-12-12 22:05:38 +0000242 CurPtr = HashEntryI;
Ted Kremenek268ee702008-12-12 18:34:08 +0000243
244 // Update the location of the last observed '#'. This is useful if we
245 // are skipping multiple blocks.
246 LastHashTokPtr = CurPtr;
247
248#ifndef DEBUG
249 // In a debug build we should verify that the token is really a '#' that
250 // appears at the start of the line.
251 Token Tok;
252 ReadToken(Tok);
253 assert(Tok.isAtStartOfLine() && Tok.is(tok::hash));
254#else
255 // In a full release build we can just skip the token entirely.
256 CurPtr += DISK_TOKEN_SIZE;
257#endif
258
259 // Did we reach a #endif? If so, go ahead and consume that token as well.
260 if (isEndif) { CurPtr += DISK_TOKEN_SIZE; }
261
262 return isEndif;
263}
264
Ted Kremenek30a12ec2008-12-17 23:36:32 +0000265SourceLocation PTHLexer::getSourceLocation() {
266 // getLocation is not on the hot path. It is used to get the location of
267 // the next token when transitioning back to this lexer when done
268 // handling a #included file. Just read the necessary data from the token
269 // data buffer to construct the SourceLocation object.
270 // NOTE: This is a virtual function; hence it is defined out-of-line.
271 const char* p = CurPtr + (1 + 1 + 4);
272 uint32_t offset =
273 ((uint32_t) ((uint8_t) p[0]))
274 | (((uint32_t) ((uint8_t) p[1])) << 8)
275 | (((uint32_t) ((uint8_t) p[2])) << 16)
276 | (((uint32_t) ((uint8_t) p[3])) << 24);
277 return SourceLocation::getFileLoc(FileID, offset);
278}
279
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000280//===----------------------------------------------------------------------===//
281// Token reconstruction from the PTH file.
282//===----------------------------------------------------------------------===//
283
284void PTHLexer::ReadToken(Token& T) {
285 // Clear the token.
286 // FIXME: Setting the flags directly should obviate this step.
287 T.startToken();
288
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000289 // Shadow CurPtr into an automatic variable so that Read8 doesn't load and
290 // store back into the instance variable.
291 const char *CurPtrShadow = CurPtr;
292
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000293 // Read the type of the token.
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000294 T.setKind((tok::TokenKind) Read8(CurPtrShadow));
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000295
296 // Set flags. This is gross, since we are really setting multiple flags.
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000297 T.setFlag((Token::TokenFlags) Read8(CurPtrShadow));
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000298
299 // Set the IdentifierInfo* (if any).
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000300 T.setIdentifierInfo(PTHMgr.ReadIdentifierInfo(CurPtrShadow));
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000301
302 // Set the SourceLocation. Since all tokens are constructed using a
Chris Lattnerb60d7992008-12-17 21:38:44 +0000303 // raw lexer, they will all be offseted from the same FileID.
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000304 T.setLocation(SourceLocation::getFileLoc(FileID, Read32(CurPtrShadow)));
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000305
306 // Finally, read and set the length of the token.
Ted Kremenek1c13c4f2008-12-17 18:38:19 +0000307 T.setLength(Read32(CurPtrShadow));
308
309 CurPtr = CurPtrShadow;
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000310}
311
312//===----------------------------------------------------------------------===//
313// Internal Data Structures for PTH file lookup and resolving identifiers.
314//===----------------------------------------------------------------------===//
315
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000316
317/// PTHFileLookup - This internal data structure is used by the PTHManager
318/// to map from FileEntry objects managed by FileManager to offsets within
319/// the PTH file.
320namespace {
321class VISIBILITY_HIDDEN PTHFileLookup {
322public:
323 class Val {
Ted Kremenekfb645b62008-12-11 23:36:38 +0000324 uint32_t TokenOff;
325 uint32_t PPCondOff;
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000326
327 public:
Ted Kremenekfb645b62008-12-11 23:36:38 +0000328 Val() : TokenOff(~0) {}
329 Val(uint32_t toff, uint32_t poff) : TokenOff(toff), PPCondOff(poff) {}
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000330
Ted Kremenekfb645b62008-12-11 23:36:38 +0000331 uint32_t getTokenOffset() const {
332 assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized.");
333 return TokenOff;
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000334 }
335
Ted Kremenekfb645b62008-12-11 23:36:38 +0000336 uint32_t gettPPCondOffset() const {
337 assert(TokenOff != ~((uint32_t)0) && "PTHFileLookup entry initialized.");
338 return PPCondOff;
339 }
340
341 bool isValid() const { return TokenOff != ~((uint32_t)0); }
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000342 };
343
344private:
345 llvm::StringMap<Val> FileMap;
346
347public:
348 PTHFileLookup() {};
349
350 Val Lookup(const FileEntry* FE) {
351 const char* s = FE->getName();
352 unsigned size = strlen(s);
353 return FileMap.GetOrCreateValue(s, s+size).getValue();
354 }
355
356 void ReadTable(const char* D) {
357 uint32_t N = Read32(D); // Read the length of the table.
358
359 for ( ; N > 0; --N) { // The rest of the data is the table itself.
360 uint32_t len = Read32(D);
361 const char* s = D;
362 D += len;
Ted Kremenekfb645b62008-12-11 23:36:38 +0000363 uint32_t TokenOff = Read32(D);
364 FileMap.GetOrCreateValue(s, s+len).getValue() = Val(TokenOff, Read32(D));
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000365 }
366 }
367};
368} // end anonymous namespace
369
370//===----------------------------------------------------------------------===//
371// PTHManager methods.
372//===----------------------------------------------------------------------===//
373
374PTHManager::PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup,
Ted Kremenekcf58e622008-12-10 19:40:23 +0000375 const char* idDataTable, IdentifierInfo** perIDCache,
Ted Kremenek6183e482008-12-03 01:16:39 +0000376 Preprocessor& pp)
377: Buf(buf), PerIDCache(perIDCache), FileLookup(fileLookup),
378 IdDataTable(idDataTable), ITable(pp.getIdentifierTable()), PP(pp) {}
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000379
380PTHManager::~PTHManager() {
381 delete Buf;
382 delete (PTHFileLookup*) FileLookup;
Ted Kremenek0e50b6e2008-12-04 22:47:11 +0000383 free(PerIDCache);
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000384}
385
386PTHManager* PTHManager::Create(const std::string& file, Preprocessor& PP) {
387
388 // Memory map the PTH file.
389 llvm::OwningPtr<llvm::MemoryBuffer>
390 File(llvm::MemoryBuffer::getFile(file.c_str()));
391
392 if (!File)
393 return 0;
394
395 // Get the buffer ranges and check if there are at least three 32-bit
396 // words at the end of the file.
397 const char* BufBeg = File->getBufferStart();
398 const char* BufEnd = File->getBufferEnd();
399
400 if(!(BufEnd > BufBeg + sizeof(uint32_t)*3)) {
401 assert(false && "Invalid PTH file.");
402 return 0; // FIXME: Proper error diagnostic?
403 }
404
405 // Compute the address of the index table at the end of the PTH file.
406 // This table contains the offset of the file lookup table, the
407 // persistent ID -> identifer data table.
408 const char* EndTable = BufEnd - sizeof(uint32_t)*3;
409
410 // Construct the file lookup table. This will be used for mapping from
411 // FileEntry*'s to cached tokens.
412 const char* FileTableOffset = EndTable + sizeof(uint32_t)*2;
413 const char* FileTable = BufBeg + Read32(FileTableOffset);
414
415 if (!(FileTable > BufBeg && FileTable < BufEnd)) {
416 assert(false && "Invalid PTH file.");
417 return 0; // FIXME: Proper error diagnostic?
418 }
419
420 llvm::OwningPtr<PTHFileLookup> FL(new PTHFileLookup());
421 FL->ReadTable(FileTable);
422
423 // Get the location of the table mapping from persistent ids to the
424 // data needed to reconstruct identifiers.
425 const char* IDTableOffset = EndTable + sizeof(uint32_t)*1;
426 const char* IData = BufBeg + Read32(IDTableOffset);
427 if (!(IData > BufBeg && IData < BufEnd)) {
428 assert(false && "Invalid PTH file.");
429 return 0; // FIXME: Proper error diagnostic?
430 }
431
Ted Kremenek6183e482008-12-03 01:16:39 +0000432 // Get the number of IdentifierInfos and pre-allocate the identifier cache.
433 uint32_t NumIds = Read32(IData);
434
435 // Pre-allocate the peristent ID -> IdentifierInfo* cache. We use calloc()
436 // so that we in the best case only zero out memory once when the OS returns
437 // us new pages.
438 IdentifierInfo** PerIDCache =
439 (IdentifierInfo**) calloc(NumIds, sizeof(*PerIDCache));
440
441 if (!PerIDCache) {
442 assert(false && "Could not allocate Persistent ID cache.");
443 return 0;
444 }
445
446 // Create the new lexer.
447 return new PTHManager(File.take(), FL.take(), IData, PerIDCache, PP);
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000448}
449
450IdentifierInfo* PTHManager::ReadIdentifierInfo(const char*& D) {
451 // Read the persistent ID from the PTH file.
452 uint32_t persistentID = Read32(D);
453
454 // A persistent ID of '0' always maps to NULL.
455 if (!persistentID)
456 return 0;
457
458 // Adjust the persistent ID by subtracting '1' so that it can be used
459 // as an index within a table in the PTH file.
460 --persistentID;
461
462 // Check if the IdentifierInfo has already been resolved.
Ted Kremenekcf58e622008-12-10 19:40:23 +0000463 IdentifierInfo*& II = PerIDCache[persistentID];
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000464 if (II) return II;
465
466 // Look in the PTH file for the string data for the IdentifierInfo object.
467 const char* TableEntry = IdDataTable + sizeof(uint32_t) * persistentID;
468 const char* IDData = Buf->getBufferStart() + Read32(TableEntry);
469 assert(IDData < Buf->getBufferEnd());
470
471 // Read the length of the string.
472 uint32_t len = Read32(IDData);
473
474 // Get the IdentifierInfo* with the specified string.
475 II = &ITable.get(IDData, IDData+len);
476 return II;
477}
478
479PTHLexer* PTHManager::CreateLexer(unsigned FileID, const FileEntry* FE) {
480
481 if (!FE)
482 return 0;
483
484 // Lookup the FileEntry object in our file lookup data structure. It will
485 // return a variant that indicates whether or not there is an offset within
486 // the PTH file that contains cached tokens.
Ted Kremenekfb645b62008-12-11 23:36:38 +0000487 PTHFileLookup::Val FileData = ((PTHFileLookup*) FileLookup)->Lookup(FE);
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000488
Ted Kremenekfb645b62008-12-11 23:36:38 +0000489 if (!FileData.isValid()) // No tokens available.
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000490 return 0;
491
492 // Compute the offset of the token data within the buffer.
Ted Kremenekfb645b62008-12-11 23:36:38 +0000493 const char* data = Buf->getBufferStart() + FileData.getTokenOffset();
Ted Kremenek268ee702008-12-12 18:34:08 +0000494
495 // Get the location of pp-conditional table.
496 const char* ppcond = Buf->getBufferStart() + FileData.gettPPCondOffset();
497 uint32_t len = Read32(ppcond);
498 if (len == 0) ppcond = 0;
499
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000500 assert(data < Buf->getBufferEnd());
Ted Kremenek268ee702008-12-12 18:34:08 +0000501 return new PTHLexer(PP, SourceLocation::getFileLoc(FileID, 0), data, ppcond,
502 *this);
Ted Kremenek0c6a77b2008-12-03 00:38:03 +0000503}