blob: 96f21f112867442bcd837d0879f29f4d656a83a8 [file] [log] [blame]
Douglas Gregor2cf26342009-04-09 22:27:44 +00001//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===//
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 defines the PCHReader class, which reads a precompiled header.
11//
12//===----------------------------------------------------------------------===//
Chris Lattner4c6f9522009-04-27 05:14:47 +000013
Douglas Gregor2cf26342009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor0a0428e2009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregorfdd01722009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregor0b748912009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
Chris Lattner42d42b52009-04-10 21:41:48 +000021#include "clang/Lex/MacroInfo.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000022#include "clang/Lex/Preprocessor.h"
Steve Naroff83d63c72009-04-24 20:03:17 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000024#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000025#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000026#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000027#include "clang/Basic/FileManager.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000028#include "clang/Basic/TargetInfo.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000029#include "llvm/Bitcode/BitstreamReader.h"
30#include "llvm/Support/Compiler.h"
31#include "llvm/Support/MemoryBuffer.h"
32#include <algorithm>
Douglas Gregore721f952009-04-28 18:58:38 +000033#include <iterator>
Douglas Gregor2cf26342009-04-09 22:27:44 +000034#include <cstdio>
Douglas Gregor4fed3f42009-04-27 18:38:38 +000035#include <sys/stat.h>
Douglas Gregor2cf26342009-04-09 22:27:44 +000036using namespace clang;
37
38//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000039// PCH reader validator implementation
40//===----------------------------------------------------------------------===//
41
42PCHReaderListener::~PCHReaderListener() {}
43
44bool
45PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
46 const LangOptions &PPLangOpts = PP.getLangOptions();
47#define PARSE_LANGOPT_BENIGN(Option)
48#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
49 if (PPLangOpts.Option != LangOpts.Option) { \
50 Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
51 return true; \
52 }
53
54 PARSE_LANGOPT_BENIGN(Trigraphs);
55 PARSE_LANGOPT_BENIGN(BCPLComment);
56 PARSE_LANGOPT_BENIGN(DollarIdents);
57 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
58 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
59 PARSE_LANGOPT_BENIGN(ImplicitInt);
60 PARSE_LANGOPT_BENIGN(Digraphs);
61 PARSE_LANGOPT_BENIGN(HexFloats);
62 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
63 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
64 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
65 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
66 PARSE_LANGOPT_BENIGN(CXXOperatorName);
67 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
68 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
69 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
70 PARSE_LANGOPT_BENIGN(PascalStrings);
71 PARSE_LANGOPT_BENIGN(WritableStrings);
72 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
73 diag::warn_pch_lax_vector_conversions);
74 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
75 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
76 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
77 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
78 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
79 diag::warn_pch_thread_safe_statics);
80 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
81 PARSE_LANGOPT_BENIGN(EmitAllDecls);
82 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
83 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
84 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
85 diag::warn_pch_heinous_extensions);
86 // FIXME: Most of the options below are benign if the macro wasn't
87 // used. Unfortunately, this means that a PCH compiled without
88 // optimization can't be used with optimization turned on, even
89 // though the only thing that changes is whether __OPTIMIZE__ was
90 // defined... but if __OPTIMIZE__ never showed up in the header, it
91 // doesn't matter. We could consider making this some special kind
92 // of check.
93 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
94 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
95 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
96 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
97 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
98 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
99 PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
100 PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
101 if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
102 Reader.Diag(diag::warn_pch_gc_mode)
103 << LangOpts.getGCMode() << PPLangOpts.getGCMode();
104 return true;
105 }
106 PARSE_LANGOPT_BENIGN(getVisibilityMode());
107 PARSE_LANGOPT_BENIGN(InstantiationDepth);
108#undef PARSE_LANGOPT_IRRELEVANT
109#undef PARSE_LANGOPT_BENIGN
110
111 return false;
112}
113
114bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
115 if (Triple != PP.getTargetInfo().getTargetTriple()) {
116 Reader.Diag(diag::warn_pch_target_triple)
117 << Triple << PP.getTargetInfo().getTargetTriple();
118 return true;
119 }
120 return false;
121}
122
123/// \brief Split the given string into a vector of lines, eliminating
124/// any empty lines in the process.
125///
126/// \param Str the string to split.
127/// \param Len the length of Str.
128/// \param KeepEmptyLines true if empty lines should be included
129/// \returns a vector of lines, with the line endings removed
130static std::vector<std::string> splitLines(const char *Str, unsigned Len,
131 bool KeepEmptyLines = false) {
132 std::vector<std::string> Lines;
133 for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
134 unsigned LineEnd = LineStart;
135 while (LineEnd < Len && Str[LineEnd] != '\n')
136 ++LineEnd;
137 if (LineStart != LineEnd || KeepEmptyLines)
138 Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
139 LineStart = LineEnd;
140 }
141 return Lines;
142}
143
144/// \brief Determine whether the string Haystack starts with the
145/// substring Needle.
146static bool startsWith(const std::string &Haystack, const char *Needle) {
147 for (unsigned I = 0, N = Haystack.size(); Needle[I] != 0; ++I) {
148 if (I == N)
149 return false;
150 if (Haystack[I] != Needle[I])
151 return false;
152 }
153
154 return true;
155}
156
157/// \brief Determine whether the string Haystack starts with the
158/// substring Needle.
159static inline bool startsWith(const std::string &Haystack,
160 const std::string &Needle) {
161 return startsWith(Haystack, Needle.c_str());
162}
163
164bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
165 unsigned PCHPredefLen,
166 FileID PCHBufferID,
167 std::string &SuggestedPredefines) {
168 const char *Predef = PP.getPredefines().c_str();
169 unsigned PredefLen = PP.getPredefines().size();
170
171 // If the two predefines buffers compare equal, we're done!
172 if (PredefLen == PCHPredefLen &&
173 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
174 return false;
175
176 SourceManager &SourceMgr = PP.getSourceManager();
177
178 // The predefines buffers are different. Determine what the
179 // differences are, and whether they require us to reject the PCH
180 // file.
181 std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
182 std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
183
184 // Sort both sets of predefined buffer lines, since
185 std::sort(CmdLineLines.begin(), CmdLineLines.end());
186 std::sort(PCHLines.begin(), PCHLines.end());
187
188 // Determine which predefines that where used to build the PCH file
189 // are missing from the command line.
190 std::vector<std::string> MissingPredefines;
191 std::set_difference(PCHLines.begin(), PCHLines.end(),
192 CmdLineLines.begin(), CmdLineLines.end(),
193 std::back_inserter(MissingPredefines));
194
195 bool MissingDefines = false;
196 bool ConflictingDefines = false;
197 for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
198 const std::string &Missing = MissingPredefines[I];
199 if (!startsWith(Missing, "#define ") != 0) {
200 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
201 return true;
202 }
203
204 // This is a macro definition. Determine the name of the macro
205 // we're defining.
206 std::string::size_type StartOfMacroName = strlen("#define ");
207 std::string::size_type EndOfMacroName
208 = Missing.find_first_of("( \n\r", StartOfMacroName);
209 assert(EndOfMacroName != std::string::npos &&
210 "Couldn't find the end of the macro name");
211 std::string MacroName = Missing.substr(StartOfMacroName,
212 EndOfMacroName - StartOfMacroName);
213
214 // Determine whether this macro was given a different definition
215 // on the command line.
216 std::string MacroDefStart = "#define " + MacroName;
217 std::string::size_type MacroDefLen = MacroDefStart.size();
218 std::vector<std::string>::iterator ConflictPos
219 = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
220 MacroDefStart);
221 for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
222 if (!startsWith(*ConflictPos, MacroDefStart)) {
223 // Different macro; we're done.
224 ConflictPos = CmdLineLines.end();
225 break;
226 }
227
228 assert(ConflictPos->size() > MacroDefLen &&
229 "Invalid #define in predefines buffer?");
230 if ((*ConflictPos)[MacroDefLen] != ' ' &&
231 (*ConflictPos)[MacroDefLen] != '(')
232 continue; // Longer macro name; keep trying.
233
234 // We found a conflicting macro definition.
235 break;
236 }
237
238 if (ConflictPos != CmdLineLines.end()) {
239 Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
240 << MacroName;
241
242 // Show the definition of this macro within the PCH file.
243 const char *MissingDef = strstr(PCHPredef, Missing.c_str());
244 unsigned Offset = MissingDef - PCHPredef;
245 SourceLocation PCHMissingLoc
246 = SourceMgr.getLocForStartOfFile(PCHBufferID)
247 .getFileLocWithOffset(Offset);
248 Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
249 << MacroName;
250
251 ConflictingDefines = true;
252 continue;
253 }
254
255 // If the macro doesn't conflict, then we'll just pick up the
256 // macro definition from the PCH file. Warn the user that they
257 // made a mistake.
258 if (ConflictingDefines)
259 continue; // Don't complain if there are already conflicting defs
260
261 if (!MissingDefines) {
262 Reader.Diag(diag::warn_cmdline_missing_macro_defs);
263 MissingDefines = true;
264 }
265
266 // Show the definition of this macro within the PCH file.
267 const char *MissingDef = strstr(PCHPredef, Missing.c_str());
268 unsigned Offset = MissingDef - PCHPredef;
269 SourceLocation PCHMissingLoc
270 = SourceMgr.getLocForStartOfFile(PCHBufferID)
271 .getFileLocWithOffset(Offset);
272 Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
273 }
274
275 if (ConflictingDefines)
276 return true;
277
278 // Determine what predefines were introduced based on command-line
279 // parameters that were not present when building the PCH
280 // file. Extra #defines are okay, so long as the identifiers being
281 // defined were not used within the precompiled header.
282 std::vector<std::string> ExtraPredefines;
283 std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
284 PCHLines.begin(), PCHLines.end(),
285 std::back_inserter(ExtraPredefines));
286 for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
287 const std::string &Extra = ExtraPredefines[I];
288 if (!startsWith(Extra, "#define ") != 0) {
289 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
290 return true;
291 }
292
293 // This is an extra macro definition. Determine the name of the
294 // macro we're defining.
295 std::string::size_type StartOfMacroName = strlen("#define ");
296 std::string::size_type EndOfMacroName
297 = Extra.find_first_of("( \n\r", StartOfMacroName);
298 assert(EndOfMacroName != std::string::npos &&
299 "Couldn't find the end of the macro name");
300 std::string MacroName = Extra.substr(StartOfMacroName,
301 EndOfMacroName - StartOfMacroName);
302
303 // Check whether this name was used somewhere in the PCH file. If
304 // so, defining it as a macro could change behavior, so we reject
305 // the PCH file.
306 if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
307 MacroName.c_str() + MacroName.size())) {
308 Reader.Diag(diag::warn_macro_name_used_in_pch)
309 << II;
310 return true;
311 }
312
313 // Add this definition to the suggested predefines buffer.
314 SuggestedPredefines += Extra;
315 SuggestedPredefines += '\n';
316 }
317
318 // If we get here, it's because the predefines buffer had compatible
319 // contents. Accept the PCH file.
320 return false;
321}
322
323void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
324 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
325}
326
327void PCHValidator::ReadCounter(unsigned Value) {
328 PP.setCounterValue(Value);
329}
330
331
332
333//===----------------------------------------------------------------------===//
Douglas Gregor668c1a42009-04-21 22:25:48 +0000334// PCH reader implementation
335//===----------------------------------------------------------------------===//
336
Chris Lattnerd1d64a02009-04-27 21:45:14 +0000337PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000338 : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
339 FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
340 SemaObj(0), PP(&PP), Context(Context), Consumer(0),
341 IdentifierTableData(0), IdentifierLookupTable(0),
342 IdentifierOffsets(0),
343 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
344 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
345 TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
346 NumSLocEntriesRead(0), NumStatementsRead(0),
347 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
348 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
349
350PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
351 Diagnostic &Diags)
352 : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
Argyrios Kyrtzidis57102112009-06-19 07:55:35 +0000353 SemaObj(0), PP(0), Context(0), Consumer(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +0000354 IdentifierTableData(0), IdentifierLookupTable(0),
355 IdentifierOffsets(0),
356 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
357 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000358 TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0),
359 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000360 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +0000361 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { }
362
363PCHReader::~PCHReader() {}
364
Chris Lattnerda930612009-04-27 05:58:23 +0000365Expr *PCHReader::ReadDeclExpr() {
366 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
367}
368
369Expr *PCHReader::ReadTypeExpr() {
Chris Lattner52e97d12009-04-27 05:41:06 +0000370 return dyn_cast_or_null<Expr>(ReadStmt(Stream));
Chris Lattner4c6f9522009-04-27 05:14:47 +0000371}
372
373
Douglas Gregor668c1a42009-04-21 22:25:48 +0000374namespace {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000375class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
376 PCHReader &Reader;
377
378public:
379 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
380
381 typedef Selector external_key_type;
382 typedef external_key_type internal_key_type;
383
384 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
385
386 static bool EqualKey(const internal_key_type& a,
387 const internal_key_type& b) {
388 return a == b;
389 }
390
391 static unsigned ComputeHash(Selector Sel) {
392 unsigned N = Sel.getNumArgs();
393 if (N == 0)
394 ++N;
395 unsigned R = 5381;
396 for (unsigned I = 0; I != N; ++I)
397 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
398 R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R);
399 return R;
400 }
401
402 // This hopefully will just get inlined and removed by the optimizer.
403 static const internal_key_type&
404 GetInternalKey(const external_key_type& x) { return x; }
405
406 static std::pair<unsigned, unsigned>
407 ReadKeyDataLength(const unsigned char*& d) {
408 using namespace clang::io;
409 unsigned KeyLen = ReadUnalignedLE16(d);
410 unsigned DataLen = ReadUnalignedLE16(d);
411 return std::make_pair(KeyLen, DataLen);
412 }
413
Douglas Gregor83941df2009-04-25 17:48:32 +0000414 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000415 using namespace clang::io;
Chris Lattnerd1d64a02009-04-27 21:45:14 +0000416 SelectorTable &SelTable = Reader.getContext()->Selectors;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000417 unsigned N = ReadUnalignedLE16(d);
418 IdentifierInfo *FirstII
419 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
420 if (N == 0)
421 return SelTable.getNullarySelector(FirstII);
422 else if (N == 1)
423 return SelTable.getUnarySelector(FirstII);
424
425 llvm::SmallVector<IdentifierInfo *, 16> Args;
426 Args.push_back(FirstII);
427 for (unsigned I = 1; I != N; ++I)
428 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
429
Douglas Gregor75fdb232009-05-22 22:45:36 +0000430 return SelTable.getSelector(N, Args.data());
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000431 }
432
433 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
434 using namespace clang::io;
435 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
436 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
437
438 data_type Result;
439
440 // Load instance methods
441 ObjCMethodList *Prev = 0;
442 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
443 ObjCMethodDecl *Method
444 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
445 if (!Result.first.Method) {
446 // This is the first method, which is the easy case.
447 Result.first.Method = Method;
448 Prev = &Result.first;
449 continue;
450 }
451
452 Prev->Next = new ObjCMethodList(Method, 0);
453 Prev = Prev->Next;
454 }
455
456 // Load factory methods
457 Prev = 0;
458 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
459 ObjCMethodDecl *Method
460 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
461 if (!Result.second.Method) {
462 // This is the first method, which is the easy case.
463 Result.second.Method = Method;
464 Prev = &Result.second;
465 continue;
466 }
467
468 Prev->Next = new ObjCMethodList(Method, 0);
469 Prev = Prev->Next;
470 }
471
472 return Result;
473 }
474};
475
476} // end anonymous namespace
477
478/// \brief The on-disk hash table used for the global method pool.
479typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
480 PCHMethodPoolLookupTable;
481
482namespace {
Douglas Gregor668c1a42009-04-21 22:25:48 +0000483class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
484 PCHReader &Reader;
485
486 // If we know the IdentifierInfo in advance, it is here and we will
487 // not build a new one. Used when deserializing information about an
488 // identifier that was constructed before the PCH file was read.
489 IdentifierInfo *KnownII;
490
491public:
492 typedef IdentifierInfo * data_type;
493
494 typedef const std::pair<const char*, unsigned> external_key_type;
495
496 typedef external_key_type internal_key_type;
497
498 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
499 : Reader(Reader), KnownII(II) { }
500
501 static bool EqualKey(const internal_key_type& a,
502 const internal_key_type& b) {
503 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
504 : false;
505 }
506
507 static unsigned ComputeHash(const internal_key_type& a) {
508 return BernsteinHash(a.first, a.second);
509 }
510
511 // This hopefully will just get inlined and removed by the optimizer.
512 static const internal_key_type&
513 GetInternalKey(const external_key_type& x) { return x; }
514
515 static std::pair<unsigned, unsigned>
516 ReadKeyDataLength(const unsigned char*& d) {
517 using namespace clang::io;
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000518 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregord6595a42009-04-25 21:04:17 +0000519 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000520 return std::make_pair(KeyLen, DataLen);
521 }
522
523 static std::pair<const char*, unsigned>
524 ReadKey(const unsigned char* d, unsigned n) {
525 assert(n >= 2 && d[n-1] == '\0');
526 return std::make_pair((const char*) d, n-1);
527 }
528
529 IdentifierInfo *ReadData(const internal_key_type& k,
530 const unsigned char* d,
531 unsigned DataLen) {
532 using namespace clang::io;
Douglas Gregora92193e2009-04-28 21:18:29 +0000533 pch::IdentID ID = ReadUnalignedLE32(d);
534 bool IsInteresting = ID & 0x01;
535
536 // Wipe out the "is interesting" bit.
537 ID = ID >> 1;
538
539 if (!IsInteresting) {
540 // For unintersting identifiers, just build the IdentifierInfo
541 // and associate it with the persistent ID.
542 IdentifierInfo *II = KnownII;
543 if (!II)
544 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
545 k.first, k.first + k.second);
546 Reader.SetIdentifierInfo(ID, II);
547 return II;
548 }
549
Douglas Gregor5998da52009-04-28 21:32:13 +0000550 unsigned Bits = ReadUnalignedLE16(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000551 bool CPlusPlusOperatorKeyword = Bits & 0x01;
552 Bits >>= 1;
553 bool Poisoned = Bits & 0x01;
554 Bits >>= 1;
555 bool ExtensionToken = Bits & 0x01;
556 Bits >>= 1;
557 bool hasMacroDefinition = Bits & 0x01;
558 Bits >>= 1;
559 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
560 Bits >>= 10;
Douglas Gregora92193e2009-04-28 21:18:29 +0000561
Douglas Gregor2deaea32009-04-22 18:49:13 +0000562 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregor5998da52009-04-28 21:32:13 +0000563 DataLen -= 6;
Douglas Gregor668c1a42009-04-21 22:25:48 +0000564
565 // Build the IdentifierInfo itself and link the identifier ID with
566 // the new IdentifierInfo.
567 IdentifierInfo *II = KnownII;
568 if (!II)
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000569 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
570 k.first, k.first + k.second);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000571 Reader.SetIdentifierInfo(ID, II);
572
Douglas Gregor2deaea32009-04-22 18:49:13 +0000573 // Set or check the various bits in the IdentifierInfo structure.
574 // FIXME: Load token IDs lazily, too?
Douglas Gregor2deaea32009-04-22 18:49:13 +0000575 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
576 assert(II->isExtensionToken() == ExtensionToken &&
577 "Incorrect extension token flag");
578 (void)ExtensionToken;
579 II->setIsPoisoned(Poisoned);
580 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
581 "Incorrect C++ operator keyword flag");
582 (void)CPlusPlusOperatorKeyword;
583
Douglas Gregor37e26842009-04-21 23:56:24 +0000584 // If this identifier is a macro, deserialize the macro
585 // definition.
586 if (hasMacroDefinition) {
Douglas Gregor5998da52009-04-28 21:32:13 +0000587 uint32_t Offset = ReadUnalignedLE32(d);
Douglas Gregor37e26842009-04-21 23:56:24 +0000588 Reader.ReadMacroRecord(Offset);
Douglas Gregor5998da52009-04-28 21:32:13 +0000589 DataLen -= 4;
Douglas Gregor37e26842009-04-21 23:56:24 +0000590 }
Douglas Gregor668c1a42009-04-21 22:25:48 +0000591
592 // Read all of the declarations visible at global scope with this
593 // name.
594 Sema *SemaObj = Reader.getSema();
Chris Lattner6bf690f2009-04-27 22:17:41 +0000595 if (Reader.getContext() == 0) return II;
Chris Lattnercc7dea82009-04-27 22:02:30 +0000596
Douglas Gregor668c1a42009-04-21 22:25:48 +0000597 while (DataLen > 0) {
598 NamedDecl *D = cast<NamedDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
Douglas Gregor668c1a42009-04-21 22:25:48 +0000599 if (SemaObj) {
600 // Introduce this declaration into the translation-unit scope
601 // and add it to the declaration chain for this identifier, so
602 // that (unqualified) name lookup will find it.
603 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
604 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
605 } else {
606 // Queue this declaration so that it will be added to the
607 // translation unit scope and identifier's declaration chain
608 // once a Sema object is known.
Douglas Gregor6cfc1a82009-04-22 21:15:06 +0000609 Reader.PreloadedDecls.push_back(D);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000610 }
611
612 DataLen -= 4;
613 }
614 return II;
615 }
616};
617
618} // end anonymous namespace
619
620/// \brief The on-disk hash table used to contain information about
621/// all of the identifiers in the program.
622typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
623 PCHIdentifierLookupTable;
624
Douglas Gregor2cf26342009-04-09 22:27:44 +0000625// FIXME: use the diagnostics machinery
Douglas Gregora02b1472009-04-28 21:53:25 +0000626bool PCHReader::Error(const char *Msg) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000627 unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
628 Diag(DiagID);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000629 return true;
630}
631
Douglas Gregore1d918e2009-04-10 23:10:45 +0000632/// \brief Check the contents of the predefines buffer against the
633/// contents of the predefines buffer used to build the PCH file.
634///
635/// The contents of the two predefines buffers should be the same. If
636/// not, then some command-line option changed the preprocessor state
637/// and we must reject the PCH file.
638///
639/// \param PCHPredef The start of the predefines buffer in the PCH
640/// file.
641///
642/// \param PCHPredefLen The length of the predefines buffer in the PCH
643/// file.
644///
645/// \param PCHBufferID The FileID for the PCH predefines buffer.
646///
647/// \returns true if there was a mismatch (in which case the PCH file
648/// should be ignored), or false otherwise.
649bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
650 unsigned PCHPredefLen,
651 FileID PCHBufferID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000652 if (Listener)
653 return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
654 SuggestedPredefines);
Douglas Gregore721f952009-04-28 18:58:38 +0000655 return false;
Douglas Gregore1d918e2009-04-10 23:10:45 +0000656}
657
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000658//===----------------------------------------------------------------------===//
659// Source Manager Deserialization
660//===----------------------------------------------------------------------===//
661
Douglas Gregorbd945002009-04-13 16:31:14 +0000662/// \brief Read the line table in the source manager block.
663/// \returns true if ther was an error.
664static bool ParseLineTable(SourceManager &SourceMgr,
665 llvm::SmallVectorImpl<uint64_t> &Record) {
666 unsigned Idx = 0;
667 LineTableInfo &LineTable = SourceMgr.getLineTable();
668
669 // Parse the file names
Douglas Gregorff0a9872009-04-13 17:12:42 +0000670 std::map<int, int> FileIDs;
671 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000672 // Extract the file name
673 unsigned FilenameLen = Record[Idx++];
674 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
675 Idx += FilenameLen;
Douglas Gregorff0a9872009-04-13 17:12:42 +0000676 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
677 Filename.size());
Douglas Gregorbd945002009-04-13 16:31:14 +0000678 }
679
680 // Parse the line entries
681 std::vector<LineEntry> Entries;
682 while (Idx < Record.size()) {
Douglas Gregorff0a9872009-04-13 17:12:42 +0000683 int FID = FileIDs[Record[Idx++]];
Douglas Gregorbd945002009-04-13 16:31:14 +0000684
685 // Extract the line entries
686 unsigned NumEntries = Record[Idx++];
687 Entries.clear();
688 Entries.reserve(NumEntries);
689 for (unsigned I = 0; I != NumEntries; ++I) {
690 unsigned FileOffset = Record[Idx++];
691 unsigned LineNo = Record[Idx++];
692 int FilenameID = Record[Idx++];
693 SrcMgr::CharacteristicKind FileKind
694 = (SrcMgr::CharacteristicKind)Record[Idx++];
695 unsigned IncludeOffset = Record[Idx++];
696 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
697 FileKind, IncludeOffset));
698 }
699 LineTable.AddEntry(FID, Entries);
700 }
701
702 return false;
703}
704
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000705namespace {
706
707class VISIBILITY_HIDDEN PCHStatData {
708public:
709 const bool hasStat;
710 const ino_t ino;
711 const dev_t dev;
712 const mode_t mode;
713 const time_t mtime;
714 const off_t size;
715
716 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
717 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
718
719 PCHStatData()
720 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
721};
722
723class VISIBILITY_HIDDEN PCHStatLookupTrait {
724 public:
725 typedef const char *external_key_type;
726 typedef const char *internal_key_type;
727
728 typedef PCHStatData data_type;
729
730 static unsigned ComputeHash(const char *path) {
731 return BernsteinHash(path);
732 }
733
734 static internal_key_type GetInternalKey(const char *path) { return path; }
735
736 static bool EqualKey(internal_key_type a, internal_key_type b) {
737 return strcmp(a, b) == 0;
738 }
739
740 static std::pair<unsigned, unsigned>
741 ReadKeyDataLength(const unsigned char*& d) {
742 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
743 unsigned DataLen = (unsigned) *d++;
744 return std::make_pair(KeyLen + 1, DataLen);
745 }
746
747 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
748 return (const char *)d;
749 }
750
751 static data_type ReadData(const internal_key_type, const unsigned char *d,
752 unsigned /*DataLen*/) {
753 using namespace clang::io;
754
755 if (*d++ == 1)
756 return data_type();
757
758 ino_t ino = (ino_t) ReadUnalignedLE32(d);
759 dev_t dev = (dev_t) ReadUnalignedLE32(d);
760 mode_t mode = (mode_t) ReadUnalignedLE16(d);
761 time_t mtime = (time_t) ReadUnalignedLE64(d);
762 off_t size = (off_t) ReadUnalignedLE64(d);
763 return data_type(ino, dev, mode, mtime, size);
764 }
765};
766
767/// \brief stat() cache for precompiled headers.
768///
769/// This cache is very similar to the stat cache used by pretokenized
770/// headers.
771class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
772 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
773 CacheTy *Cache;
774
775 unsigned &NumStatHits, &NumStatMisses;
776public:
777 PCHStatCache(const unsigned char *Buckets,
778 const unsigned char *Base,
779 unsigned &NumStatHits,
780 unsigned &NumStatMisses)
781 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
782 Cache = CacheTy::Create(Buckets, Base);
783 }
784
785 ~PCHStatCache() { delete Cache; }
786
787 int stat(const char *path, struct stat *buf) {
788 // Do the lookup for the file's data in the PCH file.
789 CacheTy::iterator I = Cache->find(path);
790
791 // If we don't get a hit in the PCH file just forward to 'stat'.
792 if (I == Cache->end()) {
793 ++NumStatMisses;
794 return ::stat(path, buf);
795 }
796
797 ++NumStatHits;
798 PCHStatData Data = *I;
799
800 if (!Data.hasStat)
801 return 1;
802
803 buf->st_ino = Data.ino;
804 buf->st_dev = Data.dev;
805 buf->st_mtime = Data.mtime;
806 buf->st_mode = Data.mode;
807 buf->st_size = Data.size;
808 return 0;
809 }
810};
811} // end anonymous namespace
812
813
Douglas Gregor14f79002009-04-10 03:52:48 +0000814/// \brief Read the source manager block
Douglas Gregore1d918e2009-04-10 23:10:45 +0000815PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregor14f79002009-04-10 03:52:48 +0000816 using namespace SrcMgr;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000817
818 // Set the source-location entry cursor to the current position in
819 // the stream. This cursor will be used to read the contents of the
820 // source manager block initially, and then lazily read
821 // source-location entries as needed.
822 SLocEntryCursor = Stream;
823
824 // The stream itself is going to skip over the source manager block.
825 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000826 Error("malformed block record in PCH file");
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000827 return Failure;
828 }
829
830 // Enter the source manager block.
831 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000832 Error("malformed source manager block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000833 return Failure;
834 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000835
Douglas Gregor14f79002009-04-10 03:52:48 +0000836 RecordData Record;
837 while (true) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000838 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregor14f79002009-04-10 03:52:48 +0000839 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000840 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000841 Error("error at end of Source Manager block in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000842 return Failure;
843 }
Douglas Gregore1d918e2009-04-10 23:10:45 +0000844 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000845 }
846
847 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
848 // No known subblocks, always skip them.
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000849 SLocEntryCursor.ReadSubBlockID();
850 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000851 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000852 return Failure;
853 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000854 continue;
855 }
856
857 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000858 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregor14f79002009-04-10 03:52:48 +0000859 continue;
860 }
861
862 // Read a record.
863 const char *BlobStart;
864 unsigned BlobLen;
865 Record.clear();
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000866 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregor14f79002009-04-10 03:52:48 +0000867 default: // Default behavior: ignore.
868 break;
869
Chris Lattner2c78b872009-04-14 23:22:57 +0000870 case pch::SM_LINE_TABLE:
Douglas Gregorbd945002009-04-13 16:31:14 +0000871 if (ParseLineTable(SourceMgr, Record))
872 return Failure;
Chris Lattner2c78b872009-04-14 23:22:57 +0000873 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000874
875 case pch::SM_HEADER_FILE_INFO: {
876 HeaderFileInfo HFI;
877 HFI.isImport = Record[0];
878 HFI.DirInfo = Record[1];
879 HFI.NumIncludes = Record[2];
880 HFI.ControllingMacroID = Record[3];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000881 if (Listener)
882 Listener->ReadHeaderFileInfo(HFI);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000883 break;
884 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000885
886 case pch::SM_SLOC_FILE_ENTRY:
887 case pch::SM_SLOC_BUFFER_ENTRY:
888 case pch::SM_SLOC_INSTANTIATION_ENTRY:
889 // Once we hit one of the source location entries, we're done.
890 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000891 }
892 }
893}
894
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000895/// \brief Read in the source location entry with the given ID.
896PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
897 if (ID == 0)
898 return Success;
899
900 if (ID > TotalNumSLocEntries) {
901 Error("source location entry ID out-of-range for PCH file");
902 return Failure;
903 }
904
905 ++NumSLocEntriesRead;
906 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
907 unsigned Code = SLocEntryCursor.ReadCode();
908 if (Code == llvm::bitc::END_BLOCK ||
909 Code == llvm::bitc::ENTER_SUBBLOCK ||
910 Code == llvm::bitc::DEFINE_ABBREV) {
911 Error("incorrectly-formatted source location entry in PCH file");
912 return Failure;
913 }
914
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000915 RecordData Record;
916 const char *BlobStart;
917 unsigned BlobLen;
918 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
919 default:
920 Error("incorrectly-formatted source location entry in PCH file");
921 return Failure;
922
923 case pch::SM_SLOC_FILE_ENTRY: {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000924 const FileEntry *File = FileMgr.getFile(BlobStart, BlobStart + BlobLen);
Chris Lattnerd3555ae2009-06-15 04:35:16 +0000925 if (File == 0) {
926 std::string ErrorStr = "could not find file '";
927 ErrorStr.append(BlobStart, BlobLen);
928 ErrorStr += "' referenced by PCH file";
929 Error(ErrorStr.c_str());
930 return Failure;
931 }
932
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000933 FileID FID = SourceMgr.createFileID(File,
934 SourceLocation::getFromRawEncoding(Record[1]),
935 (SrcMgr::CharacteristicKind)Record[2],
936 ID, Record[0]);
937 if (Record[3])
938 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
939 .setHasLineDirectives();
940
941 break;
942 }
943
944 case pch::SM_SLOC_BUFFER_ENTRY: {
945 const char *Name = BlobStart;
946 unsigned Offset = Record[0];
947 unsigned Code = SLocEntryCursor.ReadCode();
948 Record.clear();
949 unsigned RecCode
950 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
951 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
952 (void)RecCode;
953 llvm::MemoryBuffer *Buffer
954 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
955 BlobStart + BlobLen - 1,
956 Name);
957 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
958
Douglas Gregor92b059e2009-04-28 20:33:11 +0000959 if (strcmp(Name, "<built-in>") == 0) {
960 PCHPredefinesBufferID = BufferID;
961 PCHPredefines = BlobStart;
962 PCHPredefinesLen = BlobLen - 1;
963 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000964
965 break;
966 }
967
968 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
969 SourceLocation SpellingLoc
970 = SourceLocation::getFromRawEncoding(Record[1]);
971 SourceMgr.createInstantiationLoc(SpellingLoc,
972 SourceLocation::getFromRawEncoding(Record[2]),
973 SourceLocation::getFromRawEncoding(Record[3]),
974 Record[4],
975 ID,
976 Record[0]);
977 break;
978 }
979 }
980
981 return Success;
982}
983
Chris Lattner6367f6d2009-04-27 01:05:14 +0000984/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
985/// specified cursor. Read the abbreviations that are at the top of the block
986/// and then leave the cursor pointing into the block.
987bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
988 unsigned BlockID) {
989 if (Cursor.EnterSubBlock(BlockID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000990 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +0000991 return Failure;
992 }
993
Chris Lattner6367f6d2009-04-27 01:05:14 +0000994 while (true) {
995 unsigned Code = Cursor.ReadCode();
996
997 // We expect all abbrevs to be at the start of the block.
998 if (Code != llvm::bitc::DEFINE_ABBREV)
999 return false;
1000 Cursor.ReadAbbrevRecord();
1001 }
1002}
1003
Douglas Gregor37e26842009-04-21 23:56:24 +00001004void PCHReader::ReadMacroRecord(uint64_t Offset) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001005 assert(PP && "Forgot to set Preprocessor ?");
1006
Douglas Gregor37e26842009-04-21 23:56:24 +00001007 // Keep track of where we are in the stream, then jump back there
1008 // after reading this macro.
1009 SavedStreamPosition SavedPosition(Stream);
1010
1011 Stream.JumpToBit(Offset);
1012 RecordData Record;
1013 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
1014 MacroInfo *Macro = 0;
Steve Naroff83d63c72009-04-24 20:03:17 +00001015
Douglas Gregor37e26842009-04-21 23:56:24 +00001016 while (true) {
1017 unsigned Code = Stream.ReadCode();
1018 switch (Code) {
1019 case llvm::bitc::END_BLOCK:
1020 return;
1021
1022 case llvm::bitc::ENTER_SUBBLOCK:
1023 // No known subblocks, always skip them.
1024 Stream.ReadSubBlockID();
1025 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001026 Error("malformed block record in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001027 return;
1028 }
1029 continue;
1030
1031 case llvm::bitc::DEFINE_ABBREV:
1032 Stream.ReadAbbrevRecord();
1033 continue;
1034 default: break;
1035 }
1036
1037 // Read a record.
1038 Record.clear();
1039 pch::PreprocessorRecordTypes RecType =
1040 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
1041 switch (RecType) {
Douglas Gregor37e26842009-04-21 23:56:24 +00001042 case pch::PP_MACRO_OBJECT_LIKE:
1043 case pch::PP_MACRO_FUNCTION_LIKE: {
1044 // If we already have a macro, that means that we've hit the end
1045 // of the definition of the macro we were looking for. We're
1046 // done.
1047 if (Macro)
1048 return;
1049
1050 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
1051 if (II == 0) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001052 Error("macro must have a name in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001053 return;
1054 }
1055 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
1056 bool isUsed = Record[2];
1057
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001058 MacroInfo *MI = PP->AllocateMacroInfo(Loc);
Douglas Gregor37e26842009-04-21 23:56:24 +00001059 MI->setIsUsed(isUsed);
1060
1061 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
1062 // Decode function-like macro info.
1063 bool isC99VarArgs = Record[3];
1064 bool isGNUVarArgs = Record[4];
1065 MacroArgs.clear();
1066 unsigned NumArgs = Record[5];
1067 for (unsigned i = 0; i != NumArgs; ++i)
1068 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
1069
1070 // Install function-like macro info.
1071 MI->setIsFunctionLike();
1072 if (isC99VarArgs) MI->setIsC99Varargs();
1073 if (isGNUVarArgs) MI->setIsGNUVarargs();
Douglas Gregor75fdb232009-05-22 22:45:36 +00001074 MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001075 PP->getPreprocessorAllocator());
Douglas Gregor37e26842009-04-21 23:56:24 +00001076 }
1077
1078 // Finally, install the macro.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001079 PP->setMacroInfo(II, MI);
Douglas Gregor37e26842009-04-21 23:56:24 +00001080
1081 // Remember that we saw this macro last so that we add the tokens that
1082 // form its body to it.
1083 Macro = MI;
1084 ++NumMacrosRead;
1085 break;
1086 }
1087
1088 case pch::PP_TOKEN: {
1089 // If we see a TOKEN before a PP_MACRO_*, then the file is
1090 // erroneous, just pretend we didn't see this.
1091 if (Macro == 0) break;
1092
1093 Token Tok;
1094 Tok.startToken();
1095 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
1096 Tok.setLength(Record[1]);
1097 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
1098 Tok.setIdentifierInfo(II);
1099 Tok.setKind((tok::TokenKind)Record[3]);
1100 Tok.setFlag((Token::TokenFlags)Record[4]);
1101 Macro->AddTokenToBody(Tok);
1102 break;
1103 }
Steve Naroff83d63c72009-04-24 20:03:17 +00001104 }
Douglas Gregor37e26842009-04-21 23:56:24 +00001105 }
1106}
1107
Douglas Gregor668c1a42009-04-21 22:25:48 +00001108PCHReader::PCHReadResult
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001109PCHReader::ReadPCHBlock() {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001110 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001111 Error("malformed block record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001112 return Failure;
1113 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001114
1115 // Read all of the records and blocks for the PCH file.
Douglas Gregor8038d512009-04-10 17:25:41 +00001116 RecordData Record;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001117 while (!Stream.AtEndOfStream()) {
1118 unsigned Code = Stream.ReadCode();
1119 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001120 if (Stream.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001121 Error("error at end of module block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001122 return Failure;
1123 }
Chris Lattner7356a312009-04-11 21:15:38 +00001124
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001125 return Success;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001126 }
1127
1128 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1129 switch (Stream.ReadSubBlockID()) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001130 case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
1131 default: // Skip unknown content.
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001132 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001133 Error("malformed block record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001134 return Failure;
1135 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001136 break;
1137
Chris Lattner6367f6d2009-04-27 01:05:14 +00001138 case pch::DECLS_BLOCK_ID:
1139 // We lazily load the decls block, but we want to set up the
1140 // DeclsCursor cursor to point into it. Clone our current bitcode
1141 // cursor to it, enter the block and read the abbrevs in that block.
1142 // With the main cursor, we just skip over it.
1143 DeclsCursor = Stream;
1144 if (Stream.SkipBlock() || // Skip with the main cursor.
1145 // Read the abbrevs.
1146 ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001147 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +00001148 return Failure;
1149 }
1150 break;
1151
Chris Lattner7356a312009-04-11 21:15:38 +00001152 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner7356a312009-04-11 21:15:38 +00001153 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001154 Error("malformed block record in PCH file");
Chris Lattner7356a312009-04-11 21:15:38 +00001155 return Failure;
1156 }
1157 break;
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001158
Douglas Gregor14f79002009-04-10 03:52:48 +00001159 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001160 switch (ReadSourceManagerBlock()) {
1161 case Success:
1162 break;
1163
1164 case Failure:
Douglas Gregora02b1472009-04-28 21:53:25 +00001165 Error("malformed source manager block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001166 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001167
1168 case IgnorePCH:
1169 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001170 }
Douglas Gregor14f79002009-04-10 03:52:48 +00001171 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001172 }
Douglas Gregor8038d512009-04-10 17:25:41 +00001173 continue;
1174 }
1175
1176 if (Code == llvm::bitc::DEFINE_ABBREV) {
1177 Stream.ReadAbbrevRecord();
1178 continue;
1179 }
1180
1181 // Read and process a record.
1182 Record.clear();
Douglas Gregor2bec0412009-04-10 21:16:55 +00001183 const char *BlobStart = 0;
1184 unsigned BlobLen = 0;
1185 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
1186 &BlobStart, &BlobLen)) {
Douglas Gregor8038d512009-04-10 17:25:41 +00001187 default: // Default behavior: ignore.
1188 break;
1189
1190 case pch::TYPE_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001191 if (!TypesLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001192 Error("duplicate TYPE_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001193 return Failure;
1194 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001195 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001196 TypesLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001197 break;
1198
1199 case pch::DECL_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001200 if (!DeclsLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001201 Error("duplicate DECL_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001202 return Failure;
1203 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001204 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001205 DeclsLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001206 break;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001207
1208 case pch::LANGUAGE_OPTIONS:
1209 if (ParseLanguageOptions(Record))
1210 return IgnorePCH;
1211 break;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001212
Douglas Gregorab41e632009-04-27 22:23:34 +00001213 case pch::METADATA: {
1214 if (Record[0] != pch::VERSION_MAJOR) {
1215 Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
1216 : diag::warn_pch_version_too_new);
1217 return IgnorePCH;
1218 }
1219
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001220 if (Listener) {
1221 std::string TargetTriple(BlobStart, BlobLen);
1222 if (Listener->ReadTargetTriple(TargetTriple))
1223 return IgnorePCH;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001224 }
1225 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001226 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001227
1228 case pch::IDENTIFIER_TABLE:
Douglas Gregor668c1a42009-04-21 22:25:48 +00001229 IdentifierTableData = BlobStart;
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001230 if (Record[0]) {
1231 IdentifierLookupTable
1232 = PCHIdentifierLookupTable::Create(
Douglas Gregor668c1a42009-04-21 22:25:48 +00001233 (const unsigned char *)IdentifierTableData + Record[0],
1234 (const unsigned char *)IdentifierTableData,
1235 PCHIdentifierLookupTrait(*this));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001236 if (PP)
1237 PP->getIdentifierTable().setExternalIdentifierLookup(this);
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001238 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001239 break;
1240
1241 case pch::IDENTIFIER_OFFSET:
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001242 if (!IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001243 Error("duplicate IDENTIFIER_OFFSET record in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00001244 return Failure;
1245 }
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001246 IdentifierOffsets = (const uint32_t *)BlobStart;
1247 IdentifiersLoaded.resize(Record[0]);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001248 if (PP)
1249 PP->getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregorafaf3082009-04-11 00:14:32 +00001250 break;
Douglas Gregorfdd01722009-04-14 00:24:19 +00001251
1252 case pch::EXTERNAL_DEFINITIONS:
1253 if (!ExternalDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001254 Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
Douglas Gregorfdd01722009-04-14 00:24:19 +00001255 return Failure;
1256 }
1257 ExternalDefinitions.swap(Record);
1258 break;
Douglas Gregor3e1af842009-04-17 22:13:46 +00001259
Douglas Gregorad1de002009-04-18 05:55:16 +00001260 case pch::SPECIAL_TYPES:
1261 SpecialTypes.swap(Record);
1262 break;
1263
Douglas Gregor3e1af842009-04-17 22:13:46 +00001264 case pch::STATISTICS:
1265 TotalNumStatements = Record[0];
Douglas Gregor37e26842009-04-21 23:56:24 +00001266 TotalNumMacros = Record[1];
Douglas Gregor25123082009-04-22 22:34:57 +00001267 TotalLexicalDeclContexts = Record[2];
1268 TotalVisibleDeclContexts = Record[3];
Douglas Gregor3e1af842009-04-17 22:13:46 +00001269 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001270
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001271 case pch::TENTATIVE_DEFINITIONS:
1272 if (!TentativeDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001273 Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001274 return Failure;
1275 }
1276 TentativeDefinitions.swap(Record);
1277 break;
Douglas Gregor14c22f22009-04-22 22:18:58 +00001278
1279 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
1280 if (!LocallyScopedExternalDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001281 Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
Douglas Gregor14c22f22009-04-22 22:18:58 +00001282 return Failure;
1283 }
1284 LocallyScopedExternalDecls.swap(Record);
1285 break;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001286
Douglas Gregor83941df2009-04-25 17:48:32 +00001287 case pch::SELECTOR_OFFSETS:
1288 SelectorOffsets = (const uint32_t *)BlobStart;
1289 TotalNumSelectors = Record[0];
1290 SelectorsLoaded.resize(TotalNumSelectors);
1291 break;
1292
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001293 case pch::METHOD_POOL:
Douglas Gregor83941df2009-04-25 17:48:32 +00001294 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1295 if (Record[0])
1296 MethodPoolLookupTable
1297 = PCHMethodPoolLookupTable::Create(
1298 MethodPoolLookupTableData + Record[0],
1299 MethodPoolLookupTableData,
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001300 PCHMethodPoolLookupTrait(*this));
Douglas Gregor83941df2009-04-25 17:48:32 +00001301 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001302 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001303
1304 case pch::PP_COUNTER_VALUE:
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001305 if (!Record.empty() && Listener)
1306 Listener->ReadCounter(Record[0]);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001307 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001308
1309 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner090d9b52009-04-27 19:01:47 +00001310 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001311 TotalNumSLocEntries = Record[0];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001312 SourceMgr.PreallocateSLocEntries(this,
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001313 TotalNumSLocEntries,
1314 Record[1]);
1315 break;
1316
1317 case pch::SOURCE_LOCATION_PRELOADS:
1318 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1319 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1320 if (Result != Success)
1321 return Result;
1322 }
1323 break;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001324
1325 case pch::STAT_CACHE:
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001326 FileMgr.setStatCache(
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001327 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1328 (const unsigned char *)BlobStart,
1329 NumStatHits, NumStatMisses));
1330 break;
Douglas Gregorb81c1702009-04-27 20:06:05 +00001331
1332 case pch::EXT_VECTOR_DECLS:
1333 if (!ExtVectorDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001334 Error("duplicate EXT_VECTOR_DECLS record in PCH file");
Douglas Gregorb81c1702009-04-27 20:06:05 +00001335 return Failure;
1336 }
1337 ExtVectorDecls.swap(Record);
1338 break;
1339
1340 case pch::OBJC_CATEGORY_IMPLEMENTATIONS:
1341 if (!ObjCCategoryImpls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001342 Error("duplicate OBJC_CATEGORY_IMPLEMENTATIONS record in PCH file");
Douglas Gregorb81c1702009-04-27 20:06:05 +00001343 return Failure;
1344 }
1345 ObjCCategoryImpls.swap(Record);
1346 break;
Douglas Gregorb64c1932009-05-12 01:31:05 +00001347
1348 case pch::ORIGINAL_FILE_NAME:
1349 OriginalFileName.assign(BlobStart, BlobLen);
1350 break;
Douglas Gregorafaf3082009-04-11 00:14:32 +00001351 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001352 }
Douglas Gregora02b1472009-04-28 21:53:25 +00001353 Error("premature end of bitstream in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001354 return Failure;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001355}
1356
Douglas Gregore1d918e2009-04-10 23:10:45 +00001357PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001358 // Set the PCH file name.
1359 this->FileName = FileName;
1360
Douglas Gregor2cf26342009-04-09 22:27:44 +00001361 // Open the PCH file.
1362 std::string ErrStr;
1363 Buffer.reset(llvm::MemoryBuffer::getFile(FileName.c_str(), &ErrStr));
Douglas Gregore1d918e2009-04-10 23:10:45 +00001364 if (!Buffer) {
1365 Error(ErrStr.c_str());
1366 return IgnorePCH;
1367 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001368
1369 // Initialize the stream
Chris Lattnerb9fa9172009-04-26 20:59:20 +00001370 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
1371 (const unsigned char *)Buffer->getBufferEnd());
1372 Stream.init(StreamFile);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001373
1374 // Sniff for the signature.
1375 if (Stream.Read(8) != 'C' ||
1376 Stream.Read(8) != 'P' ||
1377 Stream.Read(8) != 'C' ||
Douglas Gregore1d918e2009-04-10 23:10:45 +00001378 Stream.Read(8) != 'H') {
Douglas Gregora02b1472009-04-28 21:53:25 +00001379 Diag(diag::err_not_a_pch_file) << FileName;
1380 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001381 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001382
Douglas Gregor2cf26342009-04-09 22:27:44 +00001383 while (!Stream.AtEndOfStream()) {
1384 unsigned Code = Stream.ReadCode();
1385
Douglas Gregore1d918e2009-04-10 23:10:45 +00001386 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001387 Error("invalid record at top-level of PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001388 return Failure;
1389 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001390
1391 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregor668c1a42009-04-21 22:25:48 +00001392
Douglas Gregor2cf26342009-04-09 22:27:44 +00001393 // We only know the PCH subblock ID.
1394 switch (BlockID) {
1395 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001396 if (Stream.ReadBlockInfoBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001397 Error("malformed BlockInfoBlock in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001398 return Failure;
1399 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001400 break;
1401 case pch::PCH_BLOCK_ID:
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001402 switch (ReadPCHBlock()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001403 case Success:
1404 break;
1405
1406 case Failure:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001407 return Failure;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001408
1409 case IgnorePCH:
Douglas Gregor2bec0412009-04-10 21:16:55 +00001410 // FIXME: We could consider reading through to the end of this
1411 // PCH block, skipping subblocks, to see if there are other
1412 // PCH blocks elsewhere.
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001413
1414 // Clear out any preallocated source location entries, so that
1415 // the source manager does not try to resolve them later.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001416 SourceMgr.ClearPreallocatedSLocEntries();
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001417
1418 // Remove the stat cache.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001419 FileMgr.setStatCache(0);
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001420
Douglas Gregore1d918e2009-04-10 23:10:45 +00001421 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001422 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001423 break;
1424 default:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001425 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001426 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001427 return Failure;
1428 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001429 break;
1430 }
1431 }
Douglas Gregor92b059e2009-04-28 20:33:11 +00001432
1433 // Check the predefines buffer.
1434 if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
1435 PCHPredefinesBufferID))
1436 return IgnorePCH;
1437
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001438 if (PP) {
1439 // Initialization of builtins and library builtins occurs before the
1440 // PCH file is read, so there may be some identifiers that were
1441 // loaded into the IdentifierTable before we intercepted the
1442 // creation of identifiers. Iterate through the list of known
1443 // identifiers and determine whether we have to establish
1444 // preprocessor definitions or top-level identifier declaration
1445 // chains for those identifiers.
1446 //
1447 // We copy the IdentifierInfo pointers to a small vector first,
1448 // since de-serializing declarations or macro definitions can add
1449 // new entries into the identifier table, invalidating the
1450 // iterators.
1451 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1452 for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
1453 IdEnd = PP->getIdentifierTable().end();
1454 Id != IdEnd; ++Id)
1455 Identifiers.push_back(Id->second);
1456 PCHIdentifierLookupTable *IdTable
1457 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1458 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1459 IdentifierInfo *II = Identifiers[I];
1460 // Look in the on-disk hash table for an entry for
1461 PCHIdentifierLookupTrait Info(*this, II);
1462 std::pair<const char*, unsigned> Key(II->getName(), II->getLength());
1463 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1464 if (Pos == IdTable->end())
1465 continue;
1466
1467 // Dereferencing the iterator has the effect of populating the
1468 // IdentifierInfo node with the various declarations it needs.
1469 (void)*Pos;
1470 }
Douglas Gregor668c1a42009-04-21 22:25:48 +00001471 }
1472
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001473 if (Context)
1474 InitializeContext(*Context);
Douglas Gregor0b748912009-04-14 21:18:50 +00001475
Douglas Gregor668c1a42009-04-21 22:25:48 +00001476 return Success;
Douglas Gregor0b748912009-04-14 21:18:50 +00001477}
1478
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001479void PCHReader::InitializeContext(ASTContext &Ctx) {
1480 Context = &Ctx;
1481 assert(Context && "Passed null context!");
1482
1483 assert(PP && "Forgot to set Preprocessor ?");
1484 PP->getIdentifierTable().setExternalIdentifierLookup(this);
1485 PP->getHeaderSearchInfo().SetExternalLookup(this);
1486
1487 // Load the translation unit declaration
1488 ReadDeclRecord(DeclOffsets[0], 0);
1489
1490 // Load the special types.
1491 Context->setBuiltinVaListType(
1492 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
1493 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1494 Context->setObjCIdType(GetType(Id));
1495 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1496 Context->setObjCSelType(GetType(Sel));
1497 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1498 Context->setObjCProtoType(GetType(Proto));
1499 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1500 Context->setObjCClassType(GetType(Class));
1501 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1502 Context->setCFConstantStringType(GetType(String));
1503 if (unsigned FastEnum
1504 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1505 Context->setObjCFastEnumerationStateType(GetType(FastEnum));
1506}
1507
Douglas Gregorb64c1932009-05-12 01:31:05 +00001508/// \brief Retrieve the name of the original source file name
1509/// directly from the PCH file, without actually loading the PCH
1510/// file.
1511std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
1512 // Open the PCH file.
1513 std::string ErrStr;
1514 llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
1515 Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
1516 if (!Buffer) {
1517 fprintf(stderr, "error: %s\n", ErrStr.c_str());
1518 return std::string();
1519 }
1520
1521 // Initialize the stream
1522 llvm::BitstreamReader StreamFile;
1523 llvm::BitstreamCursor Stream;
1524 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
1525 (const unsigned char *)Buffer->getBufferEnd());
1526 Stream.init(StreamFile);
1527
1528 // Sniff for the signature.
1529 if (Stream.Read(8) != 'C' ||
1530 Stream.Read(8) != 'P' ||
1531 Stream.Read(8) != 'C' ||
1532 Stream.Read(8) != 'H') {
1533 fprintf(stderr,
1534 "error: '%s' does not appear to be a precompiled header file\n",
1535 PCHFileName.c_str());
1536 return std::string();
1537 }
1538
1539 RecordData Record;
1540 while (!Stream.AtEndOfStream()) {
1541 unsigned Code = Stream.ReadCode();
1542
1543 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1544 unsigned BlockID = Stream.ReadSubBlockID();
1545
1546 // We only know the PCH subblock ID.
1547 switch (BlockID) {
1548 case pch::PCH_BLOCK_ID:
1549 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
1550 fprintf(stderr, "error: malformed block record in PCH file\n");
1551 return std::string();
1552 }
1553 break;
1554
1555 default:
1556 if (Stream.SkipBlock()) {
1557 fprintf(stderr, "error: malformed block record in PCH file\n");
1558 return std::string();
1559 }
1560 break;
1561 }
1562 continue;
1563 }
1564
1565 if (Code == llvm::bitc::END_BLOCK) {
1566 if (Stream.ReadBlockEnd()) {
1567 fprintf(stderr, "error: error at end of module block in PCH file\n");
1568 return std::string();
1569 }
1570 continue;
1571 }
1572
1573 if (Code == llvm::bitc::DEFINE_ABBREV) {
1574 Stream.ReadAbbrevRecord();
1575 continue;
1576 }
1577
1578 Record.clear();
1579 const char *BlobStart = 0;
1580 unsigned BlobLen = 0;
1581 if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
1582 == pch::ORIGINAL_FILE_NAME)
1583 return std::string(BlobStart, BlobLen);
1584 }
1585
1586 return std::string();
1587}
1588
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001589/// \brief Parse the record that corresponds to a LangOptions data
1590/// structure.
1591///
1592/// This routine compares the language options used to generate the
1593/// PCH file against the language options set for the current
1594/// compilation. For each option, we classify differences between the
1595/// two compiler states as either "benign" or "important". Benign
1596/// differences don't matter, and we accept them without complaint
1597/// (and without modifying the language options). Differences between
1598/// the states for important options cause the PCH file to be
1599/// unusable, so we emit a warning and return true to indicate that
1600/// there was an error.
1601///
1602/// \returns true if the PCH file is unacceptable, false otherwise.
1603bool PCHReader::ParseLanguageOptions(
1604 const llvm::SmallVectorImpl<uint64_t> &Record) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001605 if (Listener) {
1606 LangOptions LangOpts;
1607
1608 #define PARSE_LANGOPT(Option) \
1609 LangOpts.Option = Record[Idx]; \
1610 ++Idx
1611
1612 unsigned Idx = 0;
1613 PARSE_LANGOPT(Trigraphs);
1614 PARSE_LANGOPT(BCPLComment);
1615 PARSE_LANGOPT(DollarIdents);
1616 PARSE_LANGOPT(AsmPreprocessor);
1617 PARSE_LANGOPT(GNUMode);
1618 PARSE_LANGOPT(ImplicitInt);
1619 PARSE_LANGOPT(Digraphs);
1620 PARSE_LANGOPT(HexFloats);
1621 PARSE_LANGOPT(C99);
1622 PARSE_LANGOPT(Microsoft);
1623 PARSE_LANGOPT(CPlusPlus);
1624 PARSE_LANGOPT(CPlusPlus0x);
1625 PARSE_LANGOPT(CXXOperatorNames);
1626 PARSE_LANGOPT(ObjC1);
1627 PARSE_LANGOPT(ObjC2);
1628 PARSE_LANGOPT(ObjCNonFragileABI);
1629 PARSE_LANGOPT(PascalStrings);
1630 PARSE_LANGOPT(WritableStrings);
1631 PARSE_LANGOPT(LaxVectorConversions);
1632 PARSE_LANGOPT(Exceptions);
1633 PARSE_LANGOPT(NeXTRuntime);
1634 PARSE_LANGOPT(Freestanding);
1635 PARSE_LANGOPT(NoBuiltin);
1636 PARSE_LANGOPT(ThreadsafeStatics);
1637 PARSE_LANGOPT(Blocks);
1638 PARSE_LANGOPT(EmitAllDecls);
1639 PARSE_LANGOPT(MathErrno);
1640 PARSE_LANGOPT(OverflowChecking);
1641 PARSE_LANGOPT(HeinousExtensions);
1642 PARSE_LANGOPT(Optimize);
1643 PARSE_LANGOPT(OptimizeSize);
1644 PARSE_LANGOPT(Static);
1645 PARSE_LANGOPT(PICLevel);
1646 PARSE_LANGOPT(GNUInline);
1647 PARSE_LANGOPT(NoInline);
1648 PARSE_LANGOPT(AccessControl);
1649 PARSE_LANGOPT(CharIsSigned);
1650 LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
1651 ++Idx;
1652 LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
1653 ++Idx;
1654 PARSE_LANGOPT(InstantiationDepth);
1655 #undef PARSE_LANGOPT
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001656
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001657 return Listener->ReadLanguageOptions(LangOpts);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001658 }
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001659
1660 return false;
1661}
1662
Douglas Gregor2cf26342009-04-09 22:27:44 +00001663/// \brief Read and return the type at the given offset.
1664///
1665/// This routine actually reads the record corresponding to the type
1666/// at the given offset in the bitstream. It is a helper routine for
1667/// GetType, which deals with reading type IDs.
1668QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregor0b748912009-04-14 21:18:50 +00001669 // Keep track of where we are in the stream, then jump back there
1670 // after reading this type.
1671 SavedStreamPosition SavedPosition(Stream);
1672
Douglas Gregor2cf26342009-04-09 22:27:44 +00001673 Stream.JumpToBit(Offset);
1674 RecordData Record;
1675 unsigned Code = Stream.ReadCode();
1676 switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
Douglas Gregor6d473962009-04-15 22:00:08 +00001677 case pch::TYPE_EXT_QUAL: {
1678 assert(Record.size() == 3 &&
1679 "Incorrect encoding of extended qualifier type");
1680 QualType Base = GetType(Record[0]);
1681 QualType::GCAttrTypes GCAttr = (QualType::GCAttrTypes)Record[1];
1682 unsigned AddressSpace = Record[2];
1683
1684 QualType T = Base;
1685 if (GCAttr != QualType::GCNone)
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001686 T = Context->getObjCGCQualType(T, GCAttr);
Douglas Gregor6d473962009-04-15 22:00:08 +00001687 if (AddressSpace)
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001688 T = Context->getAddrSpaceQualType(T, AddressSpace);
Douglas Gregor6d473962009-04-15 22:00:08 +00001689 return T;
1690 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001691
Douglas Gregor2cf26342009-04-09 22:27:44 +00001692 case pch::TYPE_FIXED_WIDTH_INT: {
1693 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001694 return Context->getFixedWidthIntType(Record[0], Record[1]);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001695 }
1696
1697 case pch::TYPE_COMPLEX: {
1698 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1699 QualType ElemType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001700 return Context->getComplexType(ElemType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001701 }
1702
1703 case pch::TYPE_POINTER: {
1704 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1705 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001706 return Context->getPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001707 }
1708
1709 case pch::TYPE_BLOCK_POINTER: {
1710 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1711 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001712 return Context->getBlockPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001713 }
1714
1715 case pch::TYPE_LVALUE_REFERENCE: {
1716 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1717 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001718 return Context->getLValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001719 }
1720
1721 case pch::TYPE_RVALUE_REFERENCE: {
1722 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1723 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001724 return Context->getRValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001725 }
1726
1727 case pch::TYPE_MEMBER_POINTER: {
1728 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1729 QualType PointeeType = GetType(Record[0]);
1730 QualType ClassType = GetType(Record[1]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001731 return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
Douglas Gregor2cf26342009-04-09 22:27:44 +00001732 }
1733
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001734 case pch::TYPE_CONSTANT_ARRAY: {
1735 QualType ElementType = GetType(Record[0]);
1736 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1737 unsigned IndexTypeQuals = Record[2];
1738 unsigned Idx = 3;
1739 llvm::APInt Size = ReadAPInt(Record, Idx);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001740 return Context->getConstantArrayType(ElementType, Size, ASM,IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001741 }
1742
1743 case pch::TYPE_INCOMPLETE_ARRAY: {
1744 QualType ElementType = GetType(Record[0]);
1745 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1746 unsigned IndexTypeQuals = Record[2];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001747 return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001748 }
1749
1750 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregor0b748912009-04-14 21:18:50 +00001751 QualType ElementType = GetType(Record[0]);
1752 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1753 unsigned IndexTypeQuals = Record[2];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001754 return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
1755 ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001756 }
1757
1758 case pch::TYPE_VECTOR: {
1759 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001760 Error("incorrect encoding of vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001761 return QualType();
1762 }
1763
1764 QualType ElementType = GetType(Record[0]);
1765 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001766 return Context->getVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001767 }
1768
1769 case pch::TYPE_EXT_VECTOR: {
1770 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001771 Error("incorrect encoding of extended vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001772 return QualType();
1773 }
1774
1775 QualType ElementType = GetType(Record[0]);
1776 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001777 return Context->getExtVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001778 }
1779
1780 case pch::TYPE_FUNCTION_NO_PROTO: {
1781 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001782 Error("incorrect encoding of no-proto function type");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001783 return QualType();
1784 }
1785 QualType ResultType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001786 return Context->getFunctionNoProtoType(ResultType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001787 }
1788
1789 case pch::TYPE_FUNCTION_PROTO: {
1790 QualType ResultType = GetType(Record[0]);
1791 unsigned Idx = 1;
1792 unsigned NumParams = Record[Idx++];
1793 llvm::SmallVector<QualType, 16> ParamTypes;
1794 for (unsigned I = 0; I != NumParams; ++I)
1795 ParamTypes.push_back(GetType(Record[Idx++]));
1796 bool isVariadic = Record[Idx++];
1797 unsigned Quals = Record[Idx++];
Sebastian Redl465226e2009-05-27 22:11:52 +00001798 bool hasExceptionSpec = Record[Idx++];
1799 bool hasAnyExceptionSpec = Record[Idx++];
1800 unsigned NumExceptions = Record[Idx++];
1801 llvm::SmallVector<QualType, 2> Exceptions;
1802 for (unsigned I = 0; I != NumExceptions; ++I)
1803 Exceptions.push_back(GetType(Record[Idx++]));
Jay Foadbeaaccd2009-05-21 09:52:38 +00001804 return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
Sebastian Redl465226e2009-05-27 22:11:52 +00001805 isVariadic, Quals, hasExceptionSpec,
1806 hasAnyExceptionSpec, NumExceptions,
1807 Exceptions.data());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001808 }
1809
1810 case pch::TYPE_TYPEDEF:
Douglas Gregora02b1472009-04-28 21:53:25 +00001811 assert(Record.size() == 1 && "incorrect encoding of typedef type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001812 return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001813
1814 case pch::TYPE_TYPEOF_EXPR:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001815 return Context->getTypeOfExprType(ReadTypeExpr());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001816
1817 case pch::TYPE_TYPEOF: {
1818 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001819 Error("incorrect encoding of typeof(type) in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001820 return QualType();
1821 }
1822 QualType UnderlyingType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001823 return Context->getTypeOfType(UnderlyingType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001824 }
1825
1826 case pch::TYPE_RECORD:
Douglas Gregora02b1472009-04-28 21:53:25 +00001827 assert(Record.size() == 1 && "incorrect encoding of record type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001828 return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001829
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001830 case pch::TYPE_ENUM:
Douglas Gregora02b1472009-04-28 21:53:25 +00001831 assert(Record.size() == 1 && "incorrect encoding of enum type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001832 return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001833
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001834 case pch::TYPE_OBJC_INTERFACE:
Douglas Gregora02b1472009-04-28 21:53:25 +00001835 assert(Record.size() == 1 && "incorrect encoding of objc interface type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001836 return Context->getObjCInterfaceType(
Chris Lattner4dcf151a2009-04-22 05:57:30 +00001837 cast<ObjCInterfaceDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001838
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001839 case pch::TYPE_OBJC_QUALIFIED_INTERFACE: {
1840 unsigned Idx = 0;
1841 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1842 unsigned NumProtos = Record[Idx++];
1843 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1844 for (unsigned I = 0; I != NumProtos; ++I)
1845 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Douglas Gregor75fdb232009-05-22 22:45:36 +00001846 return Context->getObjCQualifiedInterfaceType(ItfD, Protos.data(), NumProtos);
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001847 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001848
Steve Naroffd1b3c2d2009-06-17 22:40:22 +00001849 case pch::TYPE_OBJC_OBJECT_POINTER: {
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001850 unsigned Idx = 0;
Steve Naroffd1b3c2d2009-06-17 22:40:22 +00001851 ObjCInterfaceDecl *ItfD =
1852 cast_or_null<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001853 unsigned NumProtos = Record[Idx++];
1854 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1855 for (unsigned I = 0; I != NumProtos; ++I)
1856 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroffd1b3c2d2009-06-17 22:40:22 +00001857 return Context->getObjCObjectPointerType(ItfD, Protos.data(), NumProtos);
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001858 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001859 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001860 // Suppress a GCC warning
1861 return QualType();
1862}
1863
Douglas Gregor2cf26342009-04-09 22:27:44 +00001864
Douglas Gregor8038d512009-04-10 17:25:41 +00001865QualType PCHReader::GetType(pch::TypeID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001866 unsigned Quals = ID & 0x07;
1867 unsigned Index = ID >> 3;
1868
1869 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
1870 QualType T;
1871 switch ((pch::PredefinedTypeIDs)Index) {
1872 case pch::PREDEF_TYPE_NULL_ID: return QualType();
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001873 case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
1874 case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001875
1876 case pch::PREDEF_TYPE_CHAR_U_ID:
1877 case pch::PREDEF_TYPE_CHAR_S_ID:
1878 // FIXME: Check that the signedness of CharTy is correct!
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001879 T = Context->CharTy;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001880 break;
1881
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001882 case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
1883 case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
1884 case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
1885 case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
1886 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00001887 case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001888 case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
1889 case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
1890 case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
1891 case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
1892 case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
1893 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00001894 case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001895 case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
1896 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
1897 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
1898 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
1899 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
Sebastian Redl6e8ed162009-05-10 18:38:11 +00001900 case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001901 }
1902
1903 assert(!T.isNull() && "Unknown predefined type");
1904 return T.getQualifiedType(Quals);
1905 }
1906
1907 Index -= pch::NUM_PREDEF_TYPE_IDS;
Douglas Gregor366809a2009-04-26 03:49:13 +00001908 assert(Index < TypesLoaded.size() && "Type index out-of-range");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001909 if (!TypesLoaded[Index])
1910 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]).getTypePtr();
Douglas Gregor2cf26342009-04-09 22:27:44 +00001911
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001912 return QualType(TypesLoaded[Index], Quals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001913}
1914
Douglas Gregor8038d512009-04-10 17:25:41 +00001915Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001916 if (ID == 0)
1917 return 0;
1918
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001919 if (ID > DeclsLoaded.size()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001920 Error("declaration ID out-of-range for PCH file");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001921 return 0;
1922 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001923
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001924 unsigned Index = ID - 1;
1925 if (!DeclsLoaded[Index])
1926 ReadDeclRecord(DeclOffsets[Index], Index);
1927
1928 return DeclsLoaded[Index];
Douglas Gregor2cf26342009-04-09 22:27:44 +00001929}
1930
Chris Lattner887e2b32009-04-27 05:46:25 +00001931/// \brief Resolve the offset of a statement into a statement.
1932///
1933/// This operation will read a new statement from the external
1934/// source each time it is called, and is meant to be used via a
1935/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
1936Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattnerda930612009-04-27 05:58:23 +00001937 // Since we know tha this statement is part of a decl, make sure to use the
1938 // decl cursor to read it.
1939 DeclsCursor.JumpToBit(Offset);
1940 return ReadStmt(DeclsCursor);
Douglas Gregor250fc9c2009-04-18 00:07:54 +00001941}
1942
Douglas Gregor2cf26342009-04-09 22:27:44 +00001943bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor8038d512009-04-10 17:25:41 +00001944 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001945 assert(DC->hasExternalLexicalStorage() &&
1946 "DeclContext has no lexical decls in storage");
1947 uint64_t Offset = DeclContextOffsets[DC].first;
1948 assert(Offset && "DeclContext has no lexical decls in storage");
1949
Douglas Gregor0b748912009-04-14 21:18:50 +00001950 // Keep track of where we are in the stream, then jump back there
1951 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001952 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001953
Douglas Gregor2cf26342009-04-09 22:27:44 +00001954 // Load the record containing all of the declarations lexically in
1955 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001956 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001957 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001958 unsigned Code = DeclsCursor.ReadCode();
1959 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001960 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001961 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
1962
1963 // Load all of the declaration IDs
1964 Decls.clear();
1965 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregor25123082009-04-22 22:34:57 +00001966 ++NumLexicalDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001967 return false;
1968}
1969
1970bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001971 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00001972 assert(DC->hasExternalVisibleStorage() &&
1973 "DeclContext has no visible decls in storage");
1974 uint64_t Offset = DeclContextOffsets[DC].second;
1975 assert(Offset && "DeclContext has no visible decls in storage");
1976
Douglas Gregor0b748912009-04-14 21:18:50 +00001977 // Keep track of where we are in the stream, then jump back there
1978 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001979 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001980
Douglas Gregor2cf26342009-04-09 22:27:44 +00001981 // Load the record containing all of the declarations visible in
1982 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001983 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001984 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00001985 unsigned Code = DeclsCursor.ReadCode();
1986 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00001987 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001988 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
1989 if (Record.size() == 0)
1990 return false;
1991
1992 Decls.clear();
1993
1994 unsigned Idx = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001995 while (Idx < Record.size()) {
1996 Decls.push_back(VisibleDeclaration());
1997 Decls.back().Name = ReadDeclarationName(Record, Idx);
1998
Douglas Gregor2cf26342009-04-09 22:27:44 +00001999 unsigned Size = Record[Idx++];
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002000 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002001 LoadedDecls.reserve(Size);
2002 for (unsigned I = 0; I < Size; ++I)
2003 LoadedDecls.push_back(Record[Idx++]);
2004 }
2005
Douglas Gregor25123082009-04-22 22:34:57 +00002006 ++NumVisibleDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002007 return false;
2008}
2009
Douglas Gregorfdd01722009-04-14 00:24:19 +00002010void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor0af2ca42009-04-22 19:09:20 +00002011 this->Consumer = Consumer;
2012
Douglas Gregorfdd01722009-04-14 00:24:19 +00002013 if (!Consumer)
2014 return;
2015
2016 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
2017 Decl *D = GetDecl(ExternalDefinitions[I]);
2018 DeclGroupRef DG(D);
2019 Consumer->HandleTopLevelDecl(DG);
2020 }
Douglas Gregorc62a2fe2009-04-25 00:41:30 +00002021
2022 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
2023 DeclGroupRef DG(InterestingDecls[I]);
2024 Consumer->HandleTopLevelDecl(DG);
2025 }
Douglas Gregorfdd01722009-04-14 00:24:19 +00002026}
2027
Douglas Gregor2cf26342009-04-09 22:27:44 +00002028void PCHReader::PrintStats() {
2029 std::fprintf(stderr, "*** PCH Statistics:\n");
2030
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002031 unsigned NumTypesLoaded
2032 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
2033 (Type *)0);
2034 unsigned NumDeclsLoaded
2035 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
2036 (Decl *)0);
2037 unsigned NumIdentifiersLoaded
2038 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
2039 IdentifiersLoaded.end(),
2040 (IdentifierInfo *)0);
2041 unsigned NumSelectorsLoaded
2042 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
2043 SelectorsLoaded.end(),
2044 Selector());
Douglas Gregor2d41cc12009-04-13 20:50:16 +00002045
Douglas Gregor4fed3f42009-04-27 18:38:38 +00002046 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
2047 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002048 if (TotalNumSLocEntries)
2049 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
2050 NumSLocEntriesRead, TotalNumSLocEntries,
2051 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002052 if (!TypesLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002053 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002054 NumTypesLoaded, (unsigned)TypesLoaded.size(),
2055 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
2056 if (!DeclsLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002057 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002058 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
2059 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002060 if (!IdentifiersLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002061 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002062 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
2063 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor83941df2009-04-25 17:48:32 +00002064 if (TotalNumSelectors)
2065 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
2066 NumSelectorsLoaded, TotalNumSelectors,
2067 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
2068 if (TotalNumStatements)
2069 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
2070 NumStatementsRead, TotalNumStatements,
2071 ((float)NumStatementsRead/TotalNumStatements * 100));
2072 if (TotalNumMacros)
2073 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
2074 NumMacrosRead, TotalNumMacros,
2075 ((float)NumMacrosRead/TotalNumMacros * 100));
2076 if (TotalLexicalDeclContexts)
2077 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
2078 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
2079 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
2080 * 100));
2081 if (TotalVisibleDeclContexts)
2082 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
2083 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
2084 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
2085 * 100));
2086 if (TotalSelectorsInMethodPool) {
2087 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
2088 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
2089 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
2090 * 100));
2091 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
2092 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00002093 std::fprintf(stderr, "\n");
2094}
2095
Douglas Gregor668c1a42009-04-21 22:25:48 +00002096void PCHReader::InitializeSema(Sema &S) {
2097 SemaObj = &S;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002098 S.ExternalSource = this;
2099
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002100 // Makes sure any declarations that were deserialized "too early"
2101 // still get added to the identifier's declaration chains.
2102 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
2103 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
2104 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregor668c1a42009-04-21 22:25:48 +00002105 }
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002106 PreloadedDecls.clear();
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00002107
2108 // If there were any tentative definitions, deserialize them and add
2109 // them to Sema's table of tentative definitions.
2110 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
2111 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
2112 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
2113 }
Douglas Gregor14c22f22009-04-22 22:18:58 +00002114
2115 // If there were any locally-scoped external declarations,
2116 // deserialize them and add them to Sema's table of locally-scoped
2117 // external declarations.
2118 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
2119 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
2120 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
2121 }
Douglas Gregorb81c1702009-04-27 20:06:05 +00002122
2123 // If there were any ext_vector type declarations, deserialize them
2124 // and add them to Sema's vector of such declarations.
2125 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
2126 SemaObj->ExtVectorDecls.push_back(
2127 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
2128
2129 // If there were any Objective-C category implementations,
2130 // deserialize them and add them to Sema's vector of such
2131 // definitions.
2132 for (unsigned I = 0, N = ObjCCategoryImpls.size(); I != N; ++I)
2133 SemaObj->ObjCCategoryImpls.push_back(
2134 cast<ObjCCategoryImplDecl>(GetDecl(ObjCCategoryImpls[I])));
Douglas Gregor668c1a42009-04-21 22:25:48 +00002135}
2136
2137IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
2138 // Try to find this name within our on-disk hash table
2139 PCHIdentifierLookupTable *IdTable
2140 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
2141 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
2142 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
2143 if (Pos == IdTable->end())
2144 return 0;
2145
2146 // Dereferencing the iterator has the effect of building the
2147 // IdentifierInfo node and populating it with the various
2148 // declarations it needs.
2149 return *Pos;
2150}
2151
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002152std::pair<ObjCMethodList, ObjCMethodList>
2153PCHReader::ReadMethodPool(Selector Sel) {
2154 if (!MethodPoolLookupTable)
2155 return std::pair<ObjCMethodList, ObjCMethodList>();
2156
2157 // Try to find this selector within our on-disk hash table.
2158 PCHMethodPoolLookupTable *PoolTable
2159 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
2160 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor83941df2009-04-25 17:48:32 +00002161 if (Pos == PoolTable->end()) {
2162 ++NumMethodPoolMisses;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002163 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor83941df2009-04-25 17:48:32 +00002164 }
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002165
Douglas Gregor83941df2009-04-25 17:48:32 +00002166 ++NumMethodPoolSelectorsRead;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002167 return *Pos;
2168}
2169
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002170void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregor668c1a42009-04-21 22:25:48 +00002171 assert(ID && "Non-zero identifier ID required");
Douglas Gregora02b1472009-04-28 21:53:25 +00002172 assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002173 IdentifiersLoaded[ID - 1] = II;
Douglas Gregor668c1a42009-04-21 22:25:48 +00002174}
2175
Chris Lattner7356a312009-04-11 21:15:38 +00002176IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00002177 if (ID == 0)
2178 return 0;
Chris Lattner7356a312009-04-11 21:15:38 +00002179
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002180 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002181 Error("no identifier table in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00002182 return 0;
2183 }
Chris Lattner7356a312009-04-11 21:15:38 +00002184
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002185 assert(PP && "Forgot to set Preprocessor ?");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002186 if (!IdentifiersLoaded[ID - 1]) {
2187 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00002188 const char *Str = IdentifierTableData + Offset;
Douglas Gregord6595a42009-04-25 21:04:17 +00002189
Douglas Gregor02fc7512009-04-28 20:01:51 +00002190 // All of the strings in the PCH file are preceded by a 16-bit
2191 // length. Extract that 16-bit length to avoid having to execute
2192 // strlen().
2193 const char *StrLenPtr = Str - 2;
2194 unsigned StrLen = (((unsigned) StrLenPtr[0])
2195 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
2196 IdentifiersLoaded[ID - 1]
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002197 = &PP->getIdentifierTable().get(Str, Str + StrLen);
Douglas Gregorafaf3082009-04-11 00:14:32 +00002198 }
Chris Lattner7356a312009-04-11 21:15:38 +00002199
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002200 return IdentifiersLoaded[ID - 1];
Douglas Gregor2cf26342009-04-09 22:27:44 +00002201}
2202
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002203void PCHReader::ReadSLocEntry(unsigned ID) {
2204 ReadSLocEntryRecord(ID);
2205}
2206
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002207Selector PCHReader::DecodeSelector(unsigned ID) {
2208 if (ID == 0)
2209 return Selector();
2210
Douglas Gregora02b1472009-04-28 21:53:25 +00002211 if (!MethodPoolLookupTableData)
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002212 return Selector();
Douglas Gregor83941df2009-04-25 17:48:32 +00002213
2214 if (ID > TotalNumSelectors) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002215 Error("selector ID out of range in PCH file");
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002216 return Selector();
2217 }
Douglas Gregor83941df2009-04-25 17:48:32 +00002218
2219 unsigned Index = ID - 1;
2220 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
2221 // Load this selector from the selector table.
2222 // FIXME: endianness portability issues with SelectorOffsets table
2223 PCHMethodPoolLookupTrait Trait(*this);
2224 SelectorsLoaded[Index]
2225 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
2226 }
2227
2228 return SelectorsLoaded[Index];
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002229}
2230
Douglas Gregor2cf26342009-04-09 22:27:44 +00002231DeclarationName
2232PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
2233 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
2234 switch (Kind) {
2235 case DeclarationName::Identifier:
2236 return DeclarationName(GetIdentifierInfo(Record, Idx));
2237
2238 case DeclarationName::ObjCZeroArgSelector:
2239 case DeclarationName::ObjCOneArgSelector:
2240 case DeclarationName::ObjCMultiArgSelector:
Steve Naroffa7503a72009-04-23 15:15:40 +00002241 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002242
2243 case DeclarationName::CXXConstructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002244 return Context->DeclarationNames.getCXXConstructorName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002245 GetType(Record[Idx++]));
2246
2247 case DeclarationName::CXXDestructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002248 return Context->DeclarationNames.getCXXDestructorName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002249 GetType(Record[Idx++]));
2250
2251 case DeclarationName::CXXConversionFunctionName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002252 return Context->DeclarationNames.getCXXConversionFunctionName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002253 GetType(Record[Idx++]));
2254
2255 case DeclarationName::CXXOperatorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002256 return Context->DeclarationNames.getCXXOperatorName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002257 (OverloadedOperatorKind)Record[Idx++]);
2258
2259 case DeclarationName::CXXUsingDirective:
2260 return DeclarationName::getUsingDirectiveName();
2261 }
2262
2263 // Required to silence GCC warning
2264 return DeclarationName();
2265}
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002266
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00002267/// \brief Read an integral value
2268llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
2269 unsigned BitWidth = Record[Idx++];
2270 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
2271 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
2272 Idx += NumWords;
2273 return Result;
2274}
2275
2276/// \brief Read a signed integral value
2277llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
2278 bool isUnsigned = Record[Idx++];
2279 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
2280}
2281
Douglas Gregor17fc2232009-04-14 21:55:33 +00002282/// \brief Read a floating-point value
2283llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregor17fc2232009-04-14 21:55:33 +00002284 return llvm::APFloat(ReadAPInt(Record, Idx));
2285}
2286
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002287// \brief Read a string
2288std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
2289 unsigned Len = Record[Idx++];
Jay Foadbeaaccd2009-05-21 09:52:38 +00002290 std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002291 Idx += Len;
2292 return Result;
2293}
2294
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002295DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00002296 return Diag(SourceLocation(), DiagID);
2297}
2298
2299DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002300 return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002301}
Douglas Gregor025452f2009-04-17 00:04:06 +00002302
Douglas Gregor668c1a42009-04-21 22:25:48 +00002303/// \brief Retrieve the identifier table associated with the
2304/// preprocessor.
2305IdentifierTable &PCHReader::getIdentifierTable() {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002306 assert(PP && "Forgot to set Preprocessor ?");
2307 return PP->getIdentifierTable();
Douglas Gregor668c1a42009-04-21 22:25:48 +00002308}
2309
Douglas Gregor025452f2009-04-17 00:04:06 +00002310/// \brief Record that the given ID maps to the given switch-case
2311/// statement.
2312void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
2313 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
2314 SwitchCaseStmts[ID] = SC;
2315}
2316
2317/// \brief Retrieve the switch-case statement with the given ID.
2318SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
2319 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
2320 return SwitchCaseStmts[ID];
2321}
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002322
2323/// \brief Record that the given label statement has been
2324/// deserialized and has the given ID.
2325void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
2326 assert(LabelStmts.find(ID) == LabelStmts.end() &&
2327 "Deserialized label twice");
2328 LabelStmts[ID] = S;
2329
2330 // If we've already seen any goto statements that point to this
2331 // label, resolve them now.
2332 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
2333 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
2334 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
2335 Goto->second->setLabel(S);
2336 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002337
2338 // If we've already seen any address-label statements that point to
2339 // this label, resolve them now.
2340 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
2341 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
2342 = UnresolvedAddrLabelExprs.equal_range(ID);
2343 for (AddrLabelIter AddrLabel = AddrLabels.first;
2344 AddrLabel != AddrLabels.second; ++AddrLabel)
2345 AddrLabel->second->setLabel(S);
2346 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002347}
2348
2349/// \brief Set the label of the given statement to the label
2350/// identified by ID.
2351///
2352/// Depending on the order in which the label and other statements
2353/// referencing that label occur, this operation may complete
2354/// immediately (updating the statement) or it may queue the
2355/// statement to be back-patched later.
2356void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
2357 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2358 if (Label != LabelStmts.end()) {
2359 // We've already seen this label, so set the label of the goto and
2360 // we're done.
2361 S->setLabel(Label->second);
2362 } else {
2363 // We haven't seen this label yet, so add this goto to the set of
2364 // unresolved goto statements.
2365 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2366 }
2367}
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002368
2369/// \brief Set the label of the given expression to the label
2370/// identified by ID.
2371///
2372/// Depending on the order in which the label and other statements
2373/// referencing that label occur, this operation may complete
2374/// immediately (updating the statement) or it may queue the
2375/// statement to be back-patched later.
2376void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2377 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2378 if (Label != LabelStmts.end()) {
2379 // We've already seen this label, so set the label of the
2380 // label-address expression and we're done.
2381 S->setLabel(Label->second);
2382 } else {
2383 // We haven't seen this label yet, so add this label-address
2384 // expression to the set of unresolved label-address expressions.
2385 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2386 }
2387}