blob: ce7092753b28989228e0f3a1c208949f11deabe9 [file] [log] [blame]
Douglas Gregoref84c4b2009-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 Lattner92ba5ff2009-04-27 05:14:47 +000013
Douglas Gregoref84c4b2009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor55abb232009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregora868bbd2009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregor1a0d0b92009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregoref84c4b2009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregorfeb84b02009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregoref84c4b2009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
John McCall8f115c62009-10-16 21:56:05 +000021#include "clang/AST/TypeLocVisitor.h"
Chris Lattner34321bc2009-04-10 21:41:48 +000022#include "clang/Lex/MacroInfo.h"
Douglas Gregora7f71a92009-04-10 03:52:48 +000023#include "clang/Lex/Preprocessor.h"
Steve Naroff3fa455a2009-04-24 20:03:17 +000024#include "clang/Lex/HeaderSearch.h"
Douglas Gregora868bbd2009-04-21 22:25:48 +000025#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregora7f71a92009-04-10 03:52:48 +000026#include "clang/Basic/SourceManager.h"
Douglas Gregor4c7626e2009-04-13 16:31:14 +000027#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregora7f71a92009-04-10 03:52:48 +000028#include "clang/Basic/FileManager.h"
Douglas Gregorbfbde532009-04-10 21:16:55 +000029#include "clang/Basic/TargetInfo.h"
Douglas Gregord54f3a12009-10-05 21:07:28 +000030#include "clang/Basic/Version.h"
Daniel Dunbarf8502d52009-10-17 23:52:28 +000031#include "llvm/ADT/StringExtras.h"
Douglas Gregoref84c4b2009-04-09 22:27:44 +000032#include "llvm/Bitcode/BitstreamReader.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/MemoryBuffer.h"
John McCall0ad16662009-10-29 08:12:44 +000035#include "llvm/Support/ErrorHandling.h"
Douglas Gregoref84c4b2009-04-09 22:27:44 +000036#include <algorithm>
Douglas Gregorc379c072009-04-28 18:58:38 +000037#include <iterator>
Douglas Gregoref84c4b2009-04-09 22:27:44 +000038#include <cstdio>
Douglas Gregorc5046832009-04-27 18:38:38 +000039#include <sys/stat.h>
Douglas Gregoref84c4b2009-04-09 22:27:44 +000040using namespace clang;
41
42//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000043// PCH reader validator implementation
44//===----------------------------------------------------------------------===//
45
46PCHReaderListener::~PCHReaderListener() {}
47
48bool
49PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
50 const LangOptions &PPLangOpts = PP.getLangOptions();
51#define PARSE_LANGOPT_BENIGN(Option)
52#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
53 if (PPLangOpts.Option != LangOpts.Option) { \
54 Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
55 return true; \
56 }
57
58 PARSE_LANGOPT_BENIGN(Trigraphs);
59 PARSE_LANGOPT_BENIGN(BCPLComment);
60 PARSE_LANGOPT_BENIGN(DollarIdents);
61 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
62 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
63 PARSE_LANGOPT_BENIGN(ImplicitInt);
64 PARSE_LANGOPT_BENIGN(Digraphs);
65 PARSE_LANGOPT_BENIGN(HexFloats);
66 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
67 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
68 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
69 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
70 PARSE_LANGOPT_BENIGN(CXXOperatorName);
71 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
72 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
73 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
74 PARSE_LANGOPT_BENIGN(PascalStrings);
75 PARSE_LANGOPT_BENIGN(WritableStrings);
Mike Stump11289f42009-09-09 15:08:12 +000076 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000077 diag::warn_pch_lax_vector_conversions);
Nate Begeman9d905792009-06-25 22:57:40 +000078 PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000079 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
80 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
81 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
82 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
Mike Stump11289f42009-09-09 15:08:12 +000083 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000084 diag::warn_pch_thread_safe_statics);
Daniel Dunbara77eaeb2009-09-03 04:54:28 +000085 PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000086 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
87 PARSE_LANGOPT_BENIGN(EmitAllDecls);
88 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
89 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
Mike Stump11289f42009-09-09 15:08:12 +000090 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +000091 diag::warn_pch_heinous_extensions);
92 // FIXME: Most of the options below are benign if the macro wasn't
93 // used. Unfortunately, this means that a PCH compiled without
94 // optimization can't be used with optimization turned on, even
95 // though the only thing that changes is whether __OPTIMIZE__ was
96 // defined... but if __OPTIMIZE__ never showed up in the header, it
97 // doesn't matter. We could consider making this some special kind
98 // of check.
99 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
100 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
101 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
102 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
103 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
104 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
105 PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
106 PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
John Thompsoned4e2952009-11-05 20:14:16 +0000107 PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000108 if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Mike Stump11289f42009-09-09 15:08:12 +0000109 Reader.Diag(diag::warn_pch_gc_mode)
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000110 << LangOpts.getGCMode() << PPLangOpts.getGCMode();
111 return true;
112 }
113 PARSE_LANGOPT_BENIGN(getVisibilityMode());
Daniel Dunbar143021e2009-09-21 04:16:19 +0000114 PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(),
115 diag::warn_pch_stack_protector);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000116 PARSE_LANGOPT_BENIGN(InstantiationDepth);
Nate Begeman9d905792009-06-25 22:57:40 +0000117 PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
Daniel Dunbar143021e2009-09-21 04:16:19 +0000118 PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000119#undef PARSE_LANGOPT_IRRELEVANT
120#undef PARSE_LANGOPT_BENIGN
121
122 return false;
123}
124
125bool PCHValidator::ReadTargetTriple(const std::string &Triple) {
Daniel Dunbar40165182009-08-24 09:10:05 +0000126 if (Triple != PP.getTargetInfo().getTriple().getTriple()) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000127 Reader.Diag(diag::warn_pch_target_triple)
Daniel Dunbar40165182009-08-24 09:10:05 +0000128 << Triple << PP.getTargetInfo().getTriple().getTriple();
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000129 return true;
130 }
131 return false;
132}
133
134/// \brief Split the given string into a vector of lines, eliminating
135/// any empty lines in the process.
136///
137/// \param Str the string to split.
138/// \param Len the length of Str.
139/// \param KeepEmptyLines true if empty lines should be included
140/// \returns a vector of lines, with the line endings removed
141static std::vector<std::string> splitLines(const char *Str, unsigned Len,
142 bool KeepEmptyLines = false) {
143 std::vector<std::string> Lines;
144 for (unsigned LineStart = 0; LineStart < Len; ++LineStart) {
145 unsigned LineEnd = LineStart;
146 while (LineEnd < Len && Str[LineEnd] != '\n')
147 ++LineEnd;
148 if (LineStart != LineEnd || KeepEmptyLines)
149 Lines.push_back(std::string(&Str[LineStart], &Str[LineEnd]));
150 LineStart = LineEnd;
151 }
152 return Lines;
153}
154
Mike Stump11289f42009-09-09 15:08:12 +0000155bool PCHValidator::ReadPredefinesBuffer(const char *PCHPredef,
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000156 unsigned PCHPredefLen,
157 FileID PCHBufferID,
158 std::string &SuggestedPredefines) {
159 const char *Predef = PP.getPredefines().c_str();
160 unsigned PredefLen = PP.getPredefines().size();
161
162 // If the two predefines buffers compare equal, we're done!
Mike Stump11289f42009-09-09 15:08:12 +0000163 if (PredefLen == PCHPredefLen &&
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000164 strncmp(Predef, PCHPredef, PCHPredefLen) == 0)
165 return false;
166
167 SourceManager &SourceMgr = PP.getSourceManager();
Mike Stump11289f42009-09-09 15:08:12 +0000168
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000169 // The predefines buffers are different. Determine what the
170 // differences are, and whether they require us to reject the PCH
171 // file.
172 std::vector<std::string> CmdLineLines = splitLines(Predef, PredefLen);
173 std::vector<std::string> PCHLines = splitLines(PCHPredef, PCHPredefLen);
174
Mike Stump11289f42009-09-09 15:08:12 +0000175 // Sort both sets of predefined buffer lines, since
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000176 std::sort(CmdLineLines.begin(), CmdLineLines.end());
177 std::sort(PCHLines.begin(), PCHLines.end());
178
179 // Determine which predefines that where used to build the PCH file
180 // are missing from the command line.
181 std::vector<std::string> MissingPredefines;
182 std::set_difference(PCHLines.begin(), PCHLines.end(),
183 CmdLineLines.begin(), CmdLineLines.end(),
184 std::back_inserter(MissingPredefines));
185
186 bool MissingDefines = false;
187 bool ConflictingDefines = false;
188 for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
189 const std::string &Missing = MissingPredefines[I];
Daniel Dunbar045c92f2009-11-11 00:52:00 +0000190 if (!llvm::StringRef(Missing).startswith("#define ")) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000191 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
192 return true;
193 }
Mike Stump11289f42009-09-09 15:08:12 +0000194
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000195 // This is a macro definition. Determine the name of the macro
196 // we're defining.
197 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump11289f42009-09-09 15:08:12 +0000198 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000199 = Missing.find_first_of("( \n\r", StartOfMacroName);
200 assert(EndOfMacroName != std::string::npos &&
201 "Couldn't find the end of the macro name");
202 std::string MacroName = Missing.substr(StartOfMacroName,
203 EndOfMacroName - StartOfMacroName);
204
205 // Determine whether this macro was given a different definition
206 // on the command line.
207 std::string MacroDefStart = "#define " + MacroName;
208 std::string::size_type MacroDefLen = MacroDefStart.size();
209 std::vector<std::string>::iterator ConflictPos
210 = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
211 MacroDefStart);
212 for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
Daniel Dunbar045c92f2009-11-11 00:52:00 +0000213 if (!llvm::StringRef(*ConflictPos).startswith(MacroDefStart)) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000214 // Different macro; we're done.
215 ConflictPos = CmdLineLines.end();
Mike Stump11289f42009-09-09 15:08:12 +0000216 break;
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000217 }
Mike Stump11289f42009-09-09 15:08:12 +0000218
219 assert(ConflictPos->size() > MacroDefLen &&
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000220 "Invalid #define in predefines buffer?");
Mike Stump11289f42009-09-09 15:08:12 +0000221 if ((*ConflictPos)[MacroDefLen] != ' ' &&
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000222 (*ConflictPos)[MacroDefLen] != '(')
223 continue; // Longer macro name; keep trying.
Mike Stump11289f42009-09-09 15:08:12 +0000224
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000225 // We found a conflicting macro definition.
226 break;
227 }
Mike Stump11289f42009-09-09 15:08:12 +0000228
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000229 if (ConflictPos != CmdLineLines.end()) {
230 Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
231 << MacroName;
232
233 // Show the definition of this macro within the PCH file.
234 const char *MissingDef = strstr(PCHPredef, Missing.c_str());
235 unsigned Offset = MissingDef - PCHPredef;
236 SourceLocation PCHMissingLoc
237 = SourceMgr.getLocForStartOfFile(PCHBufferID)
238 .getFileLocWithOffset(Offset);
239 Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as)
240 << MacroName;
241
242 ConflictingDefines = true;
243 continue;
244 }
Mike Stump11289f42009-09-09 15:08:12 +0000245
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000246 // If the macro doesn't conflict, then we'll just pick up the
247 // macro definition from the PCH file. Warn the user that they
248 // made a mistake.
249 if (ConflictingDefines)
250 continue; // Don't complain if there are already conflicting defs
Mike Stump11289f42009-09-09 15:08:12 +0000251
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000252 if (!MissingDefines) {
253 Reader.Diag(diag::warn_cmdline_missing_macro_defs);
254 MissingDefines = true;
255 }
256
257 // Show the definition of this macro within the PCH file.
258 const char *MissingDef = strstr(PCHPredef, Missing.c_str());
259 unsigned Offset = MissingDef - PCHPredef;
260 SourceLocation PCHMissingLoc
261 = SourceMgr.getLocForStartOfFile(PCHBufferID)
262 .getFileLocWithOffset(Offset);
263 Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
264 }
Mike Stump11289f42009-09-09 15:08:12 +0000265
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000266 if (ConflictingDefines)
267 return true;
Mike Stump11289f42009-09-09 15:08:12 +0000268
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000269 // Determine what predefines were introduced based on command-line
270 // parameters that were not present when building the PCH
271 // file. Extra #defines are okay, so long as the identifiers being
272 // defined were not used within the precompiled header.
273 std::vector<std::string> ExtraPredefines;
274 std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
275 PCHLines.begin(), PCHLines.end(),
Mike Stump11289f42009-09-09 15:08:12 +0000276 std::back_inserter(ExtraPredefines));
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000277 for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
278 const std::string &Extra = ExtraPredefines[I];
Daniel Dunbar045c92f2009-11-11 00:52:00 +0000279 if (!llvm::StringRef(Extra).startswith("#define ")) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000280 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
281 return true;
282 }
283
284 // This is an extra macro definition. Determine the name of the
285 // macro we're defining.
286 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump11289f42009-09-09 15:08:12 +0000287 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000288 = Extra.find_first_of("( \n\r", StartOfMacroName);
289 assert(EndOfMacroName != std::string::npos &&
290 "Couldn't find the end of the macro name");
291 std::string MacroName = Extra.substr(StartOfMacroName,
292 EndOfMacroName - StartOfMacroName);
293
294 // Check whether this name was used somewhere in the PCH file. If
295 // so, defining it as a macro could change behavior, so we reject
296 // the PCH file.
297 if (IdentifierInfo *II = Reader.get(MacroName.c_str(),
298 MacroName.c_str() + MacroName.size())) {
Daniel Dunbar045c92f2009-11-11 00:52:00 +0000299 Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000300 return true;
301 }
302
303 // Add this definition to the suggested predefines buffer.
304 SuggestedPredefines += Extra;
305 SuggestedPredefines += '\n';
306 }
307
308 // If we get here, it's because the predefines buffer had compatible
309 // contents. Accept the PCH file.
310 return false;
311}
312
313void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
314 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
315}
316
317void PCHValidator::ReadCounter(unsigned Value) {
318 PP.setCounterValue(Value);
319}
320
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000321//===----------------------------------------------------------------------===//
Douglas Gregora868bbd2009-04-21 22:25:48 +0000322// PCH reader implementation
323//===----------------------------------------------------------------------===//
324
Mike Stump11289f42009-09-09 15:08:12 +0000325PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
326 const char *isysroot)
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000327 : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
328 FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
Douglas Gregord2eb58a2009-10-16 18:18:30 +0000329 SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000330 IdentifierTableData(0), IdentifierLookupTable(0),
331 IdentifierOffsets(0),
332 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
333 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000334 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump11289f42009-09-09 15:08:12 +0000335 NumStatHits(0), NumStatMisses(0),
336 NumSLocEntriesRead(0), NumStatementsRead(0),
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000337 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000338 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump11289f42009-09-09 15:08:12 +0000339 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000340 RelocatablePCH = false;
341}
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000342
343PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
Mike Stump11289f42009-09-09 15:08:12 +0000344 Diagnostic &Diags, const char *isysroot)
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000345 : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
Douglas Gregord2eb58a2009-10-16 18:18:30 +0000346 SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
Chris Lattner92ba5ff2009-04-27 05:14:47 +0000347 IdentifierTableData(0), IdentifierLookupTable(0),
348 IdentifierOffsets(0),
349 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
350 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000351 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump11289f42009-09-09 15:08:12 +0000352 NumStatHits(0), NumStatMisses(0),
353 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor258ae542009-04-27 06:38:32 +0000354 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregor1342e842009-07-06 18:54:52 +0000355 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump11289f42009-09-09 15:08:12 +0000356 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000357 RelocatablePCH = false;
358}
Chris Lattner92ba5ff2009-04-27 05:14:47 +0000359
360PCHReader::~PCHReader() {}
361
Chris Lattner1de76db2009-04-27 05:58:23 +0000362Expr *PCHReader::ReadDeclExpr() {
363 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
364}
365
366Expr *PCHReader::ReadTypeExpr() {
Douglas Gregor12bfa382009-10-17 00:13:19 +0000367 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
Chris Lattner92ba5ff2009-04-27 05:14:47 +0000368}
369
370
Douglas Gregora868bbd2009-04-21 22:25:48 +0000371namespace {
Douglas Gregorc78d3462009-04-24 21:10:55 +0000372class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
373 PCHReader &Reader;
374
375public:
376 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
377
378 typedef Selector external_key_type;
379 typedef external_key_type internal_key_type;
380
381 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
Mike Stump11289f42009-09-09 15:08:12 +0000382
Douglas Gregorc78d3462009-04-24 21:10:55 +0000383 static bool EqualKey(const internal_key_type& a,
384 const internal_key_type& b) {
385 return a == b;
386 }
Mike Stump11289f42009-09-09 15:08:12 +0000387
Douglas Gregorc78d3462009-04-24 21:10:55 +0000388 static unsigned ComputeHash(Selector Sel) {
389 unsigned N = Sel.getNumArgs();
390 if (N == 0)
391 ++N;
392 unsigned R = 5381;
393 for (unsigned I = 0; I != N; ++I)
394 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
Daniel Dunbarf8502d52009-10-17 23:52:28 +0000395 R = llvm::HashString(II->getName(), R);
Douglas Gregorc78d3462009-04-24 21:10:55 +0000396 return R;
397 }
Mike Stump11289f42009-09-09 15:08:12 +0000398
Douglas Gregorc78d3462009-04-24 21:10:55 +0000399 // This hopefully will just get inlined and removed by the optimizer.
400 static const internal_key_type&
401 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump11289f42009-09-09 15:08:12 +0000402
Douglas Gregorc78d3462009-04-24 21:10:55 +0000403 static std::pair<unsigned, unsigned>
404 ReadKeyDataLength(const unsigned char*& d) {
405 using namespace clang::io;
406 unsigned KeyLen = ReadUnalignedLE16(d);
407 unsigned DataLen = ReadUnalignedLE16(d);
408 return std::make_pair(KeyLen, DataLen);
409 }
Mike Stump11289f42009-09-09 15:08:12 +0000410
Douglas Gregor95c13f52009-04-25 17:48:32 +0000411 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorc78d3462009-04-24 21:10:55 +0000412 using namespace clang::io;
Chris Lattner8575daa2009-04-27 21:45:14 +0000413 SelectorTable &SelTable = Reader.getContext()->Selectors;
Douglas Gregorc78d3462009-04-24 21:10:55 +0000414 unsigned N = ReadUnalignedLE16(d);
Mike Stump11289f42009-09-09 15:08:12 +0000415 IdentifierInfo *FirstII
Douglas Gregorc78d3462009-04-24 21:10:55 +0000416 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
417 if (N == 0)
418 return SelTable.getNullarySelector(FirstII);
419 else if (N == 1)
420 return SelTable.getUnarySelector(FirstII);
421
422 llvm::SmallVector<IdentifierInfo *, 16> Args;
423 Args.push_back(FirstII);
424 for (unsigned I = 1; I != N; ++I)
425 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
426
Douglas Gregor038c3382009-05-22 22:45:36 +0000427 return SelTable.getSelector(N, Args.data());
Douglas Gregorc78d3462009-04-24 21:10:55 +0000428 }
Mike Stump11289f42009-09-09 15:08:12 +0000429
Douglas Gregorc78d3462009-04-24 21:10:55 +0000430 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
431 using namespace clang::io;
432 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
433 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
434
435 data_type Result;
436
437 // Load instance methods
438 ObjCMethodList *Prev = 0;
439 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
Mike Stump11289f42009-09-09 15:08:12 +0000440 ObjCMethodDecl *Method
Douglas Gregorc78d3462009-04-24 21:10:55 +0000441 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
442 if (!Result.first.Method) {
443 // This is the first method, which is the easy case.
444 Result.first.Method = Method;
445 Prev = &Result.first;
446 continue;
447 }
448
449 Prev->Next = new ObjCMethodList(Method, 0);
450 Prev = Prev->Next;
451 }
452
453 // Load factory methods
454 Prev = 0;
455 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
Mike Stump11289f42009-09-09 15:08:12 +0000456 ObjCMethodDecl *Method
Douglas Gregorc78d3462009-04-24 21:10:55 +0000457 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
458 if (!Result.second.Method) {
459 // This is the first method, which is the easy case.
460 Result.second.Method = Method;
461 Prev = &Result.second;
462 continue;
463 }
464
465 Prev->Next = new ObjCMethodList(Method, 0);
466 Prev = Prev->Next;
467 }
468
469 return Result;
470 }
471};
Mike Stump11289f42009-09-09 15:08:12 +0000472
473} // end anonymous namespace
Douglas Gregorc78d3462009-04-24 21:10:55 +0000474
475/// \brief The on-disk hash table used for the global method pool.
Mike Stump11289f42009-09-09 15:08:12 +0000476typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
Douglas Gregorc78d3462009-04-24 21:10:55 +0000477 PCHMethodPoolLookupTable;
478
479namespace {
Douglas Gregora868bbd2009-04-21 22:25:48 +0000480class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
481 PCHReader &Reader;
482
483 // If we know the IdentifierInfo in advance, it is here and we will
484 // not build a new one. Used when deserializing information about an
485 // identifier that was constructed before the PCH file was read.
486 IdentifierInfo *KnownII;
487
488public:
489 typedef IdentifierInfo * data_type;
490
491 typedef const std::pair<const char*, unsigned> external_key_type;
492
493 typedef external_key_type internal_key_type;
494
Mike Stump11289f42009-09-09 15:08:12 +0000495 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
Douglas Gregora868bbd2009-04-21 22:25:48 +0000496 : Reader(Reader), KnownII(II) { }
Mike Stump11289f42009-09-09 15:08:12 +0000497
Douglas Gregora868bbd2009-04-21 22:25:48 +0000498 static bool EqualKey(const internal_key_type& a,
499 const internal_key_type& b) {
500 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
501 : false;
502 }
Mike Stump11289f42009-09-09 15:08:12 +0000503
Douglas Gregora868bbd2009-04-21 22:25:48 +0000504 static unsigned ComputeHash(const internal_key_type& a) {
Daniel Dunbarf8502d52009-10-17 23:52:28 +0000505 return llvm::HashString(llvm::StringRef(a.first, a.second));
Douglas Gregora868bbd2009-04-21 22:25:48 +0000506 }
Mike Stump11289f42009-09-09 15:08:12 +0000507
Douglas Gregora868bbd2009-04-21 22:25:48 +0000508 // This hopefully will just get inlined and removed by the optimizer.
509 static const internal_key_type&
510 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump11289f42009-09-09 15:08:12 +0000511
Douglas Gregora868bbd2009-04-21 22:25:48 +0000512 static std::pair<unsigned, unsigned>
513 ReadKeyDataLength(const unsigned char*& d) {
514 using namespace clang::io;
Douglas Gregor6b7bf5a2009-04-25 20:26:24 +0000515 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregor5287b4e2009-04-25 21:04:17 +0000516 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregora868bbd2009-04-21 22:25:48 +0000517 return std::make_pair(KeyLen, DataLen);
518 }
Mike Stump11289f42009-09-09 15:08:12 +0000519
Douglas Gregora868bbd2009-04-21 22:25:48 +0000520 static std::pair<const char*, unsigned>
521 ReadKey(const unsigned char* d, unsigned n) {
522 assert(n >= 2 && d[n-1] == '\0');
523 return std::make_pair((const char*) d, n-1);
524 }
Mike Stump11289f42009-09-09 15:08:12 +0000525
526 IdentifierInfo *ReadData(const internal_key_type& k,
Douglas Gregora868bbd2009-04-21 22:25:48 +0000527 const unsigned char* d,
528 unsigned DataLen) {
529 using namespace clang::io;
Douglas Gregor1d583f22009-04-28 21:18:29 +0000530 pch::IdentID ID = ReadUnalignedLE32(d);
531 bool IsInteresting = ID & 0x01;
532
533 // Wipe out the "is interesting" bit.
534 ID = ID >> 1;
535
536 if (!IsInteresting) {
537 // For unintersting identifiers, just build the IdentifierInfo
538 // and associate it with the persistent ID.
539 IdentifierInfo *II = KnownII;
540 if (!II)
541 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
542 k.first, k.first + k.second);
543 Reader.SetIdentifierInfo(ID, II);
544 return II;
545 }
546
Douglas Gregorb9256522009-04-28 21:32:13 +0000547 unsigned Bits = ReadUnalignedLE16(d);
Douglas Gregor4621c6a2009-04-22 18:49:13 +0000548 bool CPlusPlusOperatorKeyword = Bits & 0x01;
549 Bits >>= 1;
550 bool Poisoned = Bits & 0x01;
551 Bits >>= 1;
552 bool ExtensionToken = Bits & 0x01;
553 Bits >>= 1;
554 bool hasMacroDefinition = Bits & 0x01;
555 Bits >>= 1;
556 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
557 Bits >>= 10;
Mike Stump11289f42009-09-09 15:08:12 +0000558
Douglas Gregor4621c6a2009-04-22 18:49:13 +0000559 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregorb9256522009-04-28 21:32:13 +0000560 DataLen -= 6;
Douglas Gregora868bbd2009-04-21 22:25:48 +0000561
562 // Build the IdentifierInfo itself and link the identifier ID with
563 // the new IdentifierInfo.
564 IdentifierInfo *II = KnownII;
565 if (!II)
Douglas Gregor6b7bf5a2009-04-25 20:26:24 +0000566 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
567 k.first, k.first + k.second);
Douglas Gregora868bbd2009-04-21 22:25:48 +0000568 Reader.SetIdentifierInfo(ID, II);
569
Douglas Gregor4621c6a2009-04-22 18:49:13 +0000570 // Set or check the various bits in the IdentifierInfo structure.
571 // FIXME: Load token IDs lazily, too?
Douglas Gregor4621c6a2009-04-22 18:49:13 +0000572 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
Mike Stump11289f42009-09-09 15:08:12 +0000573 assert(II->isExtensionToken() == ExtensionToken &&
Douglas Gregor4621c6a2009-04-22 18:49:13 +0000574 "Incorrect extension token flag");
575 (void)ExtensionToken;
576 II->setIsPoisoned(Poisoned);
577 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
578 "Incorrect C++ operator keyword flag");
579 (void)CPlusPlusOperatorKeyword;
580
Douglas Gregorc3366a52009-04-21 23:56:24 +0000581 // If this identifier is a macro, deserialize the macro
582 // definition.
583 if (hasMacroDefinition) {
Douglas Gregorb9256522009-04-28 21:32:13 +0000584 uint32_t Offset = ReadUnalignedLE32(d);
Douglas Gregorc3366a52009-04-21 23:56:24 +0000585 Reader.ReadMacroRecord(Offset);
Douglas Gregorb9256522009-04-28 21:32:13 +0000586 DataLen -= 4;
Douglas Gregorc3366a52009-04-21 23:56:24 +0000587 }
Douglas Gregora868bbd2009-04-21 22:25:48 +0000588
589 // Read all of the declarations visible at global scope with this
590 // name.
Chris Lattner1d728882009-04-27 22:17:41 +0000591 if (Reader.getContext() == 0) return II;
Douglas Gregor1342e842009-07-06 18:54:52 +0000592 if (DataLen > 0) {
593 llvm::SmallVector<uint32_t, 4> DeclIDs;
594 for (; DataLen > 0; DataLen -= 4)
595 DeclIDs.push_back(ReadUnalignedLE32(d));
596 Reader.SetGloballyVisibleDecls(II, DeclIDs);
Douglas Gregora868bbd2009-04-21 22:25:48 +0000597 }
Mike Stump11289f42009-09-09 15:08:12 +0000598
Douglas Gregora868bbd2009-04-21 22:25:48 +0000599 return II;
600 }
601};
Mike Stump11289f42009-09-09 15:08:12 +0000602
603} // end anonymous namespace
Douglas Gregora868bbd2009-04-21 22:25:48 +0000604
605/// \brief The on-disk hash table used to contain information about
606/// all of the identifiers in the program.
Mike Stump11289f42009-09-09 15:08:12 +0000607typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
Douglas Gregora868bbd2009-04-21 22:25:48 +0000608 PCHIdentifierLookupTable;
609
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000610bool PCHReader::Error(const char *Msg) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000611 unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
612 Diag(DiagID);
Douglas Gregoref84c4b2009-04-09 22:27:44 +0000613 return true;
614}
615
Douglas Gregor92863e42009-04-10 23:10:45 +0000616/// \brief Check the contents of the predefines buffer against the
617/// contents of the predefines buffer used to build the PCH file.
618///
619/// The contents of the two predefines buffers should be the same. If
620/// not, then some command-line option changed the preprocessor state
621/// and we must reject the PCH file.
622///
623/// \param PCHPredef The start of the predefines buffer in the PCH
624/// file.
625///
626/// \param PCHPredefLen The length of the predefines buffer in the PCH
627/// file.
628///
629/// \param PCHBufferID The FileID for the PCH predefines buffer.
630///
631/// \returns true if there was a mismatch (in which case the PCH file
632/// should be ignored), or false otherwise.
Mike Stump11289f42009-09-09 15:08:12 +0000633bool PCHReader::CheckPredefinesBuffer(const char *PCHPredef,
Douglas Gregor92863e42009-04-10 23:10:45 +0000634 unsigned PCHPredefLen,
635 FileID PCHBufferID) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000636 if (Listener)
637 return Listener->ReadPredefinesBuffer(PCHPredef, PCHPredefLen, PCHBufferID,
638 SuggestedPredefines);
Douglas Gregorc379c072009-04-28 18:58:38 +0000639 return false;
Douglas Gregor92863e42009-04-10 23:10:45 +0000640}
641
Douglas Gregorc5046832009-04-27 18:38:38 +0000642//===----------------------------------------------------------------------===//
643// Source Manager Deserialization
644//===----------------------------------------------------------------------===//
645
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000646/// \brief Read the line table in the source manager block.
647/// \returns true if ther was an error.
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000648bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000649 unsigned Idx = 0;
650 LineTableInfo &LineTable = SourceMgr.getLineTable();
651
652 // Parse the file names
Douglas Gregora8854652009-04-13 17:12:42 +0000653 std::map<int, int> FileIDs;
654 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000655 // Extract the file name
656 unsigned FilenameLen = Record[Idx++];
657 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
658 Idx += FilenameLen;
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000659 MaybeAddSystemRootToFilename(Filename);
Mike Stump11289f42009-09-09 15:08:12 +0000660 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
Douglas Gregora8854652009-04-13 17:12:42 +0000661 Filename.size());
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000662 }
663
664 // Parse the line entries
665 std::vector<LineEntry> Entries;
666 while (Idx < Record.size()) {
Douglas Gregora8854652009-04-13 17:12:42 +0000667 int FID = FileIDs[Record[Idx++]];
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000668
669 // Extract the line entries
670 unsigned NumEntries = Record[Idx++];
671 Entries.clear();
672 Entries.reserve(NumEntries);
673 for (unsigned I = 0; I != NumEntries; ++I) {
674 unsigned FileOffset = Record[Idx++];
675 unsigned LineNo = Record[Idx++];
676 int FilenameID = Record[Idx++];
Mike Stump11289f42009-09-09 15:08:12 +0000677 SrcMgr::CharacteristicKind FileKind
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000678 = (SrcMgr::CharacteristicKind)Record[Idx++];
679 unsigned IncludeOffset = Record[Idx++];
680 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
681 FileKind, IncludeOffset));
682 }
683 LineTable.AddEntry(FID, Entries);
684 }
685
686 return false;
687}
688
Douglas Gregorc5046832009-04-27 18:38:38 +0000689namespace {
690
691class VISIBILITY_HIDDEN PCHStatData {
692public:
693 const bool hasStat;
694 const ino_t ino;
695 const dev_t dev;
696 const mode_t mode;
697 const time_t mtime;
698 const off_t size;
Mike Stump11289f42009-09-09 15:08:12 +0000699
Douglas Gregorc5046832009-04-27 18:38:38 +0000700 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
Mike Stump11289f42009-09-09 15:08:12 +0000701 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
702
Douglas Gregorc5046832009-04-27 18:38:38 +0000703 PCHStatData()
704 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
705};
706
707class VISIBILITY_HIDDEN PCHStatLookupTrait {
708 public:
709 typedef const char *external_key_type;
710 typedef const char *internal_key_type;
711
712 typedef PCHStatData data_type;
713
714 static unsigned ComputeHash(const char *path) {
Daniel Dunbarf8502d52009-10-17 23:52:28 +0000715 return llvm::HashString(path);
Douglas Gregorc5046832009-04-27 18:38:38 +0000716 }
717
718 static internal_key_type GetInternalKey(const char *path) { return path; }
719
720 static bool EqualKey(internal_key_type a, internal_key_type b) {
721 return strcmp(a, b) == 0;
722 }
723
724 static std::pair<unsigned, unsigned>
725 ReadKeyDataLength(const unsigned char*& d) {
726 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
727 unsigned DataLen = (unsigned) *d++;
728 return std::make_pair(KeyLen + 1, DataLen);
729 }
730
731 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
732 return (const char *)d;
733 }
734
735 static data_type ReadData(const internal_key_type, const unsigned char *d,
736 unsigned /*DataLen*/) {
737 using namespace clang::io;
738
739 if (*d++ == 1)
740 return data_type();
741
742 ino_t ino = (ino_t) ReadUnalignedLE32(d);
743 dev_t dev = (dev_t) ReadUnalignedLE32(d);
744 mode_t mode = (mode_t) ReadUnalignedLE16(d);
Mike Stump11289f42009-09-09 15:08:12 +0000745 time_t mtime = (time_t) ReadUnalignedLE64(d);
Douglas Gregorc5046832009-04-27 18:38:38 +0000746 off_t size = (off_t) ReadUnalignedLE64(d);
747 return data_type(ino, dev, mode, mtime, size);
748 }
749};
750
751/// \brief stat() cache for precompiled headers.
752///
753/// This cache is very similar to the stat cache used by pretokenized
754/// headers.
755class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
756 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
757 CacheTy *Cache;
758
759 unsigned &NumStatHits, &NumStatMisses;
Mike Stump11289f42009-09-09 15:08:12 +0000760public:
Douglas Gregorc5046832009-04-27 18:38:38 +0000761 PCHStatCache(const unsigned char *Buckets,
762 const unsigned char *Base,
763 unsigned &NumStatHits,
Mike Stump11289f42009-09-09 15:08:12 +0000764 unsigned &NumStatMisses)
Douglas Gregorc5046832009-04-27 18:38:38 +0000765 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
766 Cache = CacheTy::Create(Buckets, Base);
767 }
768
769 ~PCHStatCache() { delete Cache; }
Mike Stump11289f42009-09-09 15:08:12 +0000770
Douglas Gregorc5046832009-04-27 18:38:38 +0000771 int stat(const char *path, struct stat *buf) {
772 // Do the lookup for the file's data in the PCH file.
773 CacheTy::iterator I = Cache->find(path);
774
775 // If we don't get a hit in the PCH file just forward to 'stat'.
776 if (I == Cache->end()) {
777 ++NumStatMisses;
Douglas Gregord2eb58a2009-10-16 18:18:30 +0000778 return StatSysCallCache::stat(path, buf);
Douglas Gregorc5046832009-04-27 18:38:38 +0000779 }
Mike Stump11289f42009-09-09 15:08:12 +0000780
Douglas Gregorc5046832009-04-27 18:38:38 +0000781 ++NumStatHits;
782 PCHStatData Data = *I;
Mike Stump11289f42009-09-09 15:08:12 +0000783
Douglas Gregorc5046832009-04-27 18:38:38 +0000784 if (!Data.hasStat)
785 return 1;
786
787 buf->st_ino = Data.ino;
788 buf->st_dev = Data.dev;
789 buf->st_mtime = Data.mtime;
790 buf->st_mode = Data.mode;
791 buf->st_size = Data.size;
792 return 0;
793 }
794};
795} // end anonymous namespace
796
797
Douglas Gregora7f71a92009-04-10 03:52:48 +0000798/// \brief Read the source manager block
Douglas Gregor92863e42009-04-10 23:10:45 +0000799PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregora7f71a92009-04-10 03:52:48 +0000800 using namespace SrcMgr;
Douglas Gregor258ae542009-04-27 06:38:32 +0000801
802 // Set the source-location entry cursor to the current position in
803 // the stream. This cursor will be used to read the contents of the
804 // source manager block initially, and then lazily read
805 // source-location entries as needed.
806 SLocEntryCursor = Stream;
807
808 // The stream itself is going to skip over the source manager block.
809 if (Stream.SkipBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000810 Error("malformed block record in PCH file");
Douglas Gregor258ae542009-04-27 06:38:32 +0000811 return Failure;
812 }
813
814 // Enter the source manager block.
815 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000816 Error("malformed source manager block record in PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +0000817 return Failure;
818 }
Douglas Gregora7f71a92009-04-10 03:52:48 +0000819
Douglas Gregora7f71a92009-04-10 03:52:48 +0000820 RecordData Record;
821 while (true) {
Douglas Gregor258ae542009-04-27 06:38:32 +0000822 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregora7f71a92009-04-10 03:52:48 +0000823 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor258ae542009-04-27 06:38:32 +0000824 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000825 Error("error at end of Source Manager block in PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +0000826 return Failure;
827 }
Douglas Gregor92863e42009-04-10 23:10:45 +0000828 return Success;
Douglas Gregora7f71a92009-04-10 03:52:48 +0000829 }
Mike Stump11289f42009-09-09 15:08:12 +0000830
Douglas Gregora7f71a92009-04-10 03:52:48 +0000831 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
832 // No known subblocks, always skip them.
Douglas Gregor258ae542009-04-27 06:38:32 +0000833 SLocEntryCursor.ReadSubBlockID();
834 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000835 Error("malformed block record in PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +0000836 return Failure;
837 }
Douglas Gregora7f71a92009-04-10 03:52:48 +0000838 continue;
839 }
Mike Stump11289f42009-09-09 15:08:12 +0000840
Douglas Gregora7f71a92009-04-10 03:52:48 +0000841 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor258ae542009-04-27 06:38:32 +0000842 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregora7f71a92009-04-10 03:52:48 +0000843 continue;
844 }
Mike Stump11289f42009-09-09 15:08:12 +0000845
Douglas Gregora7f71a92009-04-10 03:52:48 +0000846 // Read a record.
847 const char *BlobStart;
848 unsigned BlobLen;
849 Record.clear();
Douglas Gregor258ae542009-04-27 06:38:32 +0000850 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregora7f71a92009-04-10 03:52:48 +0000851 default: // Default behavior: ignore.
852 break;
853
Chris Lattner184e65d2009-04-14 23:22:57 +0000854 case pch::SM_LINE_TABLE:
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000855 if (ParseLineTable(Record))
Douglas Gregor4c7626e2009-04-13 16:31:14 +0000856 return Failure;
Chris Lattner184e65d2009-04-14 23:22:57 +0000857 break;
Douglas Gregoreda6a892009-04-26 00:07:37 +0000858
859 case pch::SM_HEADER_FILE_INFO: {
860 HeaderFileInfo HFI;
861 HFI.isImport = Record[0];
862 HFI.DirInfo = Record[1];
863 HFI.NumIncludes = Record[2];
864 HFI.ControllingMacroID = Record[3];
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000865 if (Listener)
866 Listener->ReadHeaderFileInfo(HFI);
Douglas Gregoreda6a892009-04-26 00:07:37 +0000867 break;
868 }
Douglas Gregor258ae542009-04-27 06:38:32 +0000869
870 case pch::SM_SLOC_FILE_ENTRY:
871 case pch::SM_SLOC_BUFFER_ENTRY:
872 case pch::SM_SLOC_INSTANTIATION_ENTRY:
873 // Once we hit one of the source location entries, we're done.
874 return Success;
Douglas Gregora7f71a92009-04-10 03:52:48 +0000875 }
876 }
877}
878
Douglas Gregor258ae542009-04-27 06:38:32 +0000879/// \brief Read in the source location entry with the given ID.
880PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
881 if (ID == 0)
882 return Success;
883
884 if (ID > TotalNumSLocEntries) {
885 Error("source location entry ID out-of-range for PCH file");
886 return Failure;
887 }
888
889 ++NumSLocEntriesRead;
890 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
891 unsigned Code = SLocEntryCursor.ReadCode();
892 if (Code == llvm::bitc::END_BLOCK ||
893 Code == llvm::bitc::ENTER_SUBBLOCK ||
894 Code == llvm::bitc::DEFINE_ABBREV) {
895 Error("incorrectly-formatted source location entry in PCH file");
896 return Failure;
897 }
898
Douglas Gregor258ae542009-04-27 06:38:32 +0000899 RecordData Record;
900 const char *BlobStart;
901 unsigned BlobLen;
902 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
903 default:
904 Error("incorrectly-formatted source location entry in PCH file");
905 return Failure;
906
907 case pch::SM_SLOC_FILE_ENTRY: {
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000908 std::string Filename(BlobStart, BlobStart + BlobLen);
909 MaybeAddSystemRootToFilename(Filename);
910 const FileEntry *File = FileMgr.getFile(Filename);
Chris Lattnerd20dc872009-06-15 04:35:16 +0000911 if (File == 0) {
912 std::string ErrorStr = "could not find file '";
Douglas Gregor0086a5a2009-07-07 00:12:59 +0000913 ErrorStr += Filename;
Chris Lattnerd20dc872009-06-15 04:35:16 +0000914 ErrorStr += "' referenced by PCH file";
915 Error(ErrorStr.c_str());
916 return Failure;
917 }
Mike Stump11289f42009-09-09 15:08:12 +0000918
Douglas Gregor258ae542009-04-27 06:38:32 +0000919 FileID FID = SourceMgr.createFileID(File,
920 SourceLocation::getFromRawEncoding(Record[1]),
921 (SrcMgr::CharacteristicKind)Record[2],
922 ID, Record[0]);
923 if (Record[3])
924 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
925 .setHasLineDirectives();
926
927 break;
928 }
929
930 case pch::SM_SLOC_BUFFER_ENTRY: {
931 const char *Name = BlobStart;
932 unsigned Offset = Record[0];
933 unsigned Code = SLocEntryCursor.ReadCode();
934 Record.clear();
Mike Stump11289f42009-09-09 15:08:12 +0000935 unsigned RecCode
Douglas Gregor258ae542009-04-27 06:38:32 +0000936 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
937 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
938 (void)RecCode;
939 llvm::MemoryBuffer *Buffer
Mike Stump11289f42009-09-09 15:08:12 +0000940 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
Douglas Gregor258ae542009-04-27 06:38:32 +0000941 BlobStart + BlobLen - 1,
942 Name);
943 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
Mike Stump11289f42009-09-09 15:08:12 +0000944
Douglas Gregore6648fb2009-04-28 20:33:11 +0000945 if (strcmp(Name, "<built-in>") == 0) {
946 PCHPredefinesBufferID = BufferID;
947 PCHPredefines = BlobStart;
948 PCHPredefinesLen = BlobLen - 1;
949 }
Douglas Gregor258ae542009-04-27 06:38:32 +0000950
951 break;
952 }
953
954 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
Mike Stump11289f42009-09-09 15:08:12 +0000955 SourceLocation SpellingLoc
Douglas Gregor258ae542009-04-27 06:38:32 +0000956 = SourceLocation::getFromRawEncoding(Record[1]);
957 SourceMgr.createInstantiationLoc(SpellingLoc,
958 SourceLocation::getFromRawEncoding(Record[2]),
959 SourceLocation::getFromRawEncoding(Record[3]),
960 Record[4],
961 ID,
962 Record[0]);
963 break;
Mike Stump11289f42009-09-09 15:08:12 +0000964 }
Douglas Gregor258ae542009-04-27 06:38:32 +0000965 }
966
967 return Success;
968}
969
Chris Lattnere78a6be2009-04-27 01:05:14 +0000970/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
971/// specified cursor. Read the abbreviations that are at the top of the block
972/// and then leave the cursor pointing into the block.
973bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
974 unsigned BlockID) {
975 if (Cursor.EnterSubBlock(BlockID)) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +0000976 Error("malformed block record in PCH file");
Chris Lattnere78a6be2009-04-27 01:05:14 +0000977 return Failure;
978 }
Mike Stump11289f42009-09-09 15:08:12 +0000979
Chris Lattnere78a6be2009-04-27 01:05:14 +0000980 while (true) {
981 unsigned Code = Cursor.ReadCode();
Mike Stump11289f42009-09-09 15:08:12 +0000982
Chris Lattnere78a6be2009-04-27 01:05:14 +0000983 // We expect all abbrevs to be at the start of the block.
984 if (Code != llvm::bitc::DEFINE_ABBREV)
985 return false;
986 Cursor.ReadAbbrevRecord();
987 }
988}
989
Douglas Gregorc3366a52009-04-21 23:56:24 +0000990void PCHReader::ReadMacroRecord(uint64_t Offset) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +0000991 assert(PP && "Forgot to set Preprocessor ?");
Mike Stump11289f42009-09-09 15:08:12 +0000992
Douglas Gregorc3366a52009-04-21 23:56:24 +0000993 // Keep track of where we are in the stream, then jump back there
994 // after reading this macro.
995 SavedStreamPosition SavedPosition(Stream);
996
997 Stream.JumpToBit(Offset);
998 RecordData Record;
999 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
1000 MacroInfo *Macro = 0;
Mike Stump11289f42009-09-09 15:08:12 +00001001
Douglas Gregorc3366a52009-04-21 23:56:24 +00001002 while (true) {
1003 unsigned Code = Stream.ReadCode();
1004 switch (Code) {
1005 case llvm::bitc::END_BLOCK:
1006 return;
1007
1008 case llvm::bitc::ENTER_SUBBLOCK:
1009 // No known subblocks, always skip them.
1010 Stream.ReadSubBlockID();
1011 if (Stream.SkipBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001012 Error("malformed block record in PCH file");
Douglas Gregorc3366a52009-04-21 23:56:24 +00001013 return;
1014 }
1015 continue;
Mike Stump11289f42009-09-09 15:08:12 +00001016
Douglas Gregorc3366a52009-04-21 23:56:24 +00001017 case llvm::bitc::DEFINE_ABBREV:
1018 Stream.ReadAbbrevRecord();
1019 continue;
1020 default: break;
1021 }
1022
1023 // Read a record.
1024 Record.clear();
1025 pch::PreprocessorRecordTypes RecType =
1026 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
1027 switch (RecType) {
Douglas Gregorc3366a52009-04-21 23:56:24 +00001028 case pch::PP_MACRO_OBJECT_LIKE:
1029 case pch::PP_MACRO_FUNCTION_LIKE: {
1030 // If we already have a macro, that means that we've hit the end
1031 // of the definition of the macro we were looking for. We're
1032 // done.
1033 if (Macro)
1034 return;
1035
1036 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
1037 if (II == 0) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001038 Error("macro must have a name in PCH file");
Douglas Gregorc3366a52009-04-21 23:56:24 +00001039 return;
1040 }
1041 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
1042 bool isUsed = Record[2];
Mike Stump11289f42009-09-09 15:08:12 +00001043
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001044 MacroInfo *MI = PP->AllocateMacroInfo(Loc);
Douglas Gregorc3366a52009-04-21 23:56:24 +00001045 MI->setIsUsed(isUsed);
Mike Stump11289f42009-09-09 15:08:12 +00001046
Douglas Gregorc3366a52009-04-21 23:56:24 +00001047 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
1048 // Decode function-like macro info.
1049 bool isC99VarArgs = Record[3];
1050 bool isGNUVarArgs = Record[4];
1051 MacroArgs.clear();
1052 unsigned NumArgs = Record[5];
1053 for (unsigned i = 0; i != NumArgs; ++i)
1054 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
1055
1056 // Install function-like macro info.
1057 MI->setIsFunctionLike();
1058 if (isC99VarArgs) MI->setIsC99Varargs();
1059 if (isGNUVarArgs) MI->setIsGNUVarargs();
Douglas Gregor038c3382009-05-22 22:45:36 +00001060 MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001061 PP->getPreprocessorAllocator());
Douglas Gregorc3366a52009-04-21 23:56:24 +00001062 }
1063
1064 // Finally, install the macro.
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001065 PP->setMacroInfo(II, MI);
Douglas Gregorc3366a52009-04-21 23:56:24 +00001066
1067 // Remember that we saw this macro last so that we add the tokens that
1068 // form its body to it.
1069 Macro = MI;
1070 ++NumMacrosRead;
1071 break;
1072 }
Mike Stump11289f42009-09-09 15:08:12 +00001073
Douglas Gregorc3366a52009-04-21 23:56:24 +00001074 case pch::PP_TOKEN: {
1075 // If we see a TOKEN before a PP_MACRO_*, then the file is
1076 // erroneous, just pretend we didn't see this.
1077 if (Macro == 0) break;
Mike Stump11289f42009-09-09 15:08:12 +00001078
Douglas Gregorc3366a52009-04-21 23:56:24 +00001079 Token Tok;
1080 Tok.startToken();
1081 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
1082 Tok.setLength(Record[1]);
1083 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
1084 Tok.setIdentifierInfo(II);
1085 Tok.setKind((tok::TokenKind)Record[3]);
1086 Tok.setFlag((Token::TokenFlags)Record[4]);
1087 Macro->AddTokenToBody(Tok);
1088 break;
1089 }
Steve Naroff3fa455a2009-04-24 20:03:17 +00001090 }
Douglas Gregorc3366a52009-04-21 23:56:24 +00001091 }
1092}
1093
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001094/// \brief If we are loading a relocatable PCH file, and the filename is
1095/// not an absolute path, add the system root to the beginning of the file
1096/// name.
1097void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
1098 // If this is not a relocatable PCH file, there's nothing to do.
1099 if (!RelocatablePCH)
1100 return;
Mike Stump11289f42009-09-09 15:08:12 +00001101
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001102 if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<')
1103 return;
1104
1105 std::string FIXME = Filename;
Mike Stump11289f42009-09-09 15:08:12 +00001106
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001107 if (isysroot == 0) {
1108 // If no system root was given, default to '/'
1109 Filename.insert(Filename.begin(), '/');
1110 return;
1111 }
Mike Stump11289f42009-09-09 15:08:12 +00001112
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001113 unsigned Length = strlen(isysroot);
1114 if (isysroot[Length - 1] != '/')
1115 Filename.insert(Filename.begin(), '/');
Mike Stump11289f42009-09-09 15:08:12 +00001116
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001117 Filename.insert(Filename.begin(), isysroot, isysroot + Length);
1118}
1119
Mike Stump11289f42009-09-09 15:08:12 +00001120PCHReader::PCHReadResult
Douglas Gregoreda6a892009-04-26 00:07:37 +00001121PCHReader::ReadPCHBlock() {
Douglas Gregor55abb232009-04-10 20:39:37 +00001122 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001123 Error("malformed block record in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001124 return Failure;
1125 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001126
1127 // Read all of the records and blocks for the PCH file.
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00001128 RecordData Record;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001129 while (!Stream.AtEndOfStream()) {
1130 unsigned Code = Stream.ReadCode();
1131 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor55abb232009-04-10 20:39:37 +00001132 if (Stream.ReadBlockEnd()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001133 Error("error at end of module block in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001134 return Failure;
1135 }
Chris Lattnerc523d8e2009-04-11 21:15:38 +00001136
Douglas Gregor55abb232009-04-10 20:39:37 +00001137 return Success;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001138 }
1139
1140 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1141 switch (Stream.ReadSubBlockID()) {
Douglas Gregor12bfa382009-10-17 00:13:19 +00001142 case pch::DECLTYPES_BLOCK_ID:
Chris Lattnere78a6be2009-04-27 01:05:14 +00001143 // We lazily load the decls block, but we want to set up the
1144 // DeclsCursor cursor to point into it. Clone our current bitcode
1145 // cursor to it, enter the block and read the abbrevs in that block.
1146 // With the main cursor, we just skip over it.
1147 DeclsCursor = Stream;
1148 if (Stream.SkipBlock() || // Skip with the main cursor.
1149 // Read the abbrevs.
Douglas Gregor12bfa382009-10-17 00:13:19 +00001150 ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001151 Error("malformed block record in PCH file");
Chris Lattnere78a6be2009-04-27 01:05:14 +00001152 return Failure;
1153 }
1154 break;
Mike Stump11289f42009-09-09 15:08:12 +00001155
Chris Lattnerc523d8e2009-04-11 21:15:38 +00001156 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattnerc523d8e2009-04-11 21:15:38 +00001157 if (Stream.SkipBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001158 Error("malformed block record in PCH file");
Chris Lattnerc523d8e2009-04-11 21:15:38 +00001159 return Failure;
1160 }
1161 break;
Steve Naroff2ddea052009-04-23 10:39:46 +00001162
Douglas Gregora7f71a92009-04-10 03:52:48 +00001163 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregor92863e42009-04-10 23:10:45 +00001164 switch (ReadSourceManagerBlock()) {
1165 case Success:
1166 break;
1167
1168 case Failure:
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001169 Error("malformed source manager block in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001170 return Failure;
Douglas Gregor92863e42009-04-10 23:10:45 +00001171
1172 case IgnorePCH:
1173 return IgnorePCH;
Douglas Gregor55abb232009-04-10 20:39:37 +00001174 }
Douglas Gregora7f71a92009-04-10 03:52:48 +00001175 break;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001176 }
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00001177 continue;
1178 }
1179
1180 if (Code == llvm::bitc::DEFINE_ABBREV) {
1181 Stream.ReadAbbrevRecord();
1182 continue;
1183 }
1184
1185 // Read and process a record.
1186 Record.clear();
Douglas Gregorbfbde532009-04-10 21:16:55 +00001187 const char *BlobStart = 0;
1188 unsigned BlobLen = 0;
Mike Stump11289f42009-09-09 15:08:12 +00001189 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
Douglas Gregorbfbde532009-04-10 21:16:55 +00001190 &BlobStart, &BlobLen)) {
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00001191 default: // Default behavior: ignore.
1192 break;
1193
1194 case pch::TYPE_OFFSET:
Douglas Gregor745ed142009-04-25 18:35:21 +00001195 if (!TypesLoaded.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001196 Error("duplicate TYPE_OFFSET record in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001197 return Failure;
1198 }
Chris Lattnereeb05692009-04-27 18:24:17 +00001199 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor745ed142009-04-25 18:35:21 +00001200 TypesLoaded.resize(Record[0]);
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00001201 break;
1202
1203 case pch::DECL_OFFSET:
Douglas Gregor745ed142009-04-25 18:35:21 +00001204 if (!DeclsLoaded.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001205 Error("duplicate DECL_OFFSET record in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001206 return Failure;
1207 }
Chris Lattnereeb05692009-04-27 18:24:17 +00001208 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor745ed142009-04-25 18:35:21 +00001209 DeclsLoaded.resize(Record[0]);
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00001210 break;
Douglas Gregor55abb232009-04-10 20:39:37 +00001211
1212 case pch::LANGUAGE_OPTIONS:
1213 if (ParseLanguageOptions(Record))
1214 return IgnorePCH;
1215 break;
Douglas Gregorbfbde532009-04-10 21:16:55 +00001216
Douglas Gregor7b71e632009-04-27 22:23:34 +00001217 case pch::METADATA: {
1218 if (Record[0] != pch::VERSION_MAJOR) {
1219 Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
1220 : diag::warn_pch_version_too_new);
1221 return IgnorePCH;
1222 }
1223
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001224 RelocatablePCH = Record[4];
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001225 if (Listener) {
1226 std::string TargetTriple(BlobStart, BlobLen);
1227 if (Listener->ReadTargetTriple(TargetTriple))
1228 return IgnorePCH;
Douglas Gregorbfbde532009-04-10 21:16:55 +00001229 }
1230 break;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001231 }
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00001232
1233 case pch::IDENTIFIER_TABLE:
Douglas Gregora868bbd2009-04-21 22:25:48 +00001234 IdentifierTableData = BlobStart;
Douglas Gregor0e149972009-04-25 19:10:14 +00001235 if (Record[0]) {
Mike Stump11289f42009-09-09 15:08:12 +00001236 IdentifierLookupTable
Douglas Gregor0e149972009-04-25 19:10:14 +00001237 = PCHIdentifierLookupTable::Create(
Douglas Gregora868bbd2009-04-21 22:25:48 +00001238 (const unsigned char *)IdentifierTableData + Record[0],
Mike Stump11289f42009-09-09 15:08:12 +00001239 (const unsigned char *)IdentifierTableData,
Douglas Gregora868bbd2009-04-21 22:25:48 +00001240 PCHIdentifierLookupTrait(*this));
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001241 if (PP)
1242 PP->getIdentifierTable().setExternalIdentifierLookup(this);
Douglas Gregor0e149972009-04-25 19:10:14 +00001243 }
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00001244 break;
1245
1246 case pch::IDENTIFIER_OFFSET:
Douglas Gregor0e149972009-04-25 19:10:14 +00001247 if (!IdentifiersLoaded.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001248 Error("duplicate IDENTIFIER_OFFSET record in PCH file");
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00001249 return Failure;
1250 }
Douglas Gregor0e149972009-04-25 19:10:14 +00001251 IdentifierOffsets = (const uint32_t *)BlobStart;
1252 IdentifiersLoaded.resize(Record[0]);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001253 if (PP)
1254 PP->getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00001255 break;
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00001256
1257 case pch::EXTERNAL_DEFINITIONS:
1258 if (!ExternalDefinitions.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001259 Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00001260 return Failure;
1261 }
1262 ExternalDefinitions.swap(Record);
1263 break;
Douglas Gregor08f01292009-04-17 22:13:46 +00001264
Douglas Gregor652d82a2009-04-18 05:55:16 +00001265 case pch::SPECIAL_TYPES:
1266 SpecialTypes.swap(Record);
1267 break;
1268
Douglas Gregor08f01292009-04-17 22:13:46 +00001269 case pch::STATISTICS:
1270 TotalNumStatements = Record[0];
Douglas Gregorc3366a52009-04-21 23:56:24 +00001271 TotalNumMacros = Record[1];
Douglas Gregora57c3ab2009-04-22 22:34:57 +00001272 TotalLexicalDeclContexts = Record[2];
1273 TotalVisibleDeclContexts = Record[3];
Douglas Gregor08f01292009-04-17 22:13:46 +00001274 break;
Douglas Gregor258ae542009-04-27 06:38:32 +00001275
Douglas Gregord4df8652009-04-22 22:02:47 +00001276 case pch::TENTATIVE_DEFINITIONS:
1277 if (!TentativeDefinitions.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001278 Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
Douglas Gregord4df8652009-04-22 22:02:47 +00001279 return Failure;
1280 }
1281 TentativeDefinitions.swap(Record);
1282 break;
Douglas Gregoracfc76c2009-04-22 22:18:58 +00001283
1284 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
1285 if (!LocallyScopedExternalDecls.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001286 Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
Douglas Gregoracfc76c2009-04-22 22:18:58 +00001287 return Failure;
1288 }
1289 LocallyScopedExternalDecls.swap(Record);
1290 break;
Douglas Gregorc78d3462009-04-24 21:10:55 +00001291
Douglas Gregor95c13f52009-04-25 17:48:32 +00001292 case pch::SELECTOR_OFFSETS:
1293 SelectorOffsets = (const uint32_t *)BlobStart;
1294 TotalNumSelectors = Record[0];
1295 SelectorsLoaded.resize(TotalNumSelectors);
1296 break;
1297
Douglas Gregorc78d3462009-04-24 21:10:55 +00001298 case pch::METHOD_POOL:
Douglas Gregor95c13f52009-04-25 17:48:32 +00001299 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1300 if (Record[0])
Mike Stump11289f42009-09-09 15:08:12 +00001301 MethodPoolLookupTable
Douglas Gregor95c13f52009-04-25 17:48:32 +00001302 = PCHMethodPoolLookupTable::Create(
1303 MethodPoolLookupTableData + Record[0],
Mike Stump11289f42009-09-09 15:08:12 +00001304 MethodPoolLookupTableData,
Douglas Gregorc78d3462009-04-24 21:10:55 +00001305 PCHMethodPoolLookupTrait(*this));
Douglas Gregor95c13f52009-04-25 17:48:32 +00001306 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorc78d3462009-04-24 21:10:55 +00001307 break;
Douglas Gregoreda6a892009-04-26 00:07:37 +00001308
1309 case pch::PP_COUNTER_VALUE:
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001310 if (!Record.empty() && Listener)
1311 Listener->ReadCounter(Record[0]);
Douglas Gregoreda6a892009-04-26 00:07:37 +00001312 break;
Douglas Gregor258ae542009-04-27 06:38:32 +00001313
1314 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner12d61d32009-04-27 19:01:47 +00001315 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor258ae542009-04-27 06:38:32 +00001316 TotalNumSLocEntries = Record[0];
Douglas Gregord54f3a12009-10-05 21:07:28 +00001317 SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
Douglas Gregor258ae542009-04-27 06:38:32 +00001318 break;
1319
1320 case pch::SOURCE_LOCATION_PRELOADS:
1321 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1322 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1323 if (Result != Success)
1324 return Result;
1325 }
1326 break;
Douglas Gregorc5046832009-04-27 18:38:38 +00001327
Douglas Gregord2eb58a2009-10-16 18:18:30 +00001328 case pch::STAT_CACHE: {
1329 PCHStatCache *MyStatCache =
1330 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1331 (const unsigned char *)BlobStart,
1332 NumStatHits, NumStatMisses);
1333 FileMgr.addStatCache(MyStatCache);
1334 StatCache = MyStatCache;
Douglas Gregorc5046832009-04-27 18:38:38 +00001335 break;
Douglas Gregord2eb58a2009-10-16 18:18:30 +00001336 }
1337
Douglas Gregor61cac2b2009-04-27 20:06:05 +00001338 case pch::EXT_VECTOR_DECLS:
1339 if (!ExtVectorDecls.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001340 Error("duplicate EXT_VECTOR_DECLS record in PCH file");
Douglas Gregor61cac2b2009-04-27 20:06:05 +00001341 return Failure;
1342 }
1343 ExtVectorDecls.swap(Record);
1344 break;
1345
Douglas Gregor45fe0362009-05-12 01:31:05 +00001346 case pch::ORIGINAL_FILE_NAME:
1347 OriginalFileName.assign(BlobStart, BlobLen);
Douglas Gregor0086a5a2009-07-07 00:12:59 +00001348 MaybeAddSystemRootToFilename(OriginalFileName);
Douglas Gregor45fe0362009-05-12 01:31:05 +00001349 break;
Mike Stump11289f42009-09-09 15:08:12 +00001350
Douglas Gregorc6d5edd2009-07-02 17:08:52 +00001351 case pch::COMMENT_RANGES:
1352 Comments = (SourceRange *)BlobStart;
1353 NumComments = BlobLen / sizeof(SourceRange);
1354 break;
Douglas Gregord54f3a12009-10-05 21:07:28 +00001355
1356 case pch::SVN_BRANCH_REVISION: {
1357 unsigned CurRevision = getClangSubversionRevision();
1358 if (Record[0] && CurRevision && Record[0] != CurRevision) {
1359 Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old
1360 : diag::warn_pch_version_too_new);
1361 return IgnorePCH;
1362 }
1363
1364 const char *CurBranch = getClangSubversionPath();
1365 if (strncmp(CurBranch, BlobStart, BlobLen)) {
1366 std::string PCHBranch(BlobStart, BlobLen);
1367 Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
1368 return IgnorePCH;
1369 }
1370 break;
1371 }
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00001372 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001373 }
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001374 Error("premature end of bitstream in PCH file");
Douglas Gregor55abb232009-04-10 20:39:37 +00001375 return Failure;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001376}
1377
Douglas Gregor92863e42009-04-10 23:10:45 +00001378PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor55abb232009-04-10 20:39:37 +00001379 // Set the PCH file name.
1380 this->FileName = FileName;
1381
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001382 // Open the PCH file.
Daniel Dunbar2d925eb2009-09-22 05:38:01 +00001383 //
1384 // FIXME: This shouldn't be here, we should just take a raw_ostream.
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001385 std::string ErrStr;
Daniel Dunbar69914f42009-11-10 00:46:19 +00001386 Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
Douglas Gregor92863e42009-04-10 23:10:45 +00001387 if (!Buffer) {
1388 Error(ErrStr.c_str());
1389 return IgnorePCH;
1390 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001391
1392 // Initialize the stream
Mike Stump11289f42009-09-09 15:08:12 +00001393 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Chris Lattner9356ace2009-04-26 20:59:20 +00001394 (const unsigned char *)Buffer->getBufferEnd());
1395 Stream.init(StreamFile);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001396
1397 // Sniff for the signature.
1398 if (Stream.Read(8) != 'C' ||
1399 Stream.Read(8) != 'P' ||
1400 Stream.Read(8) != 'C' ||
Douglas Gregor92863e42009-04-10 23:10:45 +00001401 Stream.Read(8) != 'H') {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001402 Diag(diag::err_not_a_pch_file) << FileName;
1403 return Failure;
Douglas Gregor92863e42009-04-10 23:10:45 +00001404 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001405
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001406 while (!Stream.AtEndOfStream()) {
1407 unsigned Code = Stream.ReadCode();
Mike Stump11289f42009-09-09 15:08:12 +00001408
Douglas Gregor92863e42009-04-10 23:10:45 +00001409 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001410 Error("invalid record at top-level of PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +00001411 return Failure;
1412 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001413
1414 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregora868bbd2009-04-21 22:25:48 +00001415
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001416 // We only know the PCH subblock ID.
1417 switch (BlockID) {
1418 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregor92863e42009-04-10 23:10:45 +00001419 if (Stream.ReadBlockInfoBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001420 Error("malformed BlockInfoBlock in PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +00001421 return Failure;
1422 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001423 break;
1424 case pch::PCH_BLOCK_ID:
Douglas Gregoreda6a892009-04-26 00:07:37 +00001425 switch (ReadPCHBlock()) {
Douglas Gregor55abb232009-04-10 20:39:37 +00001426 case Success:
1427 break;
1428
1429 case Failure:
Douglas Gregor92863e42009-04-10 23:10:45 +00001430 return Failure;
Douglas Gregor55abb232009-04-10 20:39:37 +00001431
1432 case IgnorePCH:
Douglas Gregorbfbde532009-04-10 21:16:55 +00001433 // FIXME: We could consider reading through to the end of this
1434 // PCH block, skipping subblocks, to see if there are other
1435 // PCH blocks elsewhere.
Douglas Gregor0bc12932009-04-27 21:28:04 +00001436
1437 // Clear out any preallocated source location entries, so that
1438 // the source manager does not try to resolve them later.
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001439 SourceMgr.ClearPreallocatedSLocEntries();
Douglas Gregor0bc12932009-04-27 21:28:04 +00001440
1441 // Remove the stat cache.
Douglas Gregord2eb58a2009-10-16 18:18:30 +00001442 if (StatCache)
1443 FileMgr.removeStatCache((PCHStatCache*)StatCache);
Douglas Gregor0bc12932009-04-27 21:28:04 +00001444
Douglas Gregor92863e42009-04-10 23:10:45 +00001445 return IgnorePCH;
Douglas Gregor55abb232009-04-10 20:39:37 +00001446 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001447 break;
1448 default:
Douglas Gregor92863e42009-04-10 23:10:45 +00001449 if (Stream.SkipBlock()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001450 Error("malformed block record in PCH file");
Douglas Gregor92863e42009-04-10 23:10:45 +00001451 return Failure;
1452 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001453 break;
1454 }
Mike Stump11289f42009-09-09 15:08:12 +00001455 }
1456
Douglas Gregore6648fb2009-04-28 20:33:11 +00001457 // Check the predefines buffer.
Mike Stump11289f42009-09-09 15:08:12 +00001458 if (CheckPredefinesBuffer(PCHPredefines, PCHPredefinesLen,
Douglas Gregore6648fb2009-04-28 20:33:11 +00001459 PCHPredefinesBufferID))
1460 return IgnorePCH;
Mike Stump11289f42009-09-09 15:08:12 +00001461
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001462 if (PP) {
Zhongxing Xu3f51f412009-07-18 09:26:51 +00001463 // Initialization of keywords and pragmas occurs before the
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001464 // PCH file is read, so there may be some identifiers that were
1465 // loaded into the IdentifierTable before we intercepted the
1466 // creation of identifiers. Iterate through the list of known
1467 // identifiers and determine whether we have to establish
1468 // preprocessor definitions or top-level identifier declaration
1469 // chains for those identifiers.
1470 //
1471 // We copy the IdentifierInfo pointers to a small vector first,
1472 // since de-serializing declarations or macro definitions can add
1473 // new entries into the identifier table, invalidating the
1474 // iterators.
1475 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1476 for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
1477 IdEnd = PP->getIdentifierTable().end();
1478 Id != IdEnd; ++Id)
1479 Identifiers.push_back(Id->second);
Mike Stump11289f42009-09-09 15:08:12 +00001480 PCHIdentifierLookupTable *IdTable
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001481 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1482 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1483 IdentifierInfo *II = Identifiers[I];
1484 // Look in the on-disk hash table for an entry for
1485 PCHIdentifierLookupTrait Info(*this, II);
Daniel Dunbar2c422dc92009-10-18 20:26:12 +00001486 std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001487 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1488 if (Pos == IdTable->end())
1489 continue;
Mike Stump11289f42009-09-09 15:08:12 +00001490
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001491 // Dereferencing the iterator has the effect of populating the
1492 // IdentifierInfo node with the various declarations it needs.
1493 (void)*Pos;
1494 }
Douglas Gregora868bbd2009-04-21 22:25:48 +00001495 }
1496
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001497 if (Context)
1498 InitializeContext(*Context);
Douglas Gregorfeb84b02009-04-14 21:18:50 +00001499
Douglas Gregora868bbd2009-04-21 22:25:48 +00001500 return Success;
Douglas Gregorfeb84b02009-04-14 21:18:50 +00001501}
1502
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001503void PCHReader::InitializeContext(ASTContext &Ctx) {
1504 Context = &Ctx;
1505 assert(Context && "Passed null context!");
1506
1507 assert(PP && "Forgot to set Preprocessor ?");
1508 PP->getIdentifierTable().setExternalIdentifierLookup(this);
1509 PP->getHeaderSearchInfo().SetExternalLookup(this);
Mike Stump11289f42009-09-09 15:08:12 +00001510
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001511 // Load the translation unit declaration
1512 ReadDeclRecord(DeclOffsets[0], 0);
1513
1514 // Load the special types.
1515 Context->setBuiltinVaListType(
1516 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
1517 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1518 Context->setObjCIdType(GetType(Id));
1519 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1520 Context->setObjCSelType(GetType(Sel));
1521 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1522 Context->setObjCProtoType(GetType(Proto));
1523 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1524 Context->setObjCClassType(GetType(Class));
Steve Naroff7cae42b2009-07-10 23:34:53 +00001525
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001526 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1527 Context->setCFConstantStringType(GetType(String));
Mike Stump11289f42009-09-09 15:08:12 +00001528 if (unsigned FastEnum
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001529 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1530 Context->setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregor27821ce2009-07-07 16:35:42 +00001531 if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
1532 QualType FileType = GetType(File);
1533 assert(!FileType.isNull() && "FILE type is NULL");
John McCall9dd450b2009-09-21 23:43:11 +00001534 if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
Douglas Gregor27821ce2009-07-07 16:35:42 +00001535 Context->setFILEDecl(Typedef->getDecl());
1536 else {
Ted Kremenekc23c7e62009-07-29 21:53:49 +00001537 const TagType *Tag = FileType->getAs<TagType>();
Douglas Gregor27821ce2009-07-07 16:35:42 +00001538 assert(Tag && "Invalid FILE type in PCH file");
1539 Context->setFILEDecl(Tag->getDecl());
1540 }
1541 }
Mike Stumpa4de80b2009-07-28 02:25:19 +00001542 if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
1543 QualType Jmp_bufType = GetType(Jmp_buf);
1544 assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL");
John McCall9dd450b2009-09-21 23:43:11 +00001545 if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
Mike Stumpa4de80b2009-07-28 02:25:19 +00001546 Context->setjmp_bufDecl(Typedef->getDecl());
1547 else {
Ted Kremenekc23c7e62009-07-29 21:53:49 +00001548 const TagType *Tag = Jmp_bufType->getAs<TagType>();
Mike Stumpa4de80b2009-07-28 02:25:19 +00001549 assert(Tag && "Invalid jmp_bug type in PCH file");
1550 Context->setjmp_bufDecl(Tag->getDecl());
1551 }
1552 }
1553 if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
1554 QualType Sigjmp_bufType = GetType(Sigjmp_buf);
1555 assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL");
John McCall9dd450b2009-09-21 23:43:11 +00001556 if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
Mike Stumpa4de80b2009-07-28 02:25:19 +00001557 Context->setsigjmp_bufDecl(Typedef->getDecl());
1558 else {
Ted Kremenekc23c7e62009-07-29 21:53:49 +00001559 const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
Mike Stumpa4de80b2009-07-28 02:25:19 +00001560 assert(Tag && "Invalid sigjmp_buf type in PCH file");
1561 Context->setsigjmp_bufDecl(Tag->getDecl());
1562 }
1563 }
Mike Stump11289f42009-09-09 15:08:12 +00001564 if (unsigned ObjCIdRedef
Douglas Gregora8eed7d2009-08-21 00:27:50 +00001565 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
1566 Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
Mike Stump11289f42009-09-09 15:08:12 +00001567 if (unsigned ObjCClassRedef
Douglas Gregora8eed7d2009-08-21 00:27:50 +00001568 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
1569 Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
Mike Stumpd0153282009-10-20 02:12:22 +00001570 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
1571 Context->setBlockDescriptorType(GetType(String));
Mike Stumpe1b19ba2009-10-22 00:49:09 +00001572 if (unsigned String
1573 = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
1574 Context->setBlockDescriptorExtendedType(GetType(String));
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001575}
1576
Douglas Gregor45fe0362009-05-12 01:31:05 +00001577/// \brief Retrieve the name of the original source file name
1578/// directly from the PCH file, without actually loading the PCH
1579/// file.
1580std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
1581 // Open the PCH file.
1582 std::string ErrStr;
1583 llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
1584 Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
1585 if (!Buffer) {
1586 fprintf(stderr, "error: %s\n", ErrStr.c_str());
1587 return std::string();
1588 }
1589
1590 // Initialize the stream
1591 llvm::BitstreamReader StreamFile;
1592 llvm::BitstreamCursor Stream;
Mike Stump11289f42009-09-09 15:08:12 +00001593 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Douglas Gregor45fe0362009-05-12 01:31:05 +00001594 (const unsigned char *)Buffer->getBufferEnd());
1595 Stream.init(StreamFile);
1596
1597 // Sniff for the signature.
1598 if (Stream.Read(8) != 'C' ||
1599 Stream.Read(8) != 'P' ||
1600 Stream.Read(8) != 'C' ||
1601 Stream.Read(8) != 'H') {
Mike Stump11289f42009-09-09 15:08:12 +00001602 fprintf(stderr,
Douglas Gregor45fe0362009-05-12 01:31:05 +00001603 "error: '%s' does not appear to be a precompiled header file\n",
1604 PCHFileName.c_str());
1605 return std::string();
1606 }
1607
1608 RecordData Record;
1609 while (!Stream.AtEndOfStream()) {
1610 unsigned Code = Stream.ReadCode();
Mike Stump11289f42009-09-09 15:08:12 +00001611
Douglas Gregor45fe0362009-05-12 01:31:05 +00001612 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1613 unsigned BlockID = Stream.ReadSubBlockID();
Mike Stump11289f42009-09-09 15:08:12 +00001614
Douglas Gregor45fe0362009-05-12 01:31:05 +00001615 // We only know the PCH subblock ID.
1616 switch (BlockID) {
1617 case pch::PCH_BLOCK_ID:
1618 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
1619 fprintf(stderr, "error: malformed block record in PCH file\n");
1620 return std::string();
1621 }
1622 break;
Mike Stump11289f42009-09-09 15:08:12 +00001623
Douglas Gregor45fe0362009-05-12 01:31:05 +00001624 default:
1625 if (Stream.SkipBlock()) {
1626 fprintf(stderr, "error: malformed block record in PCH file\n");
1627 return std::string();
1628 }
1629 break;
1630 }
1631 continue;
1632 }
1633
1634 if (Code == llvm::bitc::END_BLOCK) {
1635 if (Stream.ReadBlockEnd()) {
1636 fprintf(stderr, "error: error at end of module block in PCH file\n");
1637 return std::string();
1638 }
1639 continue;
1640 }
1641
1642 if (Code == llvm::bitc::DEFINE_ABBREV) {
1643 Stream.ReadAbbrevRecord();
1644 continue;
1645 }
1646
1647 Record.clear();
1648 const char *BlobStart = 0;
1649 unsigned BlobLen = 0;
Mike Stump11289f42009-09-09 15:08:12 +00001650 if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
Douglas Gregor45fe0362009-05-12 01:31:05 +00001651 == pch::ORIGINAL_FILE_NAME)
1652 return std::string(BlobStart, BlobLen);
Mike Stump11289f42009-09-09 15:08:12 +00001653 }
Douglas Gregor45fe0362009-05-12 01:31:05 +00001654
1655 return std::string();
1656}
1657
Douglas Gregor55abb232009-04-10 20:39:37 +00001658/// \brief Parse the record that corresponds to a LangOptions data
1659/// structure.
1660///
1661/// This routine compares the language options used to generate the
1662/// PCH file against the language options set for the current
1663/// compilation. For each option, we classify differences between the
1664/// two compiler states as either "benign" or "important". Benign
1665/// differences don't matter, and we accept them without complaint
1666/// (and without modifying the language options). Differences between
1667/// the states for important options cause the PCH file to be
1668/// unusable, so we emit a warning and return true to indicate that
1669/// there was an error.
1670///
1671/// \returns true if the PCH file is unacceptable, false otherwise.
1672bool PCHReader::ParseLanguageOptions(
1673 const llvm::SmallVectorImpl<uint64_t> &Record) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001674 if (Listener) {
1675 LangOptions LangOpts;
Mike Stump11289f42009-09-09 15:08:12 +00001676
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001677 #define PARSE_LANGOPT(Option) \
1678 LangOpts.Option = Record[Idx]; \
1679 ++Idx
Mike Stump11289f42009-09-09 15:08:12 +00001680
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001681 unsigned Idx = 0;
1682 PARSE_LANGOPT(Trigraphs);
1683 PARSE_LANGOPT(BCPLComment);
1684 PARSE_LANGOPT(DollarIdents);
1685 PARSE_LANGOPT(AsmPreprocessor);
1686 PARSE_LANGOPT(GNUMode);
1687 PARSE_LANGOPT(ImplicitInt);
1688 PARSE_LANGOPT(Digraphs);
1689 PARSE_LANGOPT(HexFloats);
1690 PARSE_LANGOPT(C99);
1691 PARSE_LANGOPT(Microsoft);
1692 PARSE_LANGOPT(CPlusPlus);
1693 PARSE_LANGOPT(CPlusPlus0x);
1694 PARSE_LANGOPT(CXXOperatorNames);
1695 PARSE_LANGOPT(ObjC1);
1696 PARSE_LANGOPT(ObjC2);
1697 PARSE_LANGOPT(ObjCNonFragileABI);
1698 PARSE_LANGOPT(PascalStrings);
1699 PARSE_LANGOPT(WritableStrings);
1700 PARSE_LANGOPT(LaxVectorConversions);
Nate Begemanf2911662009-06-25 23:01:11 +00001701 PARSE_LANGOPT(AltiVec);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001702 PARSE_LANGOPT(Exceptions);
1703 PARSE_LANGOPT(NeXTRuntime);
1704 PARSE_LANGOPT(Freestanding);
1705 PARSE_LANGOPT(NoBuiltin);
1706 PARSE_LANGOPT(ThreadsafeStatics);
Douglas Gregorb3286fe2009-09-03 14:36:33 +00001707 PARSE_LANGOPT(POSIXThreads);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001708 PARSE_LANGOPT(Blocks);
1709 PARSE_LANGOPT(EmitAllDecls);
1710 PARSE_LANGOPT(MathErrno);
1711 PARSE_LANGOPT(OverflowChecking);
1712 PARSE_LANGOPT(HeinousExtensions);
1713 PARSE_LANGOPT(Optimize);
1714 PARSE_LANGOPT(OptimizeSize);
1715 PARSE_LANGOPT(Static);
1716 PARSE_LANGOPT(PICLevel);
1717 PARSE_LANGOPT(GNUInline);
1718 PARSE_LANGOPT(NoInline);
1719 PARSE_LANGOPT(AccessControl);
1720 PARSE_LANGOPT(CharIsSigned);
John Thompsoned4e2952009-11-05 20:14:16 +00001721 PARSE_LANGOPT(ShortWChar);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001722 LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
1723 ++Idx;
1724 LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
1725 ++Idx;
Daniel Dunbar143021e2009-09-21 04:16:19 +00001726 LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
1727 Record[Idx]);
1728 ++Idx;
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001729 PARSE_LANGOPT(InstantiationDepth);
Nate Begemanf2911662009-06-25 23:01:11 +00001730 PARSE_LANGOPT(OpenCL);
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001731 #undef PARSE_LANGOPT
Douglas Gregor55abb232009-04-10 20:39:37 +00001732
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00001733 return Listener->ReadLanguageOptions(LangOpts);
Douglas Gregor55abb232009-04-10 20:39:37 +00001734 }
Douglas Gregor55abb232009-04-10 20:39:37 +00001735
1736 return false;
1737}
1738
Douglas Gregorc6d5edd2009-07-02 17:08:52 +00001739void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
1740 Comments.resize(NumComments);
1741 std::copy(this->Comments, this->Comments + NumComments,
1742 Comments.begin());
1743}
1744
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001745/// \brief Read and return the type at the given offset.
1746///
1747/// This routine actually reads the record corresponding to the type
1748/// at the given offset in the bitstream. It is a helper routine for
1749/// GetType, which deals with reading type IDs.
1750QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregorfeb84b02009-04-14 21:18:50 +00001751 // Keep track of where we are in the stream, then jump back there
1752 // after reading this type.
Douglas Gregor12bfa382009-10-17 00:13:19 +00001753 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorfeb84b02009-04-14 21:18:50 +00001754
Douglas Gregor1342e842009-07-06 18:54:52 +00001755 // Note that we are loading a type record.
1756 LoadingTypeOrDecl Loading(*this);
Mike Stump11289f42009-09-09 15:08:12 +00001757
Douglas Gregor12bfa382009-10-17 00:13:19 +00001758 DeclsCursor.JumpToBit(Offset);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001759 RecordData Record;
Douglas Gregor12bfa382009-10-17 00:13:19 +00001760 unsigned Code = DeclsCursor.ReadCode();
1761 switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
Douglas Gregor455b8f42009-04-15 22:00:08 +00001762 case pch::TYPE_EXT_QUAL: {
John McCall8ccfcb52009-09-24 19:53:00 +00001763 assert(Record.size() == 2 &&
Douglas Gregor455b8f42009-04-15 22:00:08 +00001764 "Incorrect encoding of extended qualifier type");
1765 QualType Base = GetType(Record[0]);
John McCall8ccfcb52009-09-24 19:53:00 +00001766 Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
1767 return Context->getQualifiedType(Base, Quals);
Douglas Gregor455b8f42009-04-15 22:00:08 +00001768 }
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001769
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001770 case pch::TYPE_FIXED_WIDTH_INT: {
1771 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
Chris Lattner8575daa2009-04-27 21:45:14 +00001772 return Context->getFixedWidthIntType(Record[0], Record[1]);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001773 }
1774
1775 case pch::TYPE_COMPLEX: {
1776 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1777 QualType ElemType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001778 return Context->getComplexType(ElemType);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001779 }
1780
1781 case pch::TYPE_POINTER: {
1782 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1783 QualType PointeeType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001784 return Context->getPointerType(PointeeType);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001785 }
1786
1787 case pch::TYPE_BLOCK_POINTER: {
1788 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1789 QualType PointeeType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001790 return Context->getBlockPointerType(PointeeType);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001791 }
1792
1793 case pch::TYPE_LVALUE_REFERENCE: {
1794 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1795 QualType PointeeType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001796 return Context->getLValueReferenceType(PointeeType);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001797 }
1798
1799 case pch::TYPE_RVALUE_REFERENCE: {
1800 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1801 QualType PointeeType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001802 return Context->getRValueReferenceType(PointeeType);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001803 }
1804
1805 case pch::TYPE_MEMBER_POINTER: {
1806 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1807 QualType PointeeType = GetType(Record[0]);
1808 QualType ClassType = GetType(Record[1]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001809 return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001810 }
1811
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001812 case pch::TYPE_CONSTANT_ARRAY: {
1813 QualType ElementType = GetType(Record[0]);
1814 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1815 unsigned IndexTypeQuals = Record[2];
1816 unsigned Idx = 3;
1817 llvm::APInt Size = ReadAPInt(Record, Idx);
Douglas Gregor04318252009-07-06 15:59:29 +00001818 return Context->getConstantArrayType(ElementType, Size,
1819 ASM, IndexTypeQuals);
1820 }
1821
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001822 case pch::TYPE_INCOMPLETE_ARRAY: {
1823 QualType ElementType = GetType(Record[0]);
1824 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1825 unsigned IndexTypeQuals = Record[2];
Chris Lattner8575daa2009-04-27 21:45:14 +00001826 return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001827 }
1828
1829 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregorfeb84b02009-04-14 21:18:50 +00001830 QualType ElementType = GetType(Record[0]);
1831 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1832 unsigned IndexTypeQuals = Record[2];
Douglas Gregor04318252009-07-06 15:59:29 +00001833 SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
1834 SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001835 return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregor04318252009-07-06 15:59:29 +00001836 ASM, IndexTypeQuals,
1837 SourceRange(LBLoc, RBLoc));
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001838 }
1839
1840 case pch::TYPE_VECTOR: {
1841 if (Record.size() != 2) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001842 Error("incorrect encoding of vector type in PCH file");
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001843 return QualType();
1844 }
1845
1846 QualType ElementType = GetType(Record[0]);
1847 unsigned NumElements = Record[1];
Chris Lattner8575daa2009-04-27 21:45:14 +00001848 return Context->getVectorType(ElementType, NumElements);
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001849 }
1850
1851 case pch::TYPE_EXT_VECTOR: {
1852 if (Record.size() != 2) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001853 Error("incorrect encoding of extended vector type in PCH file");
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001854 return QualType();
1855 }
1856
1857 QualType ElementType = GetType(Record[0]);
1858 unsigned NumElements = Record[1];
Chris Lattner8575daa2009-04-27 21:45:14 +00001859 return Context->getExtVectorType(ElementType, NumElements);
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001860 }
1861
1862 case pch::TYPE_FUNCTION_NO_PROTO: {
1863 if (Record.size() != 1) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001864 Error("incorrect encoding of no-proto function type");
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001865 return QualType();
1866 }
1867 QualType ResultType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001868 return Context->getFunctionNoProtoType(ResultType);
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001869 }
1870
1871 case pch::TYPE_FUNCTION_PROTO: {
1872 QualType ResultType = GetType(Record[0]);
1873 unsigned Idx = 1;
1874 unsigned NumParams = Record[Idx++];
1875 llvm::SmallVector<QualType, 16> ParamTypes;
1876 for (unsigned I = 0; I != NumParams; ++I)
1877 ParamTypes.push_back(GetType(Record[Idx++]));
1878 bool isVariadic = Record[Idx++];
1879 unsigned Quals = Record[Idx++];
Sebastian Redl5068f77ac2009-05-27 22:11:52 +00001880 bool hasExceptionSpec = Record[Idx++];
1881 bool hasAnyExceptionSpec = Record[Idx++];
1882 unsigned NumExceptions = Record[Idx++];
1883 llvm::SmallVector<QualType, 2> Exceptions;
1884 for (unsigned I = 0; I != NumExceptions; ++I)
1885 Exceptions.push_back(GetType(Record[Idx++]));
Jay Foad7d0479f2009-05-21 09:52:38 +00001886 return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
Sebastian Redl5068f77ac2009-05-27 22:11:52 +00001887 isVariadic, Quals, hasExceptionSpec,
1888 hasAnyExceptionSpec, NumExceptions,
1889 Exceptions.data());
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001890 }
1891
1892 case pch::TYPE_TYPEDEF:
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001893 assert(Record.size() == 1 && "incorrect encoding of typedef type");
Chris Lattner8575daa2009-04-27 21:45:14 +00001894 return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001895
1896 case pch::TYPE_TYPEOF_EXPR:
Chris Lattner8575daa2009-04-27 21:45:14 +00001897 return Context->getTypeOfExprType(ReadTypeExpr());
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001898
1899 case pch::TYPE_TYPEOF: {
1900 if (Record.size() != 1) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001901 Error("incorrect encoding of typeof(type) in PCH file");
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001902 return QualType();
1903 }
1904 QualType UnderlyingType = GetType(Record[0]);
Chris Lattner8575daa2009-04-27 21:45:14 +00001905 return Context->getTypeOfType(UnderlyingType);
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001906 }
Mike Stump11289f42009-09-09 15:08:12 +00001907
Anders Carlsson81df7b82009-06-24 19:06:50 +00001908 case pch::TYPE_DECLTYPE:
1909 return Context->getDecltypeType(ReadTypeExpr());
1910
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001911 case pch::TYPE_RECORD:
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001912 assert(Record.size() == 1 && "incorrect encoding of record type");
Chris Lattner8575daa2009-04-27 21:45:14 +00001913 return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001914
Douglas Gregor1daeb692009-04-13 18:14:40 +00001915 case pch::TYPE_ENUM:
Douglas Gregor6f00bf82009-04-28 21:53:25 +00001916 assert(Record.size() == 1 && "incorrect encoding of enum type");
Chris Lattner8575daa2009-04-27 21:45:14 +00001917 return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
Douglas Gregor1daeb692009-04-13 18:14:40 +00001918
John McCallfcc33b02009-09-05 00:15:47 +00001919 case pch::TYPE_ELABORATED: {
1920 assert(Record.size() == 2 && "incorrect encoding of elaborated type");
1921 unsigned Tag = Record[1];
1922 return Context->getElaboratedType(GetType(Record[0]),
1923 (ElaboratedType::TagKind) Tag);
1924 }
1925
Steve Naroffc277ad12009-07-18 15:33:26 +00001926 case pch::TYPE_OBJC_INTERFACE: {
Chris Lattner587cbe12009-04-22 06:45:28 +00001927 unsigned Idx = 0;
1928 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1929 unsigned NumProtos = Record[Idx++];
1930 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1931 for (unsigned I = 0; I != NumProtos; ++I)
1932 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroffc277ad12009-07-18 15:33:26 +00001933 return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos);
Chris Lattner587cbe12009-04-22 06:45:28 +00001934 }
Douglas Gregor85c0fcd2009-04-13 20:46:52 +00001935
Steve Narofffb4330f2009-06-17 22:40:22 +00001936 case pch::TYPE_OBJC_OBJECT_POINTER: {
Chris Lattner6e054af2009-04-22 06:40:03 +00001937 unsigned Idx = 0;
Steve Naroff7cae42b2009-07-10 23:34:53 +00001938 QualType OIT = GetType(Record[Idx++]);
Chris Lattner6e054af2009-04-22 06:40:03 +00001939 unsigned NumProtos = Record[Idx++];
1940 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1941 for (unsigned I = 0; I != NumProtos; ++I)
1942 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroff7cae42b2009-07-10 23:34:53 +00001943 return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
Chris Lattner6e054af2009-04-22 06:40:03 +00001944 }
Argyrios Kyrtzidisa7a36df2009-09-29 19:42:55 +00001945
John McCallcebee162009-10-18 09:09:24 +00001946 case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
1947 unsigned Idx = 0;
1948 QualType Parm = GetType(Record[Idx++]);
1949 QualType Replacement = GetType(Record[Idx++]);
1950 return
1951 Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
1952 Replacement);
1953 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001954 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00001955 // Suppress a GCC warning
1956 return QualType();
1957}
1958
John McCall8f115c62009-10-16 21:56:05 +00001959namespace {
1960
1961class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
1962 PCHReader &Reader;
1963 const PCHReader::RecordData &Record;
1964 unsigned &Idx;
1965
1966public:
1967 TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
1968 unsigned &Idx)
1969 : Reader(Reader), Record(Record), Idx(Idx) { }
1970
John McCall17001972009-10-18 01:05:36 +00001971 // We want compile-time assurance that we've enumerated all of
1972 // these, so unfortunately we have to declare them first, then
1973 // define them out-of-line.
1974#define ABSTRACT_TYPELOC(CLASS, PARENT)
John McCall8f115c62009-10-16 21:56:05 +00001975#define TYPELOC(CLASS, PARENT) \
John McCall17001972009-10-18 01:05:36 +00001976 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
John McCall8f115c62009-10-16 21:56:05 +00001977#include "clang/AST/TypeLocNodes.def"
1978
John McCall17001972009-10-18 01:05:36 +00001979 void VisitFunctionTypeLoc(FunctionTypeLoc);
1980 void VisitArrayTypeLoc(ArrayTypeLoc);
John McCall8f115c62009-10-16 21:56:05 +00001981};
1982
1983}
1984
John McCall17001972009-10-18 01:05:36 +00001985void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
John McCall8f115c62009-10-16 21:56:05 +00001986 // nothing to do
1987}
John McCall17001972009-10-18 01:05:36 +00001988void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
1989 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00001990}
John McCall17001972009-10-18 01:05:36 +00001991void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
1992 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00001993}
John McCall17001972009-10-18 01:05:36 +00001994void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
1995 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00001996}
John McCall17001972009-10-18 01:05:36 +00001997void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
1998 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00001999}
John McCall17001972009-10-18 01:05:36 +00002000void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
2001 TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002002}
John McCall17001972009-10-18 01:05:36 +00002003void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
2004 TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002005}
John McCall17001972009-10-18 01:05:36 +00002006void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
2007 TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002008}
John McCall17001972009-10-18 01:05:36 +00002009void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
2010 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002011}
John McCall17001972009-10-18 01:05:36 +00002012void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
2013 TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2014 TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002015 if (Record[Idx++])
John McCall17001972009-10-18 01:05:36 +00002016 TL.setSizeExpr(Reader.ReadDeclExpr());
Douglas Gregor12bfa382009-10-17 00:13:19 +00002017 else
John McCall17001972009-10-18 01:05:36 +00002018 TL.setSizeExpr(0);
2019}
2020void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
2021 VisitArrayTypeLoc(TL);
2022}
2023void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
2024 VisitArrayTypeLoc(TL);
2025}
2026void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
2027 VisitArrayTypeLoc(TL);
2028}
2029void TypeLocReader::VisitDependentSizedArrayTypeLoc(
2030 DependentSizedArrayTypeLoc TL) {
2031 VisitArrayTypeLoc(TL);
2032}
2033void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
2034 DependentSizedExtVectorTypeLoc TL) {
2035 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2036}
2037void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
2038 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2039}
2040void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
2041 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2042}
2043void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
2044 TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2045 TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2046 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
John McCalle6347002009-10-23 01:28:53 +00002047 TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
John McCall17001972009-10-18 01:05:36 +00002048 }
2049}
2050void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
2051 VisitFunctionTypeLoc(TL);
2052}
2053void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
2054 VisitFunctionTypeLoc(TL);
2055}
2056void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
2057 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2058}
2059void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
2060 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2061}
2062void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
2063 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2064}
2065void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
2066 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2067}
2068void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
2069 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2070}
2071void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
2072 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2073}
2074void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
2075 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2076}
2077void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
2078 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2079}
John McCallcebee162009-10-18 09:09:24 +00002080void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
2081 SubstTemplateTypeParmTypeLoc TL) {
2082 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2083}
John McCall17001972009-10-18 01:05:36 +00002084void TypeLocReader::VisitTemplateSpecializationTypeLoc(
2085 TemplateSpecializationTypeLoc TL) {
John McCall0ad16662009-10-29 08:12:44 +00002086 TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2087 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2088 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2089 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
2090 TL.setArgLocInfo(i,
2091 Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
2092 Record, Idx));
John McCall17001972009-10-18 01:05:36 +00002093}
2094void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
2095 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2096}
2097void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
2098 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2099}
2100void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
2101 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall17001972009-10-18 01:05:36 +00002102 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2103 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2104 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2105 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall8f115c62009-10-16 21:56:05 +00002106}
John McCallfc93cf92009-10-22 22:37:11 +00002107void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
2108 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2109 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2110 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2111 TL.setHasBaseTypeAsWritten(Record[Idx++]);
2112 TL.setHasProtocolsAsWritten(Record[Idx++]);
2113 if (TL.hasProtocolsAsWritten())
2114 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2115 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
2116}
John McCall8f115c62009-10-16 21:56:05 +00002117
2118DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
2119 unsigned &Idx) {
2120 QualType InfoTy = GetType(Record[Idx++]);
2121 if (InfoTy.isNull())
2122 return 0;
2123
2124 DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
2125 TypeLocReader TLR(*this, Record, Idx);
2126 for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
2127 TLR.Visit(TL);
2128 return DInfo;
2129}
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002130
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00002131QualType PCHReader::GetType(pch::TypeID ID) {
John McCall8ccfcb52009-09-24 19:53:00 +00002132 unsigned FastQuals = ID & Qualifiers::FastMask;
2133 unsigned Index = ID >> Qualifiers::FastWidth;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002134
2135 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
2136 QualType T;
2137 switch ((pch::PredefinedTypeIDs)Index) {
2138 case pch::PREDEF_TYPE_NULL_ID: return QualType();
Chris Lattner8575daa2009-04-27 21:45:14 +00002139 case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
2140 case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002141
2142 case pch::PREDEF_TYPE_CHAR_U_ID:
2143 case pch::PREDEF_TYPE_CHAR_S_ID:
2144 // FIXME: Check that the signedness of CharTy is correct!
Chris Lattner8575daa2009-04-27 21:45:14 +00002145 T = Context->CharTy;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002146 break;
2147
Chris Lattner8575daa2009-04-27 21:45:14 +00002148 case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
2149 case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
2150 case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
2151 case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
2152 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
Chris Lattnerf122cef2009-04-30 02:43:43 +00002153 case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
Chris Lattner8575daa2009-04-27 21:45:14 +00002154 case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
2155 case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
2156 case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
2157 case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
2158 case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
2159 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
Chris Lattnerf122cef2009-04-30 02:43:43 +00002160 case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
Chris Lattner8575daa2009-04-27 21:45:14 +00002161 case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
2162 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
2163 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
2164 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
2165 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
Sebastian Redl576fd422009-05-10 18:38:11 +00002166 case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
Alisdair Mereditha9ad47d2009-07-14 06:30:34 +00002167 case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
2168 case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
Steve Naroff1329fa02009-07-15 18:40:39 +00002169 case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
2170 case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002171 }
2172
2173 assert(!T.isNull() && "Unknown predefined type");
John McCall8ccfcb52009-09-24 19:53:00 +00002174 return T.withFastQualifiers(FastQuals);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002175 }
2176
2177 Index -= pch::NUM_PREDEF_TYPE_IDS;
Steve Naroffc277ad12009-07-18 15:33:26 +00002178 //assert(Index < TypesLoaded.size() && "Type index out-of-range");
John McCall8ccfcb52009-09-24 19:53:00 +00002179 if (TypesLoaded[Index].isNull())
2180 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
Mike Stump11289f42009-09-09 15:08:12 +00002181
John McCall8ccfcb52009-09-24 19:53:00 +00002182 return TypesLoaded[Index].withFastQualifiers(FastQuals);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002183}
2184
John McCall0ad16662009-10-29 08:12:44 +00002185TemplateArgumentLocInfo
2186PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
2187 const RecordData &Record,
2188 unsigned &Index) {
2189 switch (Kind) {
2190 case TemplateArgument::Expression:
2191 return ReadDeclExpr();
2192 case TemplateArgument::Type:
2193 return GetDeclaratorInfo(Record, Index);
2194 case TemplateArgument::Null:
2195 case TemplateArgument::Integral:
2196 case TemplateArgument::Declaration:
2197 case TemplateArgument::Pack:
2198 return TemplateArgumentLocInfo();
2199 }
2200 llvm::llvm_unreachable("unexpected template argument loc");
2201 return TemplateArgumentLocInfo();
2202}
2203
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00002204Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002205 if (ID == 0)
2206 return 0;
2207
Douglas Gregor745ed142009-04-25 18:35:21 +00002208 if (ID > DeclsLoaded.size()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00002209 Error("declaration ID out-of-range for PCH file");
Douglas Gregor745ed142009-04-25 18:35:21 +00002210 return 0;
2211 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002212
Douglas Gregor745ed142009-04-25 18:35:21 +00002213 unsigned Index = ID - 1;
2214 if (!DeclsLoaded[Index])
2215 ReadDeclRecord(DeclOffsets[Index], Index);
2216
2217 return DeclsLoaded[Index];
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002218}
2219
Chris Lattner9c28af02009-04-27 05:46:25 +00002220/// \brief Resolve the offset of a statement into a statement.
2221///
2222/// This operation will read a new statement from the external
2223/// source each time it is called, and is meant to be used via a
2224/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
2225Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattner1de76db2009-04-27 05:58:23 +00002226 // Since we know tha this statement is part of a decl, make sure to use the
2227 // decl cursor to read it.
2228 DeclsCursor.JumpToBit(Offset);
2229 return ReadStmt(DeclsCursor);
Douglas Gregor3c3aa612009-04-18 00:07:54 +00002230}
2231
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002232bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor1e9bf3b2009-04-10 17:25:41 +00002233 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Mike Stump11289f42009-09-09 15:08:12 +00002234 assert(DC->hasExternalLexicalStorage() &&
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002235 "DeclContext has no lexical decls in storage");
2236 uint64_t Offset = DeclContextOffsets[DC].first;
2237 assert(Offset && "DeclContext has no lexical decls in storage");
2238
Douglas Gregorfeb84b02009-04-14 21:18:50 +00002239 // Keep track of where we are in the stream, then jump back there
2240 // after reading this context.
Chris Lattner72405d62009-04-27 07:35:40 +00002241 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorfeb84b02009-04-14 21:18:50 +00002242
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002243 // Load the record containing all of the declarations lexically in
2244 // this context.
Chris Lattner72405d62009-04-27 07:35:40 +00002245 DeclsCursor.JumpToBit(Offset);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002246 RecordData Record;
Chris Lattner72405d62009-04-27 07:35:40 +00002247 unsigned Code = DeclsCursor.ReadCode();
2248 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregore95304a2009-04-15 18:43:11 +00002249 (void)RecCode;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002250 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
2251
2252 // Load all of the declaration IDs
2253 Decls.clear();
2254 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregora57c3ab2009-04-22 22:34:57 +00002255 ++NumLexicalDeclContextsRead;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002256 return false;
2257}
2258
2259bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattner72405d62009-04-27 07:35:40 +00002260 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Mike Stump11289f42009-09-09 15:08:12 +00002261 assert(DC->hasExternalVisibleStorage() &&
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002262 "DeclContext has no visible decls in storage");
2263 uint64_t Offset = DeclContextOffsets[DC].second;
2264 assert(Offset && "DeclContext has no visible decls in storage");
2265
Douglas Gregorfeb84b02009-04-14 21:18:50 +00002266 // Keep track of where we are in the stream, then jump back there
2267 // after reading this context.
Chris Lattner72405d62009-04-27 07:35:40 +00002268 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregorfeb84b02009-04-14 21:18:50 +00002269
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002270 // Load the record containing all of the declarations visible in
2271 // this context.
Chris Lattner72405d62009-04-27 07:35:40 +00002272 DeclsCursor.JumpToBit(Offset);
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002273 RecordData Record;
Chris Lattner72405d62009-04-27 07:35:40 +00002274 unsigned Code = DeclsCursor.ReadCode();
2275 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregore95304a2009-04-15 18:43:11 +00002276 (void)RecCode;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002277 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
2278 if (Record.size() == 0)
Mike Stump11289f42009-09-09 15:08:12 +00002279 return false;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002280
2281 Decls.clear();
2282
2283 unsigned Idx = 0;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002284 while (Idx < Record.size()) {
2285 Decls.push_back(VisibleDeclaration());
2286 Decls.back().Name = ReadDeclarationName(Record, Idx);
2287
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002288 unsigned Size = Record[Idx++];
Chris Lattner72405d62009-04-27 07:35:40 +00002289 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002290 LoadedDecls.reserve(Size);
2291 for (unsigned I = 0; I < Size; ++I)
2292 LoadedDecls.push_back(Record[Idx++]);
2293 }
2294
Douglas Gregora57c3ab2009-04-22 22:34:57 +00002295 ++NumVisibleDeclContextsRead;
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002296 return false;
2297}
2298
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00002299void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregorb985eeb2009-04-22 19:09:20 +00002300 this->Consumer = Consumer;
2301
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00002302 if (!Consumer)
2303 return;
2304
2305 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
Daniel Dunbar865c2a72009-09-17 03:06:44 +00002306 // Force deserialization of this decl, which will cause it to be passed to
2307 // the consumer (or queued).
2308 GetDecl(ExternalDefinitions[I]);
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00002309 }
Douglas Gregorf005eac2009-04-25 00:41:30 +00002310
2311 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
2312 DeclGroupRef DG(InterestingDecls[I]);
2313 Consumer->HandleTopLevelDecl(DG);
2314 }
Douglas Gregor1a0d0b92009-04-14 00:24:19 +00002315}
2316
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002317void PCHReader::PrintStats() {
2318 std::fprintf(stderr, "*** PCH Statistics:\n");
2319
Mike Stump11289f42009-09-09 15:08:12 +00002320 unsigned NumTypesLoaded
Douglas Gregor0e149972009-04-25 19:10:14 +00002321 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
John McCall8ccfcb52009-09-24 19:53:00 +00002322 QualType());
Douglas Gregor0e149972009-04-25 19:10:14 +00002323 unsigned NumDeclsLoaded
2324 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
2325 (Decl *)0);
2326 unsigned NumIdentifiersLoaded
2327 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
2328 IdentifiersLoaded.end(),
2329 (IdentifierInfo *)0);
Mike Stump11289f42009-09-09 15:08:12 +00002330 unsigned NumSelectorsLoaded
Douglas Gregor0e149972009-04-25 19:10:14 +00002331 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
2332 SelectorsLoaded.end(),
2333 Selector());
Douglas Gregorc3b1dd12009-04-13 20:50:16 +00002334
Douglas Gregorc5046832009-04-27 18:38:38 +00002335 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
2336 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor258ae542009-04-27 06:38:32 +00002337 if (TotalNumSLocEntries)
2338 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
2339 NumSLocEntriesRead, TotalNumSLocEntries,
2340 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor745ed142009-04-25 18:35:21 +00002341 if (!TypesLoaded.empty())
Douglas Gregor95c13f52009-04-25 17:48:32 +00002342 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor745ed142009-04-25 18:35:21 +00002343 NumTypesLoaded, (unsigned)TypesLoaded.size(),
2344 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
2345 if (!DeclsLoaded.empty())
Douglas Gregor95c13f52009-04-25 17:48:32 +00002346 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor745ed142009-04-25 18:35:21 +00002347 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
2348 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor0e149972009-04-25 19:10:14 +00002349 if (!IdentifiersLoaded.empty())
Douglas Gregor95c13f52009-04-25 17:48:32 +00002350 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor0e149972009-04-25 19:10:14 +00002351 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
2352 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor95c13f52009-04-25 17:48:32 +00002353 if (TotalNumSelectors)
2354 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
2355 NumSelectorsLoaded, TotalNumSelectors,
2356 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
2357 if (TotalNumStatements)
2358 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
2359 NumStatementsRead, TotalNumStatements,
2360 ((float)NumStatementsRead/TotalNumStatements * 100));
2361 if (TotalNumMacros)
2362 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
2363 NumMacrosRead, TotalNumMacros,
2364 ((float)NumMacrosRead/TotalNumMacros * 100));
2365 if (TotalLexicalDeclContexts)
2366 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
2367 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
2368 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
2369 * 100));
2370 if (TotalVisibleDeclContexts)
2371 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
2372 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
2373 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
2374 * 100));
2375 if (TotalSelectorsInMethodPool) {
2376 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
2377 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
2378 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
2379 * 100));
2380 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
2381 }
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002382 std::fprintf(stderr, "\n");
2383}
2384
Douglas Gregora868bbd2009-04-21 22:25:48 +00002385void PCHReader::InitializeSema(Sema &S) {
2386 SemaObj = &S;
Douglas Gregorc78d3462009-04-24 21:10:55 +00002387 S.ExternalSource = this;
2388
Douglas Gregor7cd60f72009-04-22 21:15:06 +00002389 // Makes sure any declarations that were deserialized "too early"
2390 // still get added to the identifier's declaration chains.
2391 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
2392 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
2393 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregora868bbd2009-04-21 22:25:48 +00002394 }
Douglas Gregor7cd60f72009-04-22 21:15:06 +00002395 PreloadedDecls.clear();
Douglas Gregord4df8652009-04-22 22:02:47 +00002396
2397 // If there were any tentative definitions, deserialize them and add
2398 // them to Sema's table of tentative definitions.
2399 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
2400 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
2401 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
Chris Lattner0c797362009-09-08 18:19:27 +00002402 SemaObj->TentativeDefinitionList.push_back(Var->getDeclName());
Douglas Gregord4df8652009-04-22 22:02:47 +00002403 }
Douglas Gregoracfc76c2009-04-22 22:18:58 +00002404
2405 // If there were any locally-scoped external declarations,
2406 // deserialize them and add them to Sema's table of locally-scoped
2407 // external declarations.
2408 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
2409 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
2410 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
2411 }
Douglas Gregor61cac2b2009-04-27 20:06:05 +00002412
2413 // If there were any ext_vector type declarations, deserialize them
2414 // and add them to Sema's vector of such declarations.
2415 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
2416 SemaObj->ExtVectorDecls.push_back(
2417 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
Douglas Gregora868bbd2009-04-21 22:25:48 +00002418}
2419
2420IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
2421 // Try to find this name within our on-disk hash table
Mike Stump11289f42009-09-09 15:08:12 +00002422 PCHIdentifierLookupTable *IdTable
Douglas Gregora868bbd2009-04-21 22:25:48 +00002423 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
2424 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
2425 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
2426 if (Pos == IdTable->end())
2427 return 0;
2428
2429 // Dereferencing the iterator has the effect of building the
2430 // IdentifierInfo node and populating it with the various
2431 // declarations it needs.
2432 return *Pos;
2433}
2434
Mike Stump11289f42009-09-09 15:08:12 +00002435std::pair<ObjCMethodList, ObjCMethodList>
Douglas Gregorc78d3462009-04-24 21:10:55 +00002436PCHReader::ReadMethodPool(Selector Sel) {
2437 if (!MethodPoolLookupTable)
2438 return std::pair<ObjCMethodList, ObjCMethodList>();
2439
2440 // Try to find this selector within our on-disk hash table.
2441 PCHMethodPoolLookupTable *PoolTable
2442 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
2443 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor95c13f52009-04-25 17:48:32 +00002444 if (Pos == PoolTable->end()) {
2445 ++NumMethodPoolMisses;
Douglas Gregorc78d3462009-04-24 21:10:55 +00002446 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor95c13f52009-04-25 17:48:32 +00002447 }
Douglas Gregorc78d3462009-04-24 21:10:55 +00002448
Douglas Gregor95c13f52009-04-25 17:48:32 +00002449 ++NumMethodPoolSelectorsRead;
Douglas Gregorc78d3462009-04-24 21:10:55 +00002450 return *Pos;
2451}
2452
Douglas Gregor0e149972009-04-25 19:10:14 +00002453void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregora868bbd2009-04-21 22:25:48 +00002454 assert(ID && "Non-zero identifier ID required");
Douglas Gregor6f00bf82009-04-28 21:53:25 +00002455 assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
Douglas Gregor0e149972009-04-25 19:10:14 +00002456 IdentifiersLoaded[ID - 1] = II;
Douglas Gregora868bbd2009-04-21 22:25:48 +00002457}
2458
Douglas Gregor1342e842009-07-06 18:54:52 +00002459/// \brief Set the globally-visible declarations associated with the given
2460/// identifier.
2461///
2462/// If the PCH reader is currently in a state where the given declaration IDs
Mike Stump11289f42009-09-09 15:08:12 +00002463/// cannot safely be resolved, they are queued until it is safe to resolve
Douglas Gregor1342e842009-07-06 18:54:52 +00002464/// them.
2465///
2466/// \param II an IdentifierInfo that refers to one or more globally-visible
2467/// declarations.
2468///
2469/// \param DeclIDs the set of declaration IDs with the name @p II that are
2470/// visible at global scope.
2471///
2472/// \param Nonrecursive should be true to indicate that the caller knows that
2473/// this call is non-recursive, and therefore the globally-visible declarations
2474/// will not be placed onto the pending queue.
Mike Stump11289f42009-09-09 15:08:12 +00002475void
2476PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
Douglas Gregor1342e842009-07-06 18:54:52 +00002477 const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
2478 bool Nonrecursive) {
2479 if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
2480 PendingIdentifierInfos.push_back(PendingIdentifierInfo());
2481 PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
2482 PII.II = II;
2483 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
2484 PII.DeclIDs.push_back(DeclIDs[I]);
2485 return;
2486 }
Mike Stump11289f42009-09-09 15:08:12 +00002487
Douglas Gregor1342e842009-07-06 18:54:52 +00002488 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
2489 NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
2490 if (SemaObj) {
2491 // Introduce this declaration into the translation-unit scope
2492 // and add it to the declaration chain for this identifier, so
2493 // that (unqualified) name lookup will find it.
2494 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
2495 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
2496 } else {
2497 // Queue this declaration so that it will be added to the
2498 // translation unit scope and identifier's declaration chain
2499 // once a Sema object is known.
2500 PreloadedDecls.push_back(D);
2501 }
2502 }
2503}
2504
Chris Lattnerc523d8e2009-04-11 21:15:38 +00002505IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00002506 if (ID == 0)
2507 return 0;
Mike Stump11289f42009-09-09 15:08:12 +00002508
Douglas Gregor0e149972009-04-25 19:10:14 +00002509 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00002510 Error("no identifier table in PCH file");
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00002511 return 0;
2512 }
Mike Stump11289f42009-09-09 15:08:12 +00002513
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00002514 assert(PP && "Forgot to set Preprocessor ?");
Douglas Gregor0e149972009-04-25 19:10:14 +00002515 if (!IdentifiersLoaded[ID - 1]) {
2516 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor95272492009-04-25 21:21:38 +00002517 const char *Str = IdentifierTableData + Offset;
Douglas Gregor5287b4e2009-04-25 21:04:17 +00002518
Douglas Gregorab4df582009-04-28 20:01:51 +00002519 // All of the strings in the PCH file are preceded by a 16-bit
2520 // length. Extract that 16-bit length to avoid having to execute
2521 // strlen().
Ted Kremenekca42a512009-10-23 04:45:31 +00002522 // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
2523 // unsigned integers. This is important to avoid integer overflow when
2524 // we cast them to 'unsigned'.
Ted Kremenek49c52322009-10-23 03:57:22 +00002525 const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
Douglas Gregorab4df582009-04-28 20:01:51 +00002526 unsigned StrLen = (((unsigned) StrLenPtr[0])
2527 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
Mike Stump11289f42009-09-09 15:08:12 +00002528 IdentifiersLoaded[ID - 1]
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00002529 = &PP->getIdentifierTable().get(Str, Str + StrLen);
Douglas Gregor3ed42cb2009-04-11 00:14:32 +00002530 }
Mike Stump11289f42009-09-09 15:08:12 +00002531
Douglas Gregor0e149972009-04-25 19:10:14 +00002532 return IdentifiersLoaded[ID - 1];
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002533}
2534
Douglas Gregor258ae542009-04-27 06:38:32 +00002535void PCHReader::ReadSLocEntry(unsigned ID) {
2536 ReadSLocEntryRecord(ID);
2537}
2538
Steve Naroff2ddea052009-04-23 10:39:46 +00002539Selector PCHReader::DecodeSelector(unsigned ID) {
2540 if (ID == 0)
2541 return Selector();
Mike Stump11289f42009-09-09 15:08:12 +00002542
Douglas Gregor6f00bf82009-04-28 21:53:25 +00002543 if (!MethodPoolLookupTableData)
Steve Naroff2ddea052009-04-23 10:39:46 +00002544 return Selector();
Douglas Gregor95c13f52009-04-25 17:48:32 +00002545
2546 if (ID > TotalNumSelectors) {
Douglas Gregor6f00bf82009-04-28 21:53:25 +00002547 Error("selector ID out of range in PCH file");
Steve Naroff2ddea052009-04-23 10:39:46 +00002548 return Selector();
2549 }
Douglas Gregor95c13f52009-04-25 17:48:32 +00002550
2551 unsigned Index = ID - 1;
2552 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
2553 // Load this selector from the selector table.
2554 // FIXME: endianness portability issues with SelectorOffsets table
2555 PCHMethodPoolLookupTrait Trait(*this);
Mike Stump11289f42009-09-09 15:08:12 +00002556 SelectorsLoaded[Index]
Douglas Gregor95c13f52009-04-25 17:48:32 +00002557 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
2558 }
2559
2560 return SelectorsLoaded[Index];
Steve Naroff2ddea052009-04-23 10:39:46 +00002561}
2562
Mike Stump11289f42009-09-09 15:08:12 +00002563DeclarationName
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002564PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
2565 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
2566 switch (Kind) {
2567 case DeclarationName::Identifier:
2568 return DeclarationName(GetIdentifierInfo(Record, Idx));
2569
2570 case DeclarationName::ObjCZeroArgSelector:
2571 case DeclarationName::ObjCOneArgSelector:
2572 case DeclarationName::ObjCMultiArgSelector:
Steve Naroff3c301dc2009-04-23 15:15:40 +00002573 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002574
2575 case DeclarationName::CXXConstructorName:
Chris Lattner8575daa2009-04-27 21:45:14 +00002576 return Context->DeclarationNames.getCXXConstructorName(
Douglas Gregor2211d342009-08-05 05:36:45 +00002577 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002578
2579 case DeclarationName::CXXDestructorName:
Chris Lattner8575daa2009-04-27 21:45:14 +00002580 return Context->DeclarationNames.getCXXDestructorName(
Douglas Gregor2211d342009-08-05 05:36:45 +00002581 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002582
2583 case DeclarationName::CXXConversionFunctionName:
Chris Lattner8575daa2009-04-27 21:45:14 +00002584 return Context->DeclarationNames.getCXXConversionFunctionName(
Douglas Gregor2211d342009-08-05 05:36:45 +00002585 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002586
2587 case DeclarationName::CXXOperatorName:
Chris Lattner8575daa2009-04-27 21:45:14 +00002588 return Context->DeclarationNames.getCXXOperatorName(
Douglas Gregoref84c4b2009-04-09 22:27:44 +00002589 (OverloadedOperatorKind)Record[Idx++]);
2590
2591 case DeclarationName::CXXUsingDirective:
2592 return DeclarationName::getUsingDirectiveName();
2593 }
2594
2595 // Required to silence GCC warning
2596 return DeclarationName();
2597}
Douglas Gregor55abb232009-04-10 20:39:37 +00002598
Douglas Gregor1daeb692009-04-13 18:14:40 +00002599/// \brief Read an integral value
2600llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
2601 unsigned BitWidth = Record[Idx++];
2602 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
2603 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
2604 Idx += NumWords;
2605 return Result;
2606}
2607
2608/// \brief Read a signed integral value
2609llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
2610 bool isUnsigned = Record[Idx++];
2611 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
2612}
2613
Douglas Gregore0a3a512009-04-14 21:55:33 +00002614/// \brief Read a floating-point value
2615llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregore0a3a512009-04-14 21:55:33 +00002616 return llvm::APFloat(ReadAPInt(Record, Idx));
2617}
2618
Douglas Gregorbc8a78d52009-04-15 21:30:51 +00002619// \brief Read a string
2620std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
2621 unsigned Len = Record[Idx++];
Jay Foad7d0479f2009-05-21 09:52:38 +00002622 std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Douglas Gregorbc8a78d52009-04-15 21:30:51 +00002623 Idx += Len;
2624 return Result;
2625}
2626
Douglas Gregor55abb232009-04-10 20:39:37 +00002627DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregor92863e42009-04-10 23:10:45 +00002628 return Diag(SourceLocation(), DiagID);
2629}
2630
2631DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00002632 return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
Douglas Gregor55abb232009-04-10 20:39:37 +00002633}
Douglas Gregora9af1d12009-04-17 00:04:06 +00002634
Douglas Gregora868bbd2009-04-21 22:25:48 +00002635/// \brief Retrieve the identifier table associated with the
2636/// preprocessor.
2637IdentifierTable &PCHReader::getIdentifierTable() {
Argyrios Kyrtzidis366985d2009-06-19 00:03:23 +00002638 assert(PP && "Forgot to set Preprocessor ?");
2639 return PP->getIdentifierTable();
Douglas Gregora868bbd2009-04-21 22:25:48 +00002640}
2641
Douglas Gregora9af1d12009-04-17 00:04:06 +00002642/// \brief Record that the given ID maps to the given switch-case
2643/// statement.
2644void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
2645 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
2646 SwitchCaseStmts[ID] = SC;
2647}
2648
2649/// \brief Retrieve the switch-case statement with the given ID.
2650SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
2651 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
2652 return SwitchCaseStmts[ID];
2653}
Douglas Gregor6cc68a42009-04-17 18:18:49 +00002654
2655/// \brief Record that the given label statement has been
2656/// deserialized and has the given ID.
2657void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
Mike Stump11289f42009-09-09 15:08:12 +00002658 assert(LabelStmts.find(ID) == LabelStmts.end() &&
Douglas Gregor6cc68a42009-04-17 18:18:49 +00002659 "Deserialized label twice");
2660 LabelStmts[ID] = S;
2661
2662 // If we've already seen any goto statements that point to this
2663 // label, resolve them now.
2664 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
2665 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
2666 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
2667 Goto->second->setLabel(S);
2668 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor779d8652009-04-17 18:58:21 +00002669
2670 // If we've already seen any address-label statements that point to
2671 // this label, resolve them now.
2672 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
Mike Stump11289f42009-09-09 15:08:12 +00002673 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
Douglas Gregor779d8652009-04-17 18:58:21 +00002674 = UnresolvedAddrLabelExprs.equal_range(ID);
Mike Stump11289f42009-09-09 15:08:12 +00002675 for (AddrLabelIter AddrLabel = AddrLabels.first;
Douglas Gregor779d8652009-04-17 18:58:21 +00002676 AddrLabel != AddrLabels.second; ++AddrLabel)
2677 AddrLabel->second->setLabel(S);
2678 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor6cc68a42009-04-17 18:18:49 +00002679}
2680
2681/// \brief Set the label of the given statement to the label
2682/// identified by ID.
2683///
2684/// Depending on the order in which the label and other statements
2685/// referencing that label occur, this operation may complete
2686/// immediately (updating the statement) or it may queue the
2687/// statement to be back-patched later.
2688void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
2689 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2690 if (Label != LabelStmts.end()) {
2691 // We've already seen this label, so set the label of the goto and
2692 // we're done.
2693 S->setLabel(Label->second);
2694 } else {
2695 // We haven't seen this label yet, so add this goto to the set of
2696 // unresolved goto statements.
2697 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2698 }
2699}
Douglas Gregor779d8652009-04-17 18:58:21 +00002700
2701/// \brief Set the label of the given expression to the label
2702/// identified by ID.
2703///
2704/// Depending on the order in which the label and other statements
2705/// referencing that label occur, this operation may complete
2706/// immediately (updating the statement) or it may queue the
2707/// statement to be back-patched later.
2708void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2709 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2710 if (Label != LabelStmts.end()) {
2711 // We've already seen this label, so set the label of the
2712 // label-address expression and we're done.
2713 S->setLabel(Label->second);
2714 } else {
2715 // We haven't seen this label yet, so add this label-address
2716 // expression to the set of unresolved label-address expressions.
2717 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2718 }
2719}
Douglas Gregor1342e842009-07-06 18:54:52 +00002720
2721
Mike Stump11289f42009-09-09 15:08:12 +00002722PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
Douglas Gregor1342e842009-07-06 18:54:52 +00002723 : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
2724 Reader.CurrentlyLoadingTypeOrDecl = this;
2725}
2726
2727PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
2728 if (!Parent) {
2729 // If any identifiers with corresponding top-level declarations have
2730 // been loaded, load those declarations now.
2731 while (!Reader.PendingIdentifierInfos.empty()) {
2732 Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
2733 Reader.PendingIdentifierInfos.front().DeclIDs,
2734 true);
2735 Reader.PendingIdentifierInfos.pop_front();
2736 }
2737 }
2738
Mike Stump11289f42009-09-09 15:08:12 +00002739 Reader.CurrentlyLoadingTypeOrDecl = Parent;
Douglas Gregor1342e842009-07-06 18:54:52 +00002740}