blob: 936382482c9a629802c3259355830d90c83bb0cf [file] [log] [blame]
Douglas Gregor2cf26342009-04-09 22:27:44 +00001//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the PCHReader class, which reads a precompiled header.
11//
12//===----------------------------------------------------------------------===//
Chris Lattner4c6f9522009-04-27 05:14:47 +000013
Douglas Gregor2cf26342009-04-09 22:27:44 +000014#include "clang/Frontend/PCHReader.h"
Douglas Gregor0a0428e2009-04-10 20:39:37 +000015#include "clang/Frontend/FrontendDiagnostic.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000016#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregorfdd01722009-04-14 00:24:19 +000017#include "clang/AST/ASTConsumer.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000018#include "clang/AST/ASTContext.h"
Douglas Gregor0b748912009-04-14 21:18:50 +000019#include "clang/AST/Expr.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000020#include "clang/AST/Type.h"
John McCalla1ee0c52009-10-16 21:56:05 +000021#include "clang/AST/TypeLocVisitor.h"
Chris Lattner42d42b52009-04-10 21:41:48 +000022#include "clang/Lex/MacroInfo.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000023#include "clang/Lex/Preprocessor.h"
Steve Naroff83d63c72009-04-24 20:03:17 +000024#include "clang/Lex/HeaderSearch.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000025#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000026#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000027#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000028#include "clang/Basic/FileManager.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000029#include "clang/Basic/TargetInfo.h"
Douglas Gregor445e23e2009-10-05 21:07:28 +000030#include "clang/Basic/Version.h"
Daniel Dunbar2596e422009-10-17 23:52:28 +000031#include "llvm/ADT/StringExtras.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000032#include "llvm/Bitcode/BitstreamReader.h"
33#include "llvm/Support/Compiler.h"
34#include "llvm/Support/MemoryBuffer.h"
John McCall833ca992009-10-29 08:12:44 +000035#include "llvm/Support/ErrorHandling.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000036#include <algorithm>
Douglas Gregore721f952009-04-28 18:58:38 +000037#include <iterator>
Douglas Gregor2cf26342009-04-09 22:27:44 +000038#include <cstdio>
Douglas Gregor4fed3f42009-04-27 18:38:38 +000039#include <sys/stat.h>
Douglas Gregor2cf26342009-04-09 22:27:44 +000040using namespace clang;
41
42//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis11e51102009-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 Stump1eb44332009-09-09 15:08:12 +000076 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000077 diag::warn_pch_lax_vector_conversions);
Nate Begeman69cfb9b2009-06-25 22:57:40 +000078 PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
Argyrios Kyrtzidis11e51102009-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 Stump1eb44332009-09-09 15:08:12 +000083 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000084 diag::warn_pch_thread_safe_statics);
Daniel Dunbar5345c392009-09-03 04:54:28 +000085 PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads);
Argyrios Kyrtzidis11e51102009-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 Stump1eb44332009-09-09 15:08:12 +000090 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
Argyrios Kyrtzidis11e51102009-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 Thompsona6fda122009-11-05 20:14:16 +0000107 PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000108 if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000109 Reader.Diag(diag::warn_pch_gc_mode)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000110 << LangOpts.getGCMode() << PPLangOpts.getGCMode();
111 return true;
112 }
113 PARSE_LANGOPT_BENIGN(getVisibilityMode());
Daniel Dunbarab8e2812009-09-21 04:16:19 +0000114 PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(),
115 diag::warn_pch_stack_protector);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000116 PARSE_LANGOPT_BENIGN(InstantiationDepth);
Nate Begeman69cfb9b2009-06-25 22:57:40 +0000117 PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
Daniel Dunbarab8e2812009-09-21 04:16:19 +0000118 PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000119#undef PARSE_LANGOPT_IRRELEVANT
120#undef PARSE_LANGOPT_BENIGN
121
122 return false;
123}
124
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000125bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
126 if (Triple == PP.getTargetInfo().getTriple().str())
127 return false;
128
129 Reader.Diag(diag::warn_pch_target_triple)
130 << Triple << PP.getTargetInfo().getTriple().str();
131 return true;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000132}
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
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000141static std::vector<llvm::StringRef> splitLines(llvm::StringRef Str,
142 bool KeepEmptyLines = false) {
143 std::vector<llvm::StringRef> Lines;
144
145 while (!Str.empty()) {
146 std::pair<llvm::StringRef, llvm::StringRef> split = Str.split('\n');
147
148 if (KeepEmptyLines || !split.first.empty())
149 Lines.push_back(split.first);
150
151 Str = split.second;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000152 }
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000153
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000154 return Lines;
155}
156
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000157bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000158 FileID PCHBufferID,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000159 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000160 std::string &SuggestedPredefines) {
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000161 // We are in the context of an implicit include, so the predefines buffer
162 // will have a #include entry for the PCH file itself. Find it and skip over
163 // it in the checking below.
164 llvm::SmallString<256> PCHInclude;
165 PCHInclude += "#include \"";
166 PCHInclude += OriginalFileName;
167 PCHInclude += "\"\n";
168 std::pair<llvm::StringRef,llvm::StringRef> Split =
169 llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
170 llvm::StringRef Left = Split.first, Right = Split.second;
171 assert(Left != PP.getPredefines() && "Missing PCH include entry!");
172
173 // If the predefines is equal to the joined left and right halves, we're done!
174 if (Left.size() + Right.size() == PCHPredef.size() &&
175 PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000176 return false;
177
178 SourceManager &SourceMgr = PP.getSourceManager();
Mike Stump1eb44332009-09-09 15:08:12 +0000179
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000180 // The predefines buffers are different. Determine what the differences are,
181 // and whether they require us to reject the PCH file.
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000182 std::vector<llvm::StringRef> PCHLines = splitLines(PCHPredef);
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000183 std::vector<llvm::StringRef> CmdLineLines = splitLines(Left);
184 std::vector<llvm::StringRef> CmdLineLinesRight = splitLines(Right);
185 CmdLineLines.insert(CmdLineLines.end(),
186 CmdLineLinesRight.begin(), CmdLineLinesRight.end());
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000187
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000188 // Sort both sets of predefined buffer lines, since we allow some extra
189 // definitions and they may appear at any point in the output.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000190 std::sort(CmdLineLines.begin(), CmdLineLines.end());
191 std::sort(PCHLines.begin(), PCHLines.end());
192
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000193 // Determine which predefines that were used to build the PCH file are missing
194 // from the command line.
195 std::vector<llvm::StringRef> MissingPredefines;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000196 std::set_difference(PCHLines.begin(), PCHLines.end(),
197 CmdLineLines.begin(), CmdLineLines.end(),
198 std::back_inserter(MissingPredefines));
199
200 bool MissingDefines = false;
201 bool ConflictingDefines = false;
202 for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000203 llvm::StringRef Missing = MissingPredefines[I];
204 if (!Missing.startswith("#define ")) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000205 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
206 return true;
207 }
Mike Stump1eb44332009-09-09 15:08:12 +0000208
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000209 // This is a macro definition. Determine the name of the macro we're
210 // defining.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000211 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump1eb44332009-09-09 15:08:12 +0000212 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000213 = Missing.find_first_of("( \n\r", StartOfMacroName);
214 assert(EndOfMacroName != std::string::npos &&
215 "Couldn't find the end of the macro name");
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000216 llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000217
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000218 // Determine whether this macro was given a different definition on the
219 // command line.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000220 std::string MacroDefStart = "#define " + MacroName.str();
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000221 std::string::size_type MacroDefLen = MacroDefStart.size();
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000222 std::vector<llvm::StringRef>::iterator ConflictPos
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000223 = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
224 MacroDefStart);
225 for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000226 if (!ConflictPos->startswith(MacroDefStart)) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000227 // Different macro; we're done.
228 ConflictPos = CmdLineLines.end();
Mike Stump1eb44332009-09-09 15:08:12 +0000229 break;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000230 }
Mike Stump1eb44332009-09-09 15:08:12 +0000231
232 assert(ConflictPos->size() > MacroDefLen &&
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000233 "Invalid #define in predefines buffer?");
Mike Stump1eb44332009-09-09 15:08:12 +0000234 if ((*ConflictPos)[MacroDefLen] != ' ' &&
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000235 (*ConflictPos)[MacroDefLen] != '(')
236 continue; // Longer macro name; keep trying.
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000238 // We found a conflicting macro definition.
239 break;
240 }
Mike Stump1eb44332009-09-09 15:08:12 +0000241
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000242 if (ConflictPos != CmdLineLines.end()) {
243 Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
244 << MacroName;
245
246 // Show the definition of this macro within the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000247 llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
248 assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
249 SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
250 .getFileLocWithOffset(Offset);
251 Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000252
253 ConflictingDefines = true;
254 continue;
255 }
Mike Stump1eb44332009-09-09 15:08:12 +0000256
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000257 // If the macro doesn't conflict, then we'll just pick up the macro
258 // definition from the PCH file. Warn the user that they made a mistake.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000259 if (ConflictingDefines)
260 continue; // Don't complain if there are already conflicting defs
Mike Stump1eb44332009-09-09 15:08:12 +0000261
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000262 if (!MissingDefines) {
263 Reader.Diag(diag::warn_cmdline_missing_macro_defs);
264 MissingDefines = true;
265 }
266
267 // Show the definition of this macro within the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000268 llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
269 assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
270 SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000271 .getFileLocWithOffset(Offset);
272 Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
273 }
Mike Stump1eb44332009-09-09 15:08:12 +0000274
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000275 if (ConflictingDefines)
276 return true;
Mike Stump1eb44332009-09-09 15:08:12 +0000277
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000278 // Determine what predefines were introduced based on command-line
279 // parameters that were not present when building the PCH
280 // file. Extra #defines are okay, so long as the identifiers being
281 // defined were not used within the precompiled header.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000282 std::vector<llvm::StringRef> ExtraPredefines;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000283 std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
284 PCHLines.begin(), PCHLines.end(),
Mike Stump1eb44332009-09-09 15:08:12 +0000285 std::back_inserter(ExtraPredefines));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000286 for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000287 llvm::StringRef &Extra = ExtraPredefines[I];
288 if (!Extra.startswith("#define ")) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000289 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
290 return true;
291 }
292
293 // This is an extra macro definition. Determine the name of the
294 // macro we're defining.
295 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump1eb44332009-09-09 15:08:12 +0000296 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000297 = Extra.find_first_of("( \n\r", StartOfMacroName);
298 assert(EndOfMacroName != std::string::npos &&
299 "Couldn't find the end of the macro name");
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000300 llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000301
302 // Check whether this name was used somewhere in the PCH file. If
303 // so, defining it as a macro could change behavior, so we reject
304 // the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000305 if (IdentifierInfo *II = Reader.get(MacroName)) {
Daniel Dunbar4fda42e2009-11-11 00:52:00 +0000306 Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000307 return true;
308 }
309
310 // Add this definition to the suggested predefines buffer.
311 SuggestedPredefines += Extra;
312 SuggestedPredefines += '\n';
313 }
314
315 // If we get here, it's because the predefines buffer had compatible
316 // contents. Accept the PCH file.
317 return false;
318}
319
320void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
321 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
322}
323
324void PCHValidator::ReadCounter(unsigned Value) {
325 PP.setCounterValue(Value);
326}
327
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000328//===----------------------------------------------------------------------===//
Douglas Gregor668c1a42009-04-21 22:25:48 +0000329// PCH reader implementation
330//===----------------------------------------------------------------------===//
331
Mike Stump1eb44332009-09-09 15:08:12 +0000332PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
333 const char *isysroot)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000334 : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
335 FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
Douglas Gregor52e71082009-10-16 18:18:30 +0000336 SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000337 IdentifierTableData(0), IdentifierLookupTable(0),
338 IdentifierOffsets(0),
339 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
340 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000341 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump1eb44332009-09-09 15:08:12 +0000342 NumStatHits(0), NumStatMisses(0),
343 NumSLocEntriesRead(0), NumStatementsRead(0),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000344 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000345 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump1eb44332009-09-09 15:08:12 +0000346 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000347 RelocatablePCH = false;
348}
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000349
350PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
Mike Stump1eb44332009-09-09 15:08:12 +0000351 Diagnostic &Diags, const char *isysroot)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000352 : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
Douglas Gregor52e71082009-10-16 18:18:30 +0000353 SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +0000354 IdentifierTableData(0), IdentifierLookupTable(0),
355 IdentifierOffsets(0),
356 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
357 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000358 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump1eb44332009-09-09 15:08:12 +0000359 NumStatHits(0), NumStatMisses(0),
360 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000361 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregord89275b2009-07-06 18:54:52 +0000362 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump1eb44332009-09-09 15:08:12 +0000363 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000364 RelocatablePCH = false;
365}
Chris Lattner4c6f9522009-04-27 05:14:47 +0000366
367PCHReader::~PCHReader() {}
368
Chris Lattnerda930612009-04-27 05:58:23 +0000369Expr *PCHReader::ReadDeclExpr() {
370 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
371}
372
373Expr *PCHReader::ReadTypeExpr() {
Douglas Gregor61d60ee2009-10-17 00:13:19 +0000374 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
Chris Lattner4c6f9522009-04-27 05:14:47 +0000375}
376
377
Douglas Gregor668c1a42009-04-21 22:25:48 +0000378namespace {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000379class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
380 PCHReader &Reader;
381
382public:
383 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
384
385 typedef Selector external_key_type;
386 typedef external_key_type internal_key_type;
387
388 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
Mike Stump1eb44332009-09-09 15:08:12 +0000389
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000390 static bool EqualKey(const internal_key_type& a,
391 const internal_key_type& b) {
392 return a == b;
393 }
Mike Stump1eb44332009-09-09 15:08:12 +0000394
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000395 static unsigned ComputeHash(Selector Sel) {
396 unsigned N = Sel.getNumArgs();
397 if (N == 0)
398 ++N;
399 unsigned R = 5381;
400 for (unsigned I = 0; I != N; ++I)
401 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
Daniel Dunbar2596e422009-10-17 23:52:28 +0000402 R = llvm::HashString(II->getName(), R);
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000403 return R;
404 }
Mike Stump1eb44332009-09-09 15:08:12 +0000405
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000406 // This hopefully will just get inlined and removed by the optimizer.
407 static const internal_key_type&
408 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump1eb44332009-09-09 15:08:12 +0000409
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000410 static std::pair<unsigned, unsigned>
411 ReadKeyDataLength(const unsigned char*& d) {
412 using namespace clang::io;
413 unsigned KeyLen = ReadUnalignedLE16(d);
414 unsigned DataLen = ReadUnalignedLE16(d);
415 return std::make_pair(KeyLen, DataLen);
416 }
Mike Stump1eb44332009-09-09 15:08:12 +0000417
Douglas Gregor83941df2009-04-25 17:48:32 +0000418 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000419 using namespace clang::io;
Chris Lattnerd1d64a02009-04-27 21:45:14 +0000420 SelectorTable &SelTable = Reader.getContext()->Selectors;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000421 unsigned N = ReadUnalignedLE16(d);
Mike Stump1eb44332009-09-09 15:08:12 +0000422 IdentifierInfo *FirstII
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000423 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
424 if (N == 0)
425 return SelTable.getNullarySelector(FirstII);
426 else if (N == 1)
427 return SelTable.getUnarySelector(FirstII);
428
429 llvm::SmallVector<IdentifierInfo *, 16> Args;
430 Args.push_back(FirstII);
431 for (unsigned I = 1; I != N; ++I)
432 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
433
Douglas Gregor75fdb232009-05-22 22:45:36 +0000434 return SelTable.getSelector(N, Args.data());
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000435 }
Mike Stump1eb44332009-09-09 15:08:12 +0000436
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000437 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
438 using namespace clang::io;
439 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
440 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
441
442 data_type Result;
443
444 // Load instance methods
445 ObjCMethodList *Prev = 0;
446 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000447 ObjCMethodDecl *Method
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000448 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
449 if (!Result.first.Method) {
450 // This is the first method, which is the easy case.
451 Result.first.Method = Method;
452 Prev = &Result.first;
453 continue;
454 }
455
456 Prev->Next = new ObjCMethodList(Method, 0);
457 Prev = Prev->Next;
458 }
459
460 // Load factory methods
461 Prev = 0;
462 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000463 ObjCMethodDecl *Method
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000464 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
465 if (!Result.second.Method) {
466 // This is the first method, which is the easy case.
467 Result.second.Method = Method;
468 Prev = &Result.second;
469 continue;
470 }
471
472 Prev->Next = new ObjCMethodList(Method, 0);
473 Prev = Prev->Next;
474 }
475
476 return Result;
477 }
478};
Mike Stump1eb44332009-09-09 15:08:12 +0000479
480} // end anonymous namespace
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000481
482/// \brief The on-disk hash table used for the global method pool.
Mike Stump1eb44332009-09-09 15:08:12 +0000483typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000484 PCHMethodPoolLookupTable;
485
486namespace {
Douglas Gregor668c1a42009-04-21 22:25:48 +0000487class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
488 PCHReader &Reader;
489
490 // If we know the IdentifierInfo in advance, it is here and we will
491 // not build a new one. Used when deserializing information about an
492 // identifier that was constructed before the PCH file was read.
493 IdentifierInfo *KnownII;
494
495public:
496 typedef IdentifierInfo * data_type;
497
498 typedef const std::pair<const char*, unsigned> external_key_type;
499
500 typedef external_key_type internal_key_type;
501
Mike Stump1eb44332009-09-09 15:08:12 +0000502 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
Douglas Gregor668c1a42009-04-21 22:25:48 +0000503 : Reader(Reader), KnownII(II) { }
Mike Stump1eb44332009-09-09 15:08:12 +0000504
Douglas Gregor668c1a42009-04-21 22:25:48 +0000505 static bool EqualKey(const internal_key_type& a,
506 const internal_key_type& b) {
507 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
508 : false;
509 }
Mike Stump1eb44332009-09-09 15:08:12 +0000510
Douglas Gregor668c1a42009-04-21 22:25:48 +0000511 static unsigned ComputeHash(const internal_key_type& a) {
Daniel Dunbar2596e422009-10-17 23:52:28 +0000512 return llvm::HashString(llvm::StringRef(a.first, a.second));
Douglas Gregor668c1a42009-04-21 22:25:48 +0000513 }
Mike Stump1eb44332009-09-09 15:08:12 +0000514
Douglas Gregor668c1a42009-04-21 22:25:48 +0000515 // This hopefully will just get inlined and removed by the optimizer.
516 static const internal_key_type&
517 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump1eb44332009-09-09 15:08:12 +0000518
Douglas Gregor668c1a42009-04-21 22:25:48 +0000519 static std::pair<unsigned, unsigned>
520 ReadKeyDataLength(const unsigned char*& d) {
521 using namespace clang::io;
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000522 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregord6595a42009-04-25 21:04:17 +0000523 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000524 return std::make_pair(KeyLen, DataLen);
525 }
Mike Stump1eb44332009-09-09 15:08:12 +0000526
Douglas Gregor668c1a42009-04-21 22:25:48 +0000527 static std::pair<const char*, unsigned>
528 ReadKey(const unsigned char* d, unsigned n) {
529 assert(n >= 2 && d[n-1] == '\0');
530 return std::make_pair((const char*) d, n-1);
531 }
Mike Stump1eb44332009-09-09 15:08:12 +0000532
533 IdentifierInfo *ReadData(const internal_key_type& k,
Douglas Gregor668c1a42009-04-21 22:25:48 +0000534 const unsigned char* d,
535 unsigned DataLen) {
536 using namespace clang::io;
Douglas Gregora92193e2009-04-28 21:18:29 +0000537 pch::IdentID ID = ReadUnalignedLE32(d);
538 bool IsInteresting = ID & 0x01;
539
540 // Wipe out the "is interesting" bit.
541 ID = ID >> 1;
542
543 if (!IsInteresting) {
544 // For unintersting identifiers, just build the IdentifierInfo
545 // and associate it with the persistent ID.
546 IdentifierInfo *II = KnownII;
547 if (!II)
548 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
549 k.first, k.first + k.second);
550 Reader.SetIdentifierInfo(ID, II);
551 return II;
552 }
553
Douglas Gregor5998da52009-04-28 21:32:13 +0000554 unsigned Bits = ReadUnalignedLE16(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000555 bool CPlusPlusOperatorKeyword = Bits & 0x01;
556 Bits >>= 1;
557 bool Poisoned = Bits & 0x01;
558 Bits >>= 1;
559 bool ExtensionToken = Bits & 0x01;
560 Bits >>= 1;
561 bool hasMacroDefinition = Bits & 0x01;
562 Bits >>= 1;
563 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
564 Bits >>= 10;
Mike Stump1eb44332009-09-09 15:08:12 +0000565
Douglas Gregor2deaea32009-04-22 18:49:13 +0000566 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregor5998da52009-04-28 21:32:13 +0000567 DataLen -= 6;
Douglas Gregor668c1a42009-04-21 22:25:48 +0000568
569 // Build the IdentifierInfo itself and link the identifier ID with
570 // the new IdentifierInfo.
571 IdentifierInfo *II = KnownII;
572 if (!II)
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000573 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
574 k.first, k.first + k.second);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000575 Reader.SetIdentifierInfo(ID, II);
576
Douglas Gregor2deaea32009-04-22 18:49:13 +0000577 // Set or check the various bits in the IdentifierInfo structure.
578 // FIXME: Load token IDs lazily, too?
Douglas Gregor2deaea32009-04-22 18:49:13 +0000579 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
Mike Stump1eb44332009-09-09 15:08:12 +0000580 assert(II->isExtensionToken() == ExtensionToken &&
Douglas Gregor2deaea32009-04-22 18:49:13 +0000581 "Incorrect extension token flag");
582 (void)ExtensionToken;
583 II->setIsPoisoned(Poisoned);
584 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
585 "Incorrect C++ operator keyword flag");
586 (void)CPlusPlusOperatorKeyword;
587
Douglas Gregor37e26842009-04-21 23:56:24 +0000588 // If this identifier is a macro, deserialize the macro
589 // definition.
590 if (hasMacroDefinition) {
Douglas Gregor5998da52009-04-28 21:32:13 +0000591 uint32_t Offset = ReadUnalignedLE32(d);
Douglas Gregor37e26842009-04-21 23:56:24 +0000592 Reader.ReadMacroRecord(Offset);
Douglas Gregor5998da52009-04-28 21:32:13 +0000593 DataLen -= 4;
Douglas Gregor37e26842009-04-21 23:56:24 +0000594 }
Douglas Gregor668c1a42009-04-21 22:25:48 +0000595
596 // Read all of the declarations visible at global scope with this
597 // name.
Chris Lattner6bf690f2009-04-27 22:17:41 +0000598 if (Reader.getContext() == 0) return II;
Douglas Gregord89275b2009-07-06 18:54:52 +0000599 if (DataLen > 0) {
600 llvm::SmallVector<uint32_t, 4> DeclIDs;
601 for (; DataLen > 0; DataLen -= 4)
602 DeclIDs.push_back(ReadUnalignedLE32(d));
603 Reader.SetGloballyVisibleDecls(II, DeclIDs);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000604 }
Mike Stump1eb44332009-09-09 15:08:12 +0000605
Douglas Gregor668c1a42009-04-21 22:25:48 +0000606 return II;
607 }
608};
Mike Stump1eb44332009-09-09 15:08:12 +0000609
610} // end anonymous namespace
Douglas Gregor668c1a42009-04-21 22:25:48 +0000611
612/// \brief The on-disk hash table used to contain information about
613/// all of the identifiers in the program.
Mike Stump1eb44332009-09-09 15:08:12 +0000614typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
Douglas Gregor668c1a42009-04-21 22:25:48 +0000615 PCHIdentifierLookupTable;
616
Douglas Gregora02b1472009-04-28 21:53:25 +0000617bool PCHReader::Error(const char *Msg) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000618 unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
619 Diag(DiagID);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000620 return true;
621}
622
Douglas Gregore1d918e2009-04-10 23:10:45 +0000623/// \brief Check the contents of the predefines buffer against the
624/// contents of the predefines buffer used to build the PCH file.
625///
626/// The contents of the two predefines buffers should be the same. If
627/// not, then some command-line option changed the preprocessor state
628/// and we must reject the PCH file.
629///
630/// \param PCHPredef The start of the predefines buffer in the PCH
631/// file.
632///
633/// \param PCHPredefLen The length of the predefines buffer in the PCH
634/// file.
635///
636/// \param PCHBufferID The FileID for the PCH predefines buffer.
637///
638/// \returns true if there was a mismatch (in which case the PCH file
639/// should be ignored), or false otherwise.
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000640bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
Douglas Gregore1d918e2009-04-10 23:10:45 +0000641 FileID PCHBufferID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000642 if (Listener)
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000643 return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000644 ActualOriginalFileName,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000645 SuggestedPredefines);
Douglas Gregore721f952009-04-28 18:58:38 +0000646 return false;
Douglas Gregore1d918e2009-04-10 23:10:45 +0000647}
648
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000649//===----------------------------------------------------------------------===//
650// Source Manager Deserialization
651//===----------------------------------------------------------------------===//
652
Douglas Gregorbd945002009-04-13 16:31:14 +0000653/// \brief Read the line table in the source manager block.
654/// \returns true if ther was an error.
Douglas Gregore650c8c2009-07-07 00:12:59 +0000655bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000656 unsigned Idx = 0;
657 LineTableInfo &LineTable = SourceMgr.getLineTable();
658
659 // Parse the file names
Douglas Gregorff0a9872009-04-13 17:12:42 +0000660 std::map<int, int> FileIDs;
661 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000662 // Extract the file name
663 unsigned FilenameLen = Record[Idx++];
664 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
665 Idx += FilenameLen;
Douglas Gregore650c8c2009-07-07 00:12:59 +0000666 MaybeAddSystemRootToFilename(Filename);
Mike Stump1eb44332009-09-09 15:08:12 +0000667 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
Douglas Gregorff0a9872009-04-13 17:12:42 +0000668 Filename.size());
Douglas Gregorbd945002009-04-13 16:31:14 +0000669 }
670
671 // Parse the line entries
672 std::vector<LineEntry> Entries;
673 while (Idx < Record.size()) {
Douglas Gregorff0a9872009-04-13 17:12:42 +0000674 int FID = FileIDs[Record[Idx++]];
Douglas Gregorbd945002009-04-13 16:31:14 +0000675
676 // Extract the line entries
677 unsigned NumEntries = Record[Idx++];
678 Entries.clear();
679 Entries.reserve(NumEntries);
680 for (unsigned I = 0; I != NumEntries; ++I) {
681 unsigned FileOffset = Record[Idx++];
682 unsigned LineNo = Record[Idx++];
683 int FilenameID = Record[Idx++];
Mike Stump1eb44332009-09-09 15:08:12 +0000684 SrcMgr::CharacteristicKind FileKind
Douglas Gregorbd945002009-04-13 16:31:14 +0000685 = (SrcMgr::CharacteristicKind)Record[Idx++];
686 unsigned IncludeOffset = Record[Idx++];
687 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
688 FileKind, IncludeOffset));
689 }
690 LineTable.AddEntry(FID, Entries);
691 }
692
693 return false;
694}
695
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000696namespace {
697
698class VISIBILITY_HIDDEN PCHStatData {
699public:
700 const bool hasStat;
701 const ino_t ino;
702 const dev_t dev;
703 const mode_t mode;
704 const time_t mtime;
705 const off_t size;
Mike Stump1eb44332009-09-09 15:08:12 +0000706
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000707 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
Mike Stump1eb44332009-09-09 15:08:12 +0000708 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
709
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000710 PCHStatData()
711 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
712};
713
714class VISIBILITY_HIDDEN PCHStatLookupTrait {
715 public:
716 typedef const char *external_key_type;
717 typedef const char *internal_key_type;
718
719 typedef PCHStatData data_type;
720
721 static unsigned ComputeHash(const char *path) {
Daniel Dunbar2596e422009-10-17 23:52:28 +0000722 return llvm::HashString(path);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000723 }
724
725 static internal_key_type GetInternalKey(const char *path) { return path; }
726
727 static bool EqualKey(internal_key_type a, internal_key_type b) {
728 return strcmp(a, b) == 0;
729 }
730
731 static std::pair<unsigned, unsigned>
732 ReadKeyDataLength(const unsigned char*& d) {
733 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
734 unsigned DataLen = (unsigned) *d++;
735 return std::make_pair(KeyLen + 1, DataLen);
736 }
737
738 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
739 return (const char *)d;
740 }
741
742 static data_type ReadData(const internal_key_type, const unsigned char *d,
743 unsigned /*DataLen*/) {
744 using namespace clang::io;
745
746 if (*d++ == 1)
747 return data_type();
748
749 ino_t ino = (ino_t) ReadUnalignedLE32(d);
750 dev_t dev = (dev_t) ReadUnalignedLE32(d);
751 mode_t mode = (mode_t) ReadUnalignedLE16(d);
Mike Stump1eb44332009-09-09 15:08:12 +0000752 time_t mtime = (time_t) ReadUnalignedLE64(d);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000753 off_t size = (off_t) ReadUnalignedLE64(d);
754 return data_type(ino, dev, mode, mtime, size);
755 }
756};
757
758/// \brief stat() cache for precompiled headers.
759///
760/// This cache is very similar to the stat cache used by pretokenized
761/// headers.
762class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
763 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
764 CacheTy *Cache;
765
766 unsigned &NumStatHits, &NumStatMisses;
Mike Stump1eb44332009-09-09 15:08:12 +0000767public:
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000768 PCHStatCache(const unsigned char *Buckets,
769 const unsigned char *Base,
770 unsigned &NumStatHits,
Mike Stump1eb44332009-09-09 15:08:12 +0000771 unsigned &NumStatMisses)
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000772 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
773 Cache = CacheTy::Create(Buckets, Base);
774 }
775
776 ~PCHStatCache() { delete Cache; }
Mike Stump1eb44332009-09-09 15:08:12 +0000777
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000778 int stat(const char *path, struct stat *buf) {
779 // Do the lookup for the file's data in the PCH file.
780 CacheTy::iterator I = Cache->find(path);
781
782 // If we don't get a hit in the PCH file just forward to 'stat'.
783 if (I == Cache->end()) {
784 ++NumStatMisses;
Douglas Gregor52e71082009-10-16 18:18:30 +0000785 return StatSysCallCache::stat(path, buf);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000786 }
Mike Stump1eb44332009-09-09 15:08:12 +0000787
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000788 ++NumStatHits;
789 PCHStatData Data = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000790
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000791 if (!Data.hasStat)
792 return 1;
793
794 buf->st_ino = Data.ino;
795 buf->st_dev = Data.dev;
796 buf->st_mtime = Data.mtime;
797 buf->st_mode = Data.mode;
798 buf->st_size = Data.size;
799 return 0;
800 }
801};
802} // end anonymous namespace
803
804
Douglas Gregor14f79002009-04-10 03:52:48 +0000805/// \brief Read the source manager block
Douglas Gregore1d918e2009-04-10 23:10:45 +0000806PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregor14f79002009-04-10 03:52:48 +0000807 using namespace SrcMgr;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000808
809 // Set the source-location entry cursor to the current position in
810 // the stream. This cursor will be used to read the contents of the
811 // source manager block initially, and then lazily read
812 // source-location entries as needed.
813 SLocEntryCursor = Stream;
814
815 // The stream itself is going to skip over the source manager block.
816 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000817 Error("malformed block record in PCH file");
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000818 return Failure;
819 }
820
821 // Enter the source manager block.
822 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000823 Error("malformed source manager block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000824 return Failure;
825 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000826
Douglas Gregor14f79002009-04-10 03:52:48 +0000827 RecordData Record;
828 while (true) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000829 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregor14f79002009-04-10 03:52:48 +0000830 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000831 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000832 Error("error at end of Source Manager block in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000833 return Failure;
834 }
Douglas Gregore1d918e2009-04-10 23:10:45 +0000835 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000836 }
Mike Stump1eb44332009-09-09 15:08:12 +0000837
Douglas Gregor14f79002009-04-10 03:52:48 +0000838 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
839 // No known subblocks, always skip them.
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000840 SLocEntryCursor.ReadSubBlockID();
841 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000842 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000843 return Failure;
844 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000845 continue;
846 }
Mike Stump1eb44332009-09-09 15:08:12 +0000847
Douglas Gregor14f79002009-04-10 03:52:48 +0000848 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000849 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregor14f79002009-04-10 03:52:48 +0000850 continue;
851 }
Mike Stump1eb44332009-09-09 15:08:12 +0000852
Douglas Gregor14f79002009-04-10 03:52:48 +0000853 // Read a record.
854 const char *BlobStart;
855 unsigned BlobLen;
856 Record.clear();
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000857 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregor14f79002009-04-10 03:52:48 +0000858 default: // Default behavior: ignore.
859 break;
860
Chris Lattner2c78b872009-04-14 23:22:57 +0000861 case pch::SM_LINE_TABLE:
Douglas Gregore650c8c2009-07-07 00:12:59 +0000862 if (ParseLineTable(Record))
Douglas Gregorbd945002009-04-13 16:31:14 +0000863 return Failure;
Chris Lattner2c78b872009-04-14 23:22:57 +0000864 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000865
866 case pch::SM_HEADER_FILE_INFO: {
867 HeaderFileInfo HFI;
868 HFI.isImport = Record[0];
869 HFI.DirInfo = Record[1];
870 HFI.NumIncludes = Record[2];
871 HFI.ControllingMacroID = Record[3];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000872 if (Listener)
873 Listener->ReadHeaderFileInfo(HFI);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000874 break;
875 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000876
877 case pch::SM_SLOC_FILE_ENTRY:
878 case pch::SM_SLOC_BUFFER_ENTRY:
879 case pch::SM_SLOC_INSTANTIATION_ENTRY:
880 // Once we hit one of the source location entries, we're done.
881 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000882 }
883 }
884}
885
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000886/// \brief Read in the source location entry with the given ID.
887PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
888 if (ID == 0)
889 return Success;
890
891 if (ID > TotalNumSLocEntries) {
892 Error("source location entry ID out-of-range for PCH file");
893 return Failure;
894 }
895
896 ++NumSLocEntriesRead;
897 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
898 unsigned Code = SLocEntryCursor.ReadCode();
899 if (Code == llvm::bitc::END_BLOCK ||
900 Code == llvm::bitc::ENTER_SUBBLOCK ||
901 Code == llvm::bitc::DEFINE_ABBREV) {
902 Error("incorrectly-formatted source location entry in PCH file");
903 return Failure;
904 }
905
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000906 RecordData Record;
907 const char *BlobStart;
908 unsigned BlobLen;
909 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
910 default:
911 Error("incorrectly-formatted source location entry in PCH file");
912 return Failure;
913
914 case pch::SM_SLOC_FILE_ENTRY: {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000915 std::string Filename(BlobStart, BlobStart + BlobLen);
916 MaybeAddSystemRootToFilename(Filename);
917 const FileEntry *File = FileMgr.getFile(Filename);
Chris Lattnerd3555ae2009-06-15 04:35:16 +0000918 if (File == 0) {
919 std::string ErrorStr = "could not find file '";
Douglas Gregore650c8c2009-07-07 00:12:59 +0000920 ErrorStr += Filename;
Chris Lattnerd3555ae2009-06-15 04:35:16 +0000921 ErrorStr += "' referenced by PCH file";
922 Error(ErrorStr.c_str());
923 return Failure;
924 }
Mike Stump1eb44332009-09-09 15:08:12 +0000925
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000926 FileID FID = SourceMgr.createFileID(File,
927 SourceLocation::getFromRawEncoding(Record[1]),
928 (SrcMgr::CharacteristicKind)Record[2],
929 ID, Record[0]);
930 if (Record[3])
931 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
932 .setHasLineDirectives();
933
934 break;
935 }
936
937 case pch::SM_SLOC_BUFFER_ENTRY: {
938 const char *Name = BlobStart;
939 unsigned Offset = Record[0];
940 unsigned Code = SLocEntryCursor.ReadCode();
941 Record.clear();
Mike Stump1eb44332009-09-09 15:08:12 +0000942 unsigned RecCode
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000943 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
944 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
945 (void)RecCode;
946 llvm::MemoryBuffer *Buffer
Mike Stump1eb44332009-09-09 15:08:12 +0000947 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000948 BlobStart + BlobLen - 1,
949 Name);
950 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
Mike Stump1eb44332009-09-09 15:08:12 +0000951
Douglas Gregor92b059e2009-04-28 20:33:11 +0000952 if (strcmp(Name, "<built-in>") == 0) {
953 PCHPredefinesBufferID = BufferID;
954 PCHPredefines = BlobStart;
955 PCHPredefinesLen = BlobLen - 1;
956 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000957
958 break;
959 }
960
961 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
Mike Stump1eb44332009-09-09 15:08:12 +0000962 SourceLocation SpellingLoc
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000963 = SourceLocation::getFromRawEncoding(Record[1]);
964 SourceMgr.createInstantiationLoc(SpellingLoc,
965 SourceLocation::getFromRawEncoding(Record[2]),
966 SourceLocation::getFromRawEncoding(Record[3]),
967 Record[4],
968 ID,
969 Record[0]);
970 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000971 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000972 }
973
974 return Success;
975}
976
Chris Lattner6367f6d2009-04-27 01:05:14 +0000977/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
978/// specified cursor. Read the abbreviations that are at the top of the block
979/// and then leave the cursor pointing into the block.
980bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
981 unsigned BlockID) {
982 if (Cursor.EnterSubBlock(BlockID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000983 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +0000984 return Failure;
985 }
Mike Stump1eb44332009-09-09 15:08:12 +0000986
Chris Lattner6367f6d2009-04-27 01:05:14 +0000987 while (true) {
988 unsigned Code = Cursor.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +0000989
Chris Lattner6367f6d2009-04-27 01:05:14 +0000990 // We expect all abbrevs to be at the start of the block.
991 if (Code != llvm::bitc::DEFINE_ABBREV)
992 return false;
993 Cursor.ReadAbbrevRecord();
994 }
995}
996
Douglas Gregor37e26842009-04-21 23:56:24 +0000997void PCHReader::ReadMacroRecord(uint64_t Offset) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000998 assert(PP && "Forgot to set Preprocessor ?");
Mike Stump1eb44332009-09-09 15:08:12 +0000999
Douglas Gregor37e26842009-04-21 23:56:24 +00001000 // Keep track of where we are in the stream, then jump back there
1001 // after reading this macro.
1002 SavedStreamPosition SavedPosition(Stream);
1003
1004 Stream.JumpToBit(Offset);
1005 RecordData Record;
1006 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
1007 MacroInfo *Macro = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001008
Douglas Gregor37e26842009-04-21 23:56:24 +00001009 while (true) {
1010 unsigned Code = Stream.ReadCode();
1011 switch (Code) {
1012 case llvm::bitc::END_BLOCK:
1013 return;
1014
1015 case llvm::bitc::ENTER_SUBBLOCK:
1016 // No known subblocks, always skip them.
1017 Stream.ReadSubBlockID();
1018 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001019 Error("malformed block record in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001020 return;
1021 }
1022 continue;
Mike Stump1eb44332009-09-09 15:08:12 +00001023
Douglas Gregor37e26842009-04-21 23:56:24 +00001024 case llvm::bitc::DEFINE_ABBREV:
1025 Stream.ReadAbbrevRecord();
1026 continue;
1027 default: break;
1028 }
1029
1030 // Read a record.
1031 Record.clear();
1032 pch::PreprocessorRecordTypes RecType =
1033 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
1034 switch (RecType) {
Douglas Gregor37e26842009-04-21 23:56:24 +00001035 case pch::PP_MACRO_OBJECT_LIKE:
1036 case pch::PP_MACRO_FUNCTION_LIKE: {
1037 // If we already have a macro, that means that we've hit the end
1038 // of the definition of the macro we were looking for. We're
1039 // done.
1040 if (Macro)
1041 return;
1042
1043 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
1044 if (II == 0) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001045 Error("macro must have a name in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001046 return;
1047 }
1048 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
1049 bool isUsed = Record[2];
Mike Stump1eb44332009-09-09 15:08:12 +00001050
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001051 MacroInfo *MI = PP->AllocateMacroInfo(Loc);
Douglas Gregor37e26842009-04-21 23:56:24 +00001052 MI->setIsUsed(isUsed);
Mike Stump1eb44332009-09-09 15:08:12 +00001053
Douglas Gregor37e26842009-04-21 23:56:24 +00001054 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
1055 // Decode function-like macro info.
1056 bool isC99VarArgs = Record[3];
1057 bool isGNUVarArgs = Record[4];
1058 MacroArgs.clear();
1059 unsigned NumArgs = Record[5];
1060 for (unsigned i = 0; i != NumArgs; ++i)
1061 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
1062
1063 // Install function-like macro info.
1064 MI->setIsFunctionLike();
1065 if (isC99VarArgs) MI->setIsC99Varargs();
1066 if (isGNUVarArgs) MI->setIsGNUVarargs();
Douglas Gregor75fdb232009-05-22 22:45:36 +00001067 MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001068 PP->getPreprocessorAllocator());
Douglas Gregor37e26842009-04-21 23:56:24 +00001069 }
1070
1071 // Finally, install the macro.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001072 PP->setMacroInfo(II, MI);
Douglas Gregor37e26842009-04-21 23:56:24 +00001073
1074 // Remember that we saw this macro last so that we add the tokens that
1075 // form its body to it.
1076 Macro = MI;
1077 ++NumMacrosRead;
1078 break;
1079 }
Mike Stump1eb44332009-09-09 15:08:12 +00001080
Douglas Gregor37e26842009-04-21 23:56:24 +00001081 case pch::PP_TOKEN: {
1082 // If we see a TOKEN before a PP_MACRO_*, then the file is
1083 // erroneous, just pretend we didn't see this.
1084 if (Macro == 0) break;
Mike Stump1eb44332009-09-09 15:08:12 +00001085
Douglas Gregor37e26842009-04-21 23:56:24 +00001086 Token Tok;
1087 Tok.startToken();
1088 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
1089 Tok.setLength(Record[1]);
1090 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
1091 Tok.setIdentifierInfo(II);
1092 Tok.setKind((tok::TokenKind)Record[3]);
1093 Tok.setFlag((Token::TokenFlags)Record[4]);
1094 Macro->AddTokenToBody(Tok);
1095 break;
1096 }
Steve Naroff83d63c72009-04-24 20:03:17 +00001097 }
Douglas Gregor37e26842009-04-21 23:56:24 +00001098 }
1099}
1100
Douglas Gregore650c8c2009-07-07 00:12:59 +00001101/// \brief If we are loading a relocatable PCH file, and the filename is
1102/// not an absolute path, add the system root to the beginning of the file
1103/// name.
1104void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
1105 // If this is not a relocatable PCH file, there's nothing to do.
1106 if (!RelocatablePCH)
1107 return;
Mike Stump1eb44332009-09-09 15:08:12 +00001108
Douglas Gregore650c8c2009-07-07 00:12:59 +00001109 if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<')
1110 return;
1111
1112 std::string FIXME = Filename;
Mike Stump1eb44332009-09-09 15:08:12 +00001113
Douglas Gregore650c8c2009-07-07 00:12:59 +00001114 if (isysroot == 0) {
1115 // If no system root was given, default to '/'
1116 Filename.insert(Filename.begin(), '/');
1117 return;
1118 }
Mike Stump1eb44332009-09-09 15:08:12 +00001119
Douglas Gregore650c8c2009-07-07 00:12:59 +00001120 unsigned Length = strlen(isysroot);
1121 if (isysroot[Length - 1] != '/')
1122 Filename.insert(Filename.begin(), '/');
Mike Stump1eb44332009-09-09 15:08:12 +00001123
Douglas Gregore650c8c2009-07-07 00:12:59 +00001124 Filename.insert(Filename.begin(), isysroot, isysroot + Length);
1125}
1126
Mike Stump1eb44332009-09-09 15:08:12 +00001127PCHReader::PCHReadResult
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001128PCHReader::ReadPCHBlock() {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001129 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001130 Error("malformed block record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001131 return Failure;
1132 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001133
1134 // Read all of the records and blocks for the PCH file.
Douglas Gregor8038d512009-04-10 17:25:41 +00001135 RecordData Record;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001136 while (!Stream.AtEndOfStream()) {
1137 unsigned Code = Stream.ReadCode();
1138 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001139 if (Stream.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001140 Error("error at end of module block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001141 return Failure;
1142 }
Chris Lattner7356a312009-04-11 21:15:38 +00001143
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001144 return Success;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001145 }
1146
1147 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1148 switch (Stream.ReadSubBlockID()) {
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001149 case pch::DECLTYPES_BLOCK_ID:
Chris Lattner6367f6d2009-04-27 01:05:14 +00001150 // We lazily load the decls block, but we want to set up the
1151 // DeclsCursor cursor to point into it. Clone our current bitcode
1152 // cursor to it, enter the block and read the abbrevs in that block.
1153 // With the main cursor, we just skip over it.
1154 DeclsCursor = Stream;
1155 if (Stream.SkipBlock() || // Skip with the main cursor.
1156 // Read the abbrevs.
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001157 ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001158 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +00001159 return Failure;
1160 }
1161 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001162
Chris Lattner7356a312009-04-11 21:15:38 +00001163 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner7356a312009-04-11 21:15:38 +00001164 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001165 Error("malformed block record in PCH file");
Chris Lattner7356a312009-04-11 21:15:38 +00001166 return Failure;
1167 }
1168 break;
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001169
Douglas Gregor14f79002009-04-10 03:52:48 +00001170 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001171 switch (ReadSourceManagerBlock()) {
1172 case Success:
1173 break;
1174
1175 case Failure:
Douglas Gregora02b1472009-04-28 21:53:25 +00001176 Error("malformed source manager block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001177 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001178
1179 case IgnorePCH:
1180 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001181 }
Douglas Gregor14f79002009-04-10 03:52:48 +00001182 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001183 }
Douglas Gregor8038d512009-04-10 17:25:41 +00001184 continue;
1185 }
1186
1187 if (Code == llvm::bitc::DEFINE_ABBREV) {
1188 Stream.ReadAbbrevRecord();
1189 continue;
1190 }
1191
1192 // Read and process a record.
1193 Record.clear();
Douglas Gregor2bec0412009-04-10 21:16:55 +00001194 const char *BlobStart = 0;
1195 unsigned BlobLen = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001196 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
Douglas Gregor2bec0412009-04-10 21:16:55 +00001197 &BlobStart, &BlobLen)) {
Douglas Gregor8038d512009-04-10 17:25:41 +00001198 default: // Default behavior: ignore.
1199 break;
1200
1201 case pch::TYPE_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001202 if (!TypesLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001203 Error("duplicate TYPE_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001204 return Failure;
1205 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001206 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001207 TypesLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001208 break;
1209
1210 case pch::DECL_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001211 if (!DeclsLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001212 Error("duplicate DECL_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001213 return Failure;
1214 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001215 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001216 DeclsLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001217 break;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001218
1219 case pch::LANGUAGE_OPTIONS:
1220 if (ParseLanguageOptions(Record))
1221 return IgnorePCH;
1222 break;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001223
Douglas Gregorab41e632009-04-27 22:23:34 +00001224 case pch::METADATA: {
1225 if (Record[0] != pch::VERSION_MAJOR) {
1226 Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
1227 : diag::warn_pch_version_too_new);
1228 return IgnorePCH;
1229 }
1230
Douglas Gregore650c8c2009-07-07 00:12:59 +00001231 RelocatablePCH = Record[4];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001232 if (Listener) {
1233 std::string TargetTriple(BlobStart, BlobLen);
1234 if (Listener->ReadTargetTriple(TargetTriple))
1235 return IgnorePCH;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001236 }
1237 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001238 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001239
1240 case pch::IDENTIFIER_TABLE:
Douglas Gregor668c1a42009-04-21 22:25:48 +00001241 IdentifierTableData = BlobStart;
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001242 if (Record[0]) {
Mike Stump1eb44332009-09-09 15:08:12 +00001243 IdentifierLookupTable
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001244 = PCHIdentifierLookupTable::Create(
Douglas Gregor668c1a42009-04-21 22:25:48 +00001245 (const unsigned char *)IdentifierTableData + Record[0],
Mike Stump1eb44332009-09-09 15:08:12 +00001246 (const unsigned char *)IdentifierTableData,
Douglas Gregor668c1a42009-04-21 22:25:48 +00001247 PCHIdentifierLookupTrait(*this));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001248 if (PP)
1249 PP->getIdentifierTable().setExternalIdentifierLookup(this);
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001250 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001251 break;
1252
1253 case pch::IDENTIFIER_OFFSET:
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001254 if (!IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001255 Error("duplicate IDENTIFIER_OFFSET record in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00001256 return Failure;
1257 }
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001258 IdentifierOffsets = (const uint32_t *)BlobStart;
1259 IdentifiersLoaded.resize(Record[0]);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001260 if (PP)
1261 PP->getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregorafaf3082009-04-11 00:14:32 +00001262 break;
Douglas Gregorfdd01722009-04-14 00:24:19 +00001263
1264 case pch::EXTERNAL_DEFINITIONS:
1265 if (!ExternalDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001266 Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
Douglas Gregorfdd01722009-04-14 00:24:19 +00001267 return Failure;
1268 }
1269 ExternalDefinitions.swap(Record);
1270 break;
Douglas Gregor3e1af842009-04-17 22:13:46 +00001271
Douglas Gregorad1de002009-04-18 05:55:16 +00001272 case pch::SPECIAL_TYPES:
1273 SpecialTypes.swap(Record);
1274 break;
1275
Douglas Gregor3e1af842009-04-17 22:13:46 +00001276 case pch::STATISTICS:
1277 TotalNumStatements = Record[0];
Douglas Gregor37e26842009-04-21 23:56:24 +00001278 TotalNumMacros = Record[1];
Douglas Gregor25123082009-04-22 22:34:57 +00001279 TotalLexicalDeclContexts = Record[2];
1280 TotalVisibleDeclContexts = Record[3];
Douglas Gregor3e1af842009-04-17 22:13:46 +00001281 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001282
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001283 case pch::TENTATIVE_DEFINITIONS:
1284 if (!TentativeDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001285 Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001286 return Failure;
1287 }
1288 TentativeDefinitions.swap(Record);
1289 break;
Douglas Gregor14c22f22009-04-22 22:18:58 +00001290
1291 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
1292 if (!LocallyScopedExternalDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001293 Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
Douglas Gregor14c22f22009-04-22 22:18:58 +00001294 return Failure;
1295 }
1296 LocallyScopedExternalDecls.swap(Record);
1297 break;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001298
Douglas Gregor83941df2009-04-25 17:48:32 +00001299 case pch::SELECTOR_OFFSETS:
1300 SelectorOffsets = (const uint32_t *)BlobStart;
1301 TotalNumSelectors = Record[0];
1302 SelectorsLoaded.resize(TotalNumSelectors);
1303 break;
1304
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001305 case pch::METHOD_POOL:
Douglas Gregor83941df2009-04-25 17:48:32 +00001306 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1307 if (Record[0])
Mike Stump1eb44332009-09-09 15:08:12 +00001308 MethodPoolLookupTable
Douglas Gregor83941df2009-04-25 17:48:32 +00001309 = PCHMethodPoolLookupTable::Create(
1310 MethodPoolLookupTableData + Record[0],
Mike Stump1eb44332009-09-09 15:08:12 +00001311 MethodPoolLookupTableData,
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001312 PCHMethodPoolLookupTrait(*this));
Douglas Gregor83941df2009-04-25 17:48:32 +00001313 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001314 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001315
1316 case pch::PP_COUNTER_VALUE:
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001317 if (!Record.empty() && Listener)
1318 Listener->ReadCounter(Record[0]);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001319 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001320
1321 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner090d9b52009-04-27 19:01:47 +00001322 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001323 TotalNumSLocEntries = Record[0];
Douglas Gregor445e23e2009-10-05 21:07:28 +00001324 SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001325 break;
1326
1327 case pch::SOURCE_LOCATION_PRELOADS:
1328 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1329 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1330 if (Result != Success)
1331 return Result;
1332 }
1333 break;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001334
Douglas Gregor52e71082009-10-16 18:18:30 +00001335 case pch::STAT_CACHE: {
1336 PCHStatCache *MyStatCache =
1337 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1338 (const unsigned char *)BlobStart,
1339 NumStatHits, NumStatMisses);
1340 FileMgr.addStatCache(MyStatCache);
1341 StatCache = MyStatCache;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001342 break;
Douglas Gregor52e71082009-10-16 18:18:30 +00001343 }
1344
Douglas Gregorb81c1702009-04-27 20:06:05 +00001345 case pch::EXT_VECTOR_DECLS:
1346 if (!ExtVectorDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001347 Error("duplicate EXT_VECTOR_DECLS record in PCH file");
Douglas Gregorb81c1702009-04-27 20:06:05 +00001348 return Failure;
1349 }
1350 ExtVectorDecls.swap(Record);
1351 break;
1352
Douglas Gregorb64c1932009-05-12 01:31:05 +00001353 case pch::ORIGINAL_FILE_NAME:
Daniel Dunbar7b5a1212009-11-11 05:29:04 +00001354 ActualOriginalFileName.assign(BlobStart, BlobLen);
1355 OriginalFileName = ActualOriginalFileName;
Douglas Gregore650c8c2009-07-07 00:12:59 +00001356 MaybeAddSystemRootToFilename(OriginalFileName);
Douglas Gregorb64c1932009-05-12 01:31:05 +00001357 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001358
Douglas Gregor2e222532009-07-02 17:08:52 +00001359 case pch::COMMENT_RANGES:
1360 Comments = (SourceRange *)BlobStart;
1361 NumComments = BlobLen / sizeof(SourceRange);
1362 break;
Douglas Gregor445e23e2009-10-05 21:07:28 +00001363
1364 case pch::SVN_BRANCH_REVISION: {
1365 unsigned CurRevision = getClangSubversionRevision();
1366 if (Record[0] && CurRevision && Record[0] != CurRevision) {
1367 Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old
1368 : diag::warn_pch_version_too_new);
1369 return IgnorePCH;
1370 }
1371
1372 const char *CurBranch = getClangSubversionPath();
1373 if (strncmp(CurBranch, BlobStart, BlobLen)) {
1374 std::string PCHBranch(BlobStart, BlobLen);
1375 Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
1376 return IgnorePCH;
1377 }
1378 break;
1379 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001380 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001381 }
Douglas Gregora02b1472009-04-28 21:53:25 +00001382 Error("premature end of bitstream in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001383 return Failure;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001384}
1385
Douglas Gregore1d918e2009-04-10 23:10:45 +00001386PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001387 // Set the PCH file name.
1388 this->FileName = FileName;
1389
Douglas Gregor2cf26342009-04-09 22:27:44 +00001390 // Open the PCH file.
Daniel Dunbarf3c740e2009-09-22 05:38:01 +00001391 //
1392 // FIXME: This shouldn't be here, we should just take a raw_ostream.
Douglas Gregor2cf26342009-04-09 22:27:44 +00001393 std::string ErrStr;
Daniel Dunbar731ad8f2009-11-10 00:46:19 +00001394 Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
Douglas Gregore1d918e2009-04-10 23:10:45 +00001395 if (!Buffer) {
1396 Error(ErrStr.c_str());
1397 return IgnorePCH;
1398 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001399
1400 // Initialize the stream
Mike Stump1eb44332009-09-09 15:08:12 +00001401 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Chris Lattnerb9fa9172009-04-26 20:59:20 +00001402 (const unsigned char *)Buffer->getBufferEnd());
1403 Stream.init(StreamFile);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001404
1405 // Sniff for the signature.
1406 if (Stream.Read(8) != 'C' ||
1407 Stream.Read(8) != 'P' ||
1408 Stream.Read(8) != 'C' ||
Douglas Gregore1d918e2009-04-10 23:10:45 +00001409 Stream.Read(8) != 'H') {
Douglas Gregora02b1472009-04-28 21:53:25 +00001410 Diag(diag::err_not_a_pch_file) << FileName;
1411 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001412 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001413
Douglas Gregor2cf26342009-04-09 22:27:44 +00001414 while (!Stream.AtEndOfStream()) {
1415 unsigned Code = Stream.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +00001416
Douglas Gregore1d918e2009-04-10 23:10:45 +00001417 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001418 Error("invalid record at top-level of PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001419 return Failure;
1420 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001421
1422 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregor668c1a42009-04-21 22:25:48 +00001423
Douglas Gregor2cf26342009-04-09 22:27:44 +00001424 // We only know the PCH subblock ID.
1425 switch (BlockID) {
1426 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001427 if (Stream.ReadBlockInfoBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001428 Error("malformed BlockInfoBlock in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001429 return Failure;
1430 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001431 break;
1432 case pch::PCH_BLOCK_ID:
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001433 switch (ReadPCHBlock()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001434 case Success:
1435 break;
1436
1437 case Failure:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001438 return Failure;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001439
1440 case IgnorePCH:
Douglas Gregor2bec0412009-04-10 21:16:55 +00001441 // FIXME: We could consider reading through to the end of this
1442 // PCH block, skipping subblocks, to see if there are other
1443 // PCH blocks elsewhere.
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001444
1445 // Clear out any preallocated source location entries, so that
1446 // the source manager does not try to resolve them later.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001447 SourceMgr.ClearPreallocatedSLocEntries();
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001448
1449 // Remove the stat cache.
Douglas Gregor52e71082009-10-16 18:18:30 +00001450 if (StatCache)
1451 FileMgr.removeStatCache((PCHStatCache*)StatCache);
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001452
Douglas Gregore1d918e2009-04-10 23:10:45 +00001453 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001454 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001455 break;
1456 default:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001457 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001458 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001459 return Failure;
1460 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001461 break;
1462 }
Mike Stump1eb44332009-09-09 15:08:12 +00001463 }
1464
Douglas Gregor92b059e2009-04-28 20:33:11 +00001465 // Check the predefines buffer.
Daniel Dunbardc3c0d22009-11-11 00:52:11 +00001466 if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
Douglas Gregor92b059e2009-04-28 20:33:11 +00001467 PCHPredefinesBufferID))
1468 return IgnorePCH;
Mike Stump1eb44332009-09-09 15:08:12 +00001469
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001470 if (PP) {
Zhongxing Xu08996212009-07-18 09:26:51 +00001471 // Initialization of keywords and pragmas occurs before the
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001472 // PCH file is read, so there may be some identifiers that were
1473 // loaded into the IdentifierTable before we intercepted the
1474 // creation of identifiers. Iterate through the list of known
1475 // identifiers and determine whether we have to establish
1476 // preprocessor definitions or top-level identifier declaration
1477 // chains for those identifiers.
1478 //
1479 // We copy the IdentifierInfo pointers to a small vector first,
1480 // since de-serializing declarations or macro definitions can add
1481 // new entries into the identifier table, invalidating the
1482 // iterators.
1483 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1484 for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
1485 IdEnd = PP->getIdentifierTable().end();
1486 Id != IdEnd; ++Id)
1487 Identifiers.push_back(Id->second);
Mike Stump1eb44332009-09-09 15:08:12 +00001488 PCHIdentifierLookupTable *IdTable
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001489 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1490 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1491 IdentifierInfo *II = Identifiers[I];
1492 // Look in the on-disk hash table for an entry for
1493 PCHIdentifierLookupTrait Info(*this, II);
Daniel Dunbare013d682009-10-18 20:26:12 +00001494 std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001495 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1496 if (Pos == IdTable->end())
1497 continue;
Mike Stump1eb44332009-09-09 15:08:12 +00001498
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001499 // Dereferencing the iterator has the effect of populating the
1500 // IdentifierInfo node with the various declarations it needs.
1501 (void)*Pos;
1502 }
Douglas Gregor668c1a42009-04-21 22:25:48 +00001503 }
1504
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001505 if (Context)
1506 InitializeContext(*Context);
Douglas Gregor0b748912009-04-14 21:18:50 +00001507
Douglas Gregor668c1a42009-04-21 22:25:48 +00001508 return Success;
Douglas Gregor0b748912009-04-14 21:18:50 +00001509}
1510
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001511void PCHReader::InitializeContext(ASTContext &Ctx) {
1512 Context = &Ctx;
1513 assert(Context && "Passed null context!");
1514
1515 assert(PP && "Forgot to set Preprocessor ?");
1516 PP->getIdentifierTable().setExternalIdentifierLookup(this);
1517 PP->getHeaderSearchInfo().SetExternalLookup(this);
Mike Stump1eb44332009-09-09 15:08:12 +00001518
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001519 // Load the translation unit declaration
1520 ReadDeclRecord(DeclOffsets[0], 0);
1521
1522 // Load the special types.
1523 Context->setBuiltinVaListType(
1524 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
1525 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1526 Context->setObjCIdType(GetType(Id));
1527 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1528 Context->setObjCSelType(GetType(Sel));
1529 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1530 Context->setObjCProtoType(GetType(Proto));
1531 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1532 Context->setObjCClassType(GetType(Class));
Steve Naroff14108da2009-07-10 23:34:53 +00001533
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001534 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1535 Context->setCFConstantStringType(GetType(String));
Mike Stump1eb44332009-09-09 15:08:12 +00001536 if (unsigned FastEnum
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001537 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1538 Context->setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001539 if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
1540 QualType FileType = GetType(File);
1541 assert(!FileType.isNull() && "FILE type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001542 if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001543 Context->setFILEDecl(Typedef->getDecl());
1544 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001545 const TagType *Tag = FileType->getAs<TagType>();
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001546 assert(Tag && "Invalid FILE type in PCH file");
1547 Context->setFILEDecl(Tag->getDecl());
1548 }
1549 }
Mike Stump782fa302009-07-28 02:25:19 +00001550 if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
1551 QualType Jmp_bufType = GetType(Jmp_buf);
1552 assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001553 if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
Mike Stump782fa302009-07-28 02:25:19 +00001554 Context->setjmp_bufDecl(Typedef->getDecl());
1555 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001556 const TagType *Tag = Jmp_bufType->getAs<TagType>();
Mike Stump782fa302009-07-28 02:25:19 +00001557 assert(Tag && "Invalid jmp_bug type in PCH file");
1558 Context->setjmp_bufDecl(Tag->getDecl());
1559 }
1560 }
1561 if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
1562 QualType Sigjmp_bufType = GetType(Sigjmp_buf);
1563 assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001564 if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
Mike Stump782fa302009-07-28 02:25:19 +00001565 Context->setsigjmp_bufDecl(Typedef->getDecl());
1566 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001567 const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
Mike Stump782fa302009-07-28 02:25:19 +00001568 assert(Tag && "Invalid sigjmp_buf type in PCH file");
1569 Context->setsigjmp_bufDecl(Tag->getDecl());
1570 }
1571 }
Mike Stump1eb44332009-09-09 15:08:12 +00001572 if (unsigned ObjCIdRedef
Douglas Gregord1571ac2009-08-21 00:27:50 +00001573 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
1574 Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
Mike Stump1eb44332009-09-09 15:08:12 +00001575 if (unsigned ObjCClassRedef
Douglas Gregord1571ac2009-08-21 00:27:50 +00001576 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
1577 Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
Mike Stumpadaaad32009-10-20 02:12:22 +00001578 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
1579 Context->setBlockDescriptorType(GetType(String));
Mike Stump083c25e2009-10-22 00:49:09 +00001580 if (unsigned String
1581 = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
1582 Context->setBlockDescriptorExtendedType(GetType(String));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001583}
1584
Douglas Gregorb64c1932009-05-12 01:31:05 +00001585/// \brief Retrieve the name of the original source file name
1586/// directly from the PCH file, without actually loading the PCH
1587/// file.
1588std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
1589 // Open the PCH file.
1590 std::string ErrStr;
1591 llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
1592 Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
1593 if (!Buffer) {
1594 fprintf(stderr, "error: %s\n", ErrStr.c_str());
1595 return std::string();
1596 }
1597
1598 // Initialize the stream
1599 llvm::BitstreamReader StreamFile;
1600 llvm::BitstreamCursor Stream;
Mike Stump1eb44332009-09-09 15:08:12 +00001601 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Douglas Gregorb64c1932009-05-12 01:31:05 +00001602 (const unsigned char *)Buffer->getBufferEnd());
1603 Stream.init(StreamFile);
1604
1605 // Sniff for the signature.
1606 if (Stream.Read(8) != 'C' ||
1607 Stream.Read(8) != 'P' ||
1608 Stream.Read(8) != 'C' ||
1609 Stream.Read(8) != 'H') {
Mike Stump1eb44332009-09-09 15:08:12 +00001610 fprintf(stderr,
Douglas Gregorb64c1932009-05-12 01:31:05 +00001611 "error: '%s' does not appear to be a precompiled header file\n",
1612 PCHFileName.c_str());
1613 return std::string();
1614 }
1615
1616 RecordData Record;
1617 while (!Stream.AtEndOfStream()) {
1618 unsigned Code = Stream.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +00001619
Douglas Gregorb64c1932009-05-12 01:31:05 +00001620 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1621 unsigned BlockID = Stream.ReadSubBlockID();
Mike Stump1eb44332009-09-09 15:08:12 +00001622
Douglas Gregorb64c1932009-05-12 01:31:05 +00001623 // We only know the PCH subblock ID.
1624 switch (BlockID) {
1625 case pch::PCH_BLOCK_ID:
1626 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
1627 fprintf(stderr, "error: malformed block record in PCH file\n");
1628 return std::string();
1629 }
1630 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001631
Douglas Gregorb64c1932009-05-12 01:31:05 +00001632 default:
1633 if (Stream.SkipBlock()) {
1634 fprintf(stderr, "error: malformed block record in PCH file\n");
1635 return std::string();
1636 }
1637 break;
1638 }
1639 continue;
1640 }
1641
1642 if (Code == llvm::bitc::END_BLOCK) {
1643 if (Stream.ReadBlockEnd()) {
1644 fprintf(stderr, "error: error at end of module block in PCH file\n");
1645 return std::string();
1646 }
1647 continue;
1648 }
1649
1650 if (Code == llvm::bitc::DEFINE_ABBREV) {
1651 Stream.ReadAbbrevRecord();
1652 continue;
1653 }
1654
1655 Record.clear();
1656 const char *BlobStart = 0;
1657 unsigned BlobLen = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001658 if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
Douglas Gregorb64c1932009-05-12 01:31:05 +00001659 == pch::ORIGINAL_FILE_NAME)
1660 return std::string(BlobStart, BlobLen);
Mike Stump1eb44332009-09-09 15:08:12 +00001661 }
Douglas Gregorb64c1932009-05-12 01:31:05 +00001662
1663 return std::string();
1664}
1665
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001666/// \brief Parse the record that corresponds to a LangOptions data
1667/// structure.
1668///
1669/// This routine compares the language options used to generate the
1670/// PCH file against the language options set for the current
1671/// compilation. For each option, we classify differences between the
1672/// two compiler states as either "benign" or "important". Benign
1673/// differences don't matter, and we accept them without complaint
1674/// (and without modifying the language options). Differences between
1675/// the states for important options cause the PCH file to be
1676/// unusable, so we emit a warning and return true to indicate that
1677/// there was an error.
1678///
1679/// \returns true if the PCH file is unacceptable, false otherwise.
1680bool PCHReader::ParseLanguageOptions(
1681 const llvm::SmallVectorImpl<uint64_t> &Record) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001682 if (Listener) {
1683 LangOptions LangOpts;
Mike Stump1eb44332009-09-09 15:08:12 +00001684
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001685 #define PARSE_LANGOPT(Option) \
1686 LangOpts.Option = Record[Idx]; \
1687 ++Idx
Mike Stump1eb44332009-09-09 15:08:12 +00001688
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001689 unsigned Idx = 0;
1690 PARSE_LANGOPT(Trigraphs);
1691 PARSE_LANGOPT(BCPLComment);
1692 PARSE_LANGOPT(DollarIdents);
1693 PARSE_LANGOPT(AsmPreprocessor);
1694 PARSE_LANGOPT(GNUMode);
1695 PARSE_LANGOPT(ImplicitInt);
1696 PARSE_LANGOPT(Digraphs);
1697 PARSE_LANGOPT(HexFloats);
1698 PARSE_LANGOPT(C99);
1699 PARSE_LANGOPT(Microsoft);
1700 PARSE_LANGOPT(CPlusPlus);
1701 PARSE_LANGOPT(CPlusPlus0x);
1702 PARSE_LANGOPT(CXXOperatorNames);
1703 PARSE_LANGOPT(ObjC1);
1704 PARSE_LANGOPT(ObjC2);
1705 PARSE_LANGOPT(ObjCNonFragileABI);
1706 PARSE_LANGOPT(PascalStrings);
1707 PARSE_LANGOPT(WritableStrings);
1708 PARSE_LANGOPT(LaxVectorConversions);
Nate Begemanb9e7e632009-06-25 23:01:11 +00001709 PARSE_LANGOPT(AltiVec);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001710 PARSE_LANGOPT(Exceptions);
1711 PARSE_LANGOPT(NeXTRuntime);
1712 PARSE_LANGOPT(Freestanding);
1713 PARSE_LANGOPT(NoBuiltin);
1714 PARSE_LANGOPT(ThreadsafeStatics);
Douglas Gregor972d9542009-09-03 14:36:33 +00001715 PARSE_LANGOPT(POSIXThreads);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001716 PARSE_LANGOPT(Blocks);
1717 PARSE_LANGOPT(EmitAllDecls);
1718 PARSE_LANGOPT(MathErrno);
1719 PARSE_LANGOPT(OverflowChecking);
1720 PARSE_LANGOPT(HeinousExtensions);
1721 PARSE_LANGOPT(Optimize);
1722 PARSE_LANGOPT(OptimizeSize);
1723 PARSE_LANGOPT(Static);
1724 PARSE_LANGOPT(PICLevel);
1725 PARSE_LANGOPT(GNUInline);
1726 PARSE_LANGOPT(NoInline);
1727 PARSE_LANGOPT(AccessControl);
1728 PARSE_LANGOPT(CharIsSigned);
John Thompsona6fda122009-11-05 20:14:16 +00001729 PARSE_LANGOPT(ShortWChar);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001730 LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
1731 ++Idx;
1732 LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
1733 ++Idx;
Daniel Dunbarab8e2812009-09-21 04:16:19 +00001734 LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
1735 Record[Idx]);
1736 ++Idx;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001737 PARSE_LANGOPT(InstantiationDepth);
Nate Begemanb9e7e632009-06-25 23:01:11 +00001738 PARSE_LANGOPT(OpenCL);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001739 #undef PARSE_LANGOPT
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001740
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001741 return Listener->ReadLanguageOptions(LangOpts);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001742 }
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001743
1744 return false;
1745}
1746
Douglas Gregor2e222532009-07-02 17:08:52 +00001747void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
1748 Comments.resize(NumComments);
1749 std::copy(this->Comments, this->Comments + NumComments,
1750 Comments.begin());
1751}
1752
Douglas Gregor2cf26342009-04-09 22:27:44 +00001753/// \brief Read and return the type at the given offset.
1754///
1755/// This routine actually reads the record corresponding to the type
1756/// at the given offset in the bitstream. It is a helper routine for
1757/// GetType, which deals with reading type IDs.
1758QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregor0b748912009-04-14 21:18:50 +00001759 // Keep track of where we are in the stream, then jump back there
1760 // after reading this type.
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001761 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001762
Douglas Gregord89275b2009-07-06 18:54:52 +00001763 // Note that we are loading a type record.
1764 LoadingTypeOrDecl Loading(*this);
Mike Stump1eb44332009-09-09 15:08:12 +00001765
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001766 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001767 RecordData Record;
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001768 unsigned Code = DeclsCursor.ReadCode();
1769 switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
Douglas Gregor6d473962009-04-15 22:00:08 +00001770 case pch::TYPE_EXT_QUAL: {
John McCall0953e762009-09-24 19:53:00 +00001771 assert(Record.size() == 2 &&
Douglas Gregor6d473962009-04-15 22:00:08 +00001772 "Incorrect encoding of extended qualifier type");
1773 QualType Base = GetType(Record[0]);
John McCall0953e762009-09-24 19:53:00 +00001774 Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
1775 return Context->getQualifiedType(Base, Quals);
Douglas Gregor6d473962009-04-15 22:00:08 +00001776 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001777
Douglas Gregor2cf26342009-04-09 22:27:44 +00001778 case pch::TYPE_FIXED_WIDTH_INT: {
1779 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001780 return Context->getFixedWidthIntType(Record[0], Record[1]);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001781 }
1782
1783 case pch::TYPE_COMPLEX: {
1784 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1785 QualType ElemType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001786 return Context->getComplexType(ElemType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001787 }
1788
1789 case pch::TYPE_POINTER: {
1790 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1791 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001792 return Context->getPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001793 }
1794
1795 case pch::TYPE_BLOCK_POINTER: {
1796 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1797 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001798 return Context->getBlockPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001799 }
1800
1801 case pch::TYPE_LVALUE_REFERENCE: {
1802 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1803 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001804 return Context->getLValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001805 }
1806
1807 case pch::TYPE_RVALUE_REFERENCE: {
1808 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1809 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001810 return Context->getRValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001811 }
1812
1813 case pch::TYPE_MEMBER_POINTER: {
1814 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1815 QualType PointeeType = GetType(Record[0]);
1816 QualType ClassType = GetType(Record[1]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001817 return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
Douglas Gregor2cf26342009-04-09 22:27:44 +00001818 }
1819
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001820 case pch::TYPE_CONSTANT_ARRAY: {
1821 QualType ElementType = GetType(Record[0]);
1822 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1823 unsigned IndexTypeQuals = Record[2];
1824 unsigned Idx = 3;
1825 llvm::APInt Size = ReadAPInt(Record, Idx);
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001826 return Context->getConstantArrayType(ElementType, Size,
1827 ASM, IndexTypeQuals);
1828 }
1829
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001830 case pch::TYPE_INCOMPLETE_ARRAY: {
1831 QualType ElementType = GetType(Record[0]);
1832 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1833 unsigned IndexTypeQuals = Record[2];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001834 return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001835 }
1836
1837 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregor0b748912009-04-14 21:18:50 +00001838 QualType ElementType = GetType(Record[0]);
1839 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1840 unsigned IndexTypeQuals = Record[2];
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001841 SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
1842 SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001843 return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001844 ASM, IndexTypeQuals,
1845 SourceRange(LBLoc, RBLoc));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001846 }
1847
1848 case pch::TYPE_VECTOR: {
1849 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001850 Error("incorrect encoding of vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001851 return QualType();
1852 }
1853
1854 QualType ElementType = GetType(Record[0]);
1855 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001856 return Context->getVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001857 }
1858
1859 case pch::TYPE_EXT_VECTOR: {
1860 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001861 Error("incorrect encoding of extended vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001862 return QualType();
1863 }
1864
1865 QualType ElementType = GetType(Record[0]);
1866 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001867 return Context->getExtVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001868 }
1869
1870 case pch::TYPE_FUNCTION_NO_PROTO: {
1871 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001872 Error("incorrect encoding of no-proto function type");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001873 return QualType();
1874 }
1875 QualType ResultType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001876 return Context->getFunctionNoProtoType(ResultType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001877 }
1878
1879 case pch::TYPE_FUNCTION_PROTO: {
1880 QualType ResultType = GetType(Record[0]);
1881 unsigned Idx = 1;
1882 unsigned NumParams = Record[Idx++];
1883 llvm::SmallVector<QualType, 16> ParamTypes;
1884 for (unsigned I = 0; I != NumParams; ++I)
1885 ParamTypes.push_back(GetType(Record[Idx++]));
1886 bool isVariadic = Record[Idx++];
1887 unsigned Quals = Record[Idx++];
Sebastian Redl465226e2009-05-27 22:11:52 +00001888 bool hasExceptionSpec = Record[Idx++];
1889 bool hasAnyExceptionSpec = Record[Idx++];
1890 unsigned NumExceptions = Record[Idx++];
1891 llvm::SmallVector<QualType, 2> Exceptions;
1892 for (unsigned I = 0; I != NumExceptions; ++I)
1893 Exceptions.push_back(GetType(Record[Idx++]));
Jay Foadbeaaccd2009-05-21 09:52:38 +00001894 return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
Sebastian Redl465226e2009-05-27 22:11:52 +00001895 isVariadic, Quals, hasExceptionSpec,
1896 hasAnyExceptionSpec, NumExceptions,
1897 Exceptions.data());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001898 }
1899
1900 case pch::TYPE_TYPEDEF:
Douglas Gregora02b1472009-04-28 21:53:25 +00001901 assert(Record.size() == 1 && "incorrect encoding of typedef type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001902 return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001903
1904 case pch::TYPE_TYPEOF_EXPR:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001905 return Context->getTypeOfExprType(ReadTypeExpr());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001906
1907 case pch::TYPE_TYPEOF: {
1908 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001909 Error("incorrect encoding of typeof(type) in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001910 return QualType();
1911 }
1912 QualType UnderlyingType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001913 return Context->getTypeOfType(UnderlyingType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001914 }
Mike Stump1eb44332009-09-09 15:08:12 +00001915
Anders Carlsson395b4752009-06-24 19:06:50 +00001916 case pch::TYPE_DECLTYPE:
1917 return Context->getDecltypeType(ReadTypeExpr());
1918
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001919 case pch::TYPE_RECORD:
Douglas Gregora02b1472009-04-28 21:53:25 +00001920 assert(Record.size() == 1 && "incorrect encoding of record type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001921 return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001922
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001923 case pch::TYPE_ENUM:
Douglas Gregora02b1472009-04-28 21:53:25 +00001924 assert(Record.size() == 1 && "incorrect encoding of enum type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001925 return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001926
John McCall7da24312009-09-05 00:15:47 +00001927 case pch::TYPE_ELABORATED: {
1928 assert(Record.size() == 2 && "incorrect encoding of elaborated type");
1929 unsigned Tag = Record[1];
1930 return Context->getElaboratedType(GetType(Record[0]),
1931 (ElaboratedType::TagKind) Tag);
1932 }
1933
Steve Naroffc15cb2a2009-07-18 15:33:26 +00001934 case pch::TYPE_OBJC_INTERFACE: {
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001935 unsigned Idx = 0;
1936 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1937 unsigned NumProtos = Record[Idx++];
1938 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1939 for (unsigned I = 0; I != NumProtos; ++I)
1940 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroffc15cb2a2009-07-18 15:33:26 +00001941 return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos);
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001942 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001943
Steve Naroffd1b3c2d2009-06-17 22:40:22 +00001944 case pch::TYPE_OBJC_OBJECT_POINTER: {
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001945 unsigned Idx = 0;
Steve Naroff14108da2009-07-10 23:34:53 +00001946 QualType OIT = GetType(Record[Idx++]);
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001947 unsigned NumProtos = Record[Idx++];
1948 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1949 for (unsigned I = 0; I != NumProtos; ++I)
1950 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroff14108da2009-07-10 23:34:53 +00001951 return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001952 }
Argyrios Kyrtzidis24fab412009-09-29 19:42:55 +00001953
John McCall49a832b2009-10-18 09:09:24 +00001954 case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
1955 unsigned Idx = 0;
1956 QualType Parm = GetType(Record[Idx++]);
1957 QualType Replacement = GetType(Record[Idx++]);
1958 return
1959 Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
1960 Replacement);
1961 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001962 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001963 // Suppress a GCC warning
1964 return QualType();
1965}
1966
John McCalla1ee0c52009-10-16 21:56:05 +00001967namespace {
1968
1969class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
1970 PCHReader &Reader;
1971 const PCHReader::RecordData &Record;
1972 unsigned &Idx;
1973
1974public:
1975 TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
1976 unsigned &Idx)
1977 : Reader(Reader), Record(Record), Idx(Idx) { }
1978
John McCall51bd8032009-10-18 01:05:36 +00001979 // We want compile-time assurance that we've enumerated all of
1980 // these, so unfortunately we have to declare them first, then
1981 // define them out-of-line.
1982#define ABSTRACT_TYPELOC(CLASS, PARENT)
John McCalla1ee0c52009-10-16 21:56:05 +00001983#define TYPELOC(CLASS, PARENT) \
John McCall51bd8032009-10-18 01:05:36 +00001984 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
John McCalla1ee0c52009-10-16 21:56:05 +00001985#include "clang/AST/TypeLocNodes.def"
1986
John McCall51bd8032009-10-18 01:05:36 +00001987 void VisitFunctionTypeLoc(FunctionTypeLoc);
1988 void VisitArrayTypeLoc(ArrayTypeLoc);
John McCalla1ee0c52009-10-16 21:56:05 +00001989};
1990
1991}
1992
John McCall51bd8032009-10-18 01:05:36 +00001993void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
John McCalla1ee0c52009-10-16 21:56:05 +00001994 // nothing to do
1995}
John McCall51bd8032009-10-18 01:05:36 +00001996void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
1997 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00001998}
John McCall51bd8032009-10-18 01:05:36 +00001999void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
2000 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002001}
John McCall51bd8032009-10-18 01:05:36 +00002002void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
2003 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002004}
John McCall51bd8032009-10-18 01:05:36 +00002005void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
2006 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002007}
John McCall51bd8032009-10-18 01:05:36 +00002008void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
2009 TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002010}
John McCall51bd8032009-10-18 01:05:36 +00002011void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
2012 TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002013}
John McCall51bd8032009-10-18 01:05:36 +00002014void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
2015 TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002016}
John McCall51bd8032009-10-18 01:05:36 +00002017void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
2018 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002019}
John McCall51bd8032009-10-18 01:05:36 +00002020void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
2021 TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2022 TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002023 if (Record[Idx++])
John McCall51bd8032009-10-18 01:05:36 +00002024 TL.setSizeExpr(Reader.ReadDeclExpr());
Douglas Gregor61d60ee2009-10-17 00:13:19 +00002025 else
John McCall51bd8032009-10-18 01:05:36 +00002026 TL.setSizeExpr(0);
2027}
2028void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
2029 VisitArrayTypeLoc(TL);
2030}
2031void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
2032 VisitArrayTypeLoc(TL);
2033}
2034void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
2035 VisitArrayTypeLoc(TL);
2036}
2037void TypeLocReader::VisitDependentSizedArrayTypeLoc(
2038 DependentSizedArrayTypeLoc TL) {
2039 VisitArrayTypeLoc(TL);
2040}
2041void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
2042 DependentSizedExtVectorTypeLoc TL) {
2043 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2044}
2045void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
2046 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2047}
2048void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
2049 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2050}
2051void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
2052 TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2053 TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2054 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
John McCall86acc2a2009-10-23 01:28:53 +00002055 TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
John McCall51bd8032009-10-18 01:05:36 +00002056 }
2057}
2058void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
2059 VisitFunctionTypeLoc(TL);
2060}
2061void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
2062 VisitFunctionTypeLoc(TL);
2063}
2064void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
2065 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2066}
2067void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
2068 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2069}
2070void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
2071 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2072}
2073void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
2074 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2075}
2076void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
2077 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2078}
2079void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
2080 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2081}
2082void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
2083 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2084}
2085void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
2086 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2087}
John McCall49a832b2009-10-18 09:09:24 +00002088void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
2089 SubstTemplateTypeParmTypeLoc TL) {
2090 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2091}
John McCall51bd8032009-10-18 01:05:36 +00002092void TypeLocReader::VisitTemplateSpecializationTypeLoc(
2093 TemplateSpecializationTypeLoc TL) {
John McCall833ca992009-10-29 08:12:44 +00002094 TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2095 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2096 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2097 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
2098 TL.setArgLocInfo(i,
2099 Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
2100 Record, Idx));
John McCall51bd8032009-10-18 01:05:36 +00002101}
2102void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
2103 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2104}
2105void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
2106 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2107}
2108void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
2109 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall51bd8032009-10-18 01:05:36 +00002110 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2111 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2112 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2113 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002114}
John McCall54e14c42009-10-22 22:37:11 +00002115void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
2116 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2117 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2118 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2119 TL.setHasBaseTypeAsWritten(Record[Idx++]);
2120 TL.setHasProtocolsAsWritten(Record[Idx++]);
2121 if (TL.hasProtocolsAsWritten())
2122 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2123 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
2124}
John McCalla1ee0c52009-10-16 21:56:05 +00002125
2126DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
2127 unsigned &Idx) {
2128 QualType InfoTy = GetType(Record[Idx++]);
2129 if (InfoTy.isNull())
2130 return 0;
2131
2132 DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
2133 TypeLocReader TLR(*this, Record, Idx);
2134 for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
2135 TLR.Visit(TL);
2136 return DInfo;
2137}
Douglas Gregor2cf26342009-04-09 22:27:44 +00002138
Douglas Gregor8038d512009-04-10 17:25:41 +00002139QualType PCHReader::GetType(pch::TypeID ID) {
John McCall0953e762009-09-24 19:53:00 +00002140 unsigned FastQuals = ID & Qualifiers::FastMask;
2141 unsigned Index = ID >> Qualifiers::FastWidth;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002142
2143 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
2144 QualType T;
2145 switch ((pch::PredefinedTypeIDs)Index) {
2146 case pch::PREDEF_TYPE_NULL_ID: return QualType();
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002147 case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
2148 case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002149
2150 case pch::PREDEF_TYPE_CHAR_U_ID:
2151 case pch::PREDEF_TYPE_CHAR_S_ID:
2152 // FIXME: Check that the signedness of CharTy is correct!
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002153 T = Context->CharTy;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002154 break;
2155
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002156 case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
2157 case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
2158 case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
2159 case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
2160 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00002161 case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002162 case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
2163 case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
2164 case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
2165 case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
2166 case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
2167 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00002168 case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002169 case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
2170 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
2171 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
2172 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
2173 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
Sebastian Redl6e8ed162009-05-10 18:38:11 +00002174 case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
Alisdair Meredithf5c209d2009-07-14 06:30:34 +00002175 case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
2176 case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
Steve Naroffde2e22d2009-07-15 18:40:39 +00002177 case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
2178 case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002179 }
2180
2181 assert(!T.isNull() && "Unknown predefined type");
John McCall0953e762009-09-24 19:53:00 +00002182 return T.withFastQualifiers(FastQuals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002183 }
2184
2185 Index -= pch::NUM_PREDEF_TYPE_IDS;
Steve Naroffc15cb2a2009-07-18 15:33:26 +00002186 //assert(Index < TypesLoaded.size() && "Type index out-of-range");
John McCall0953e762009-09-24 19:53:00 +00002187 if (TypesLoaded[Index].isNull())
2188 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
Mike Stump1eb44332009-09-09 15:08:12 +00002189
John McCall0953e762009-09-24 19:53:00 +00002190 return TypesLoaded[Index].withFastQualifiers(FastQuals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002191}
2192
John McCall833ca992009-10-29 08:12:44 +00002193TemplateArgumentLocInfo
2194PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
2195 const RecordData &Record,
2196 unsigned &Index) {
2197 switch (Kind) {
2198 case TemplateArgument::Expression:
2199 return ReadDeclExpr();
2200 case TemplateArgument::Type:
2201 return GetDeclaratorInfo(Record, Index);
Douglas Gregor788cd062009-11-11 01:00:40 +00002202 case TemplateArgument::Template: {
2203 SourceLocation
2204 QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
2205 QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
2206 TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
2207 return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
2208 TemplateNameLoc);
2209 }
John McCall833ca992009-10-29 08:12:44 +00002210 case TemplateArgument::Null:
2211 case TemplateArgument::Integral:
2212 case TemplateArgument::Declaration:
2213 case TemplateArgument::Pack:
2214 return TemplateArgumentLocInfo();
2215 }
2216 llvm::llvm_unreachable("unexpected template argument loc");
2217 return TemplateArgumentLocInfo();
2218}
2219
Douglas Gregor8038d512009-04-10 17:25:41 +00002220Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00002221 if (ID == 0)
2222 return 0;
2223
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002224 if (ID > DeclsLoaded.size()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002225 Error("declaration ID out-of-range for PCH file");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002226 return 0;
2227 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00002228
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002229 unsigned Index = ID - 1;
2230 if (!DeclsLoaded[Index])
2231 ReadDeclRecord(DeclOffsets[Index], Index);
2232
2233 return DeclsLoaded[Index];
Douglas Gregor2cf26342009-04-09 22:27:44 +00002234}
2235
Chris Lattner887e2b32009-04-27 05:46:25 +00002236/// \brief Resolve the offset of a statement into a statement.
2237///
2238/// This operation will read a new statement from the external
2239/// source each time it is called, and is meant to be used via a
2240/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
2241Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattnerda930612009-04-27 05:58:23 +00002242 // Since we know tha this statement is part of a decl, make sure to use the
2243 // decl cursor to read it.
2244 DeclsCursor.JumpToBit(Offset);
2245 return ReadStmt(DeclsCursor);
Douglas Gregor250fc9c2009-04-18 00:07:54 +00002246}
2247
Douglas Gregor2cf26342009-04-09 22:27:44 +00002248bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor8038d512009-04-10 17:25:41 +00002249 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Mike Stump1eb44332009-09-09 15:08:12 +00002250 assert(DC->hasExternalLexicalStorage() &&
Douglas Gregor2cf26342009-04-09 22:27:44 +00002251 "DeclContext has no lexical decls in storage");
2252 uint64_t Offset = DeclContextOffsets[DC].first;
2253 assert(Offset && "DeclContext has no lexical decls in storage");
2254
Douglas Gregor0b748912009-04-14 21:18:50 +00002255 // Keep track of where we are in the stream, then jump back there
2256 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002257 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00002258
Douglas Gregor2cf26342009-04-09 22:27:44 +00002259 // Load the record containing all of the declarations lexically in
2260 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002261 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002262 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002263 unsigned Code = DeclsCursor.ReadCode();
2264 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00002265 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002266 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
2267
2268 // Load all of the declaration IDs
2269 Decls.clear();
2270 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregor25123082009-04-22 22:34:57 +00002271 ++NumLexicalDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002272 return false;
2273}
2274
2275bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002276 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Mike Stump1eb44332009-09-09 15:08:12 +00002277 assert(DC->hasExternalVisibleStorage() &&
Douglas Gregor2cf26342009-04-09 22:27:44 +00002278 "DeclContext has no visible decls in storage");
2279 uint64_t Offset = DeclContextOffsets[DC].second;
2280 assert(Offset && "DeclContext has no visible decls in storage");
2281
Douglas Gregor0b748912009-04-14 21:18:50 +00002282 // Keep track of where we are in the stream, then jump back there
2283 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002284 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00002285
Douglas Gregor2cf26342009-04-09 22:27:44 +00002286 // Load the record containing all of the declarations visible in
2287 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002288 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002289 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002290 unsigned Code = DeclsCursor.ReadCode();
2291 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00002292 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002293 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
2294 if (Record.size() == 0)
Mike Stump1eb44332009-09-09 15:08:12 +00002295 return false;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002296
2297 Decls.clear();
2298
2299 unsigned Idx = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002300 while (Idx < Record.size()) {
2301 Decls.push_back(VisibleDeclaration());
2302 Decls.back().Name = ReadDeclarationName(Record, Idx);
2303
Douglas Gregor2cf26342009-04-09 22:27:44 +00002304 unsigned Size = Record[Idx++];
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002305 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002306 LoadedDecls.reserve(Size);
2307 for (unsigned I = 0; I < Size; ++I)
2308 LoadedDecls.push_back(Record[Idx++]);
2309 }
2310
Douglas Gregor25123082009-04-22 22:34:57 +00002311 ++NumVisibleDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002312 return false;
2313}
2314
Douglas Gregorfdd01722009-04-14 00:24:19 +00002315void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor0af2ca42009-04-22 19:09:20 +00002316 this->Consumer = Consumer;
2317
Douglas Gregorfdd01722009-04-14 00:24:19 +00002318 if (!Consumer)
2319 return;
2320
2321 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
Daniel Dunbar04a0b502009-09-17 03:06:44 +00002322 // Force deserialization of this decl, which will cause it to be passed to
2323 // the consumer (or queued).
2324 GetDecl(ExternalDefinitions[I]);
Douglas Gregorfdd01722009-04-14 00:24:19 +00002325 }
Douglas Gregorc62a2fe2009-04-25 00:41:30 +00002326
2327 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
2328 DeclGroupRef DG(InterestingDecls[I]);
2329 Consumer->HandleTopLevelDecl(DG);
2330 }
Douglas Gregorfdd01722009-04-14 00:24:19 +00002331}
2332
Douglas Gregor2cf26342009-04-09 22:27:44 +00002333void PCHReader::PrintStats() {
2334 std::fprintf(stderr, "*** PCH Statistics:\n");
2335
Mike Stump1eb44332009-09-09 15:08:12 +00002336 unsigned NumTypesLoaded
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002337 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
John McCall0953e762009-09-24 19:53:00 +00002338 QualType());
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002339 unsigned NumDeclsLoaded
2340 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
2341 (Decl *)0);
2342 unsigned NumIdentifiersLoaded
2343 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
2344 IdentifiersLoaded.end(),
2345 (IdentifierInfo *)0);
Mike Stump1eb44332009-09-09 15:08:12 +00002346 unsigned NumSelectorsLoaded
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002347 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
2348 SelectorsLoaded.end(),
2349 Selector());
Douglas Gregor2d41cc12009-04-13 20:50:16 +00002350
Douglas Gregor4fed3f42009-04-27 18:38:38 +00002351 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
2352 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002353 if (TotalNumSLocEntries)
2354 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
2355 NumSLocEntriesRead, TotalNumSLocEntries,
2356 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002357 if (!TypesLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002358 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002359 NumTypesLoaded, (unsigned)TypesLoaded.size(),
2360 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
2361 if (!DeclsLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002362 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002363 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
2364 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002365 if (!IdentifiersLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002366 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002367 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
2368 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor83941df2009-04-25 17:48:32 +00002369 if (TotalNumSelectors)
2370 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
2371 NumSelectorsLoaded, TotalNumSelectors,
2372 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
2373 if (TotalNumStatements)
2374 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
2375 NumStatementsRead, TotalNumStatements,
2376 ((float)NumStatementsRead/TotalNumStatements * 100));
2377 if (TotalNumMacros)
2378 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
2379 NumMacrosRead, TotalNumMacros,
2380 ((float)NumMacrosRead/TotalNumMacros * 100));
2381 if (TotalLexicalDeclContexts)
2382 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
2383 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
2384 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
2385 * 100));
2386 if (TotalVisibleDeclContexts)
2387 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
2388 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
2389 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
2390 * 100));
2391 if (TotalSelectorsInMethodPool) {
2392 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
2393 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
2394 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
2395 * 100));
2396 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
2397 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00002398 std::fprintf(stderr, "\n");
2399}
2400
Douglas Gregor668c1a42009-04-21 22:25:48 +00002401void PCHReader::InitializeSema(Sema &S) {
2402 SemaObj = &S;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002403 S.ExternalSource = this;
2404
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002405 // Makes sure any declarations that were deserialized "too early"
2406 // still get added to the identifier's declaration chains.
2407 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
2408 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
2409 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregor668c1a42009-04-21 22:25:48 +00002410 }
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002411 PreloadedDecls.clear();
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00002412
2413 // If there were any tentative definitions, deserialize them and add
2414 // them to Sema's table of tentative definitions.
2415 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
2416 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
2417 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
Chris Lattner63d65f82009-09-08 18:19:27 +00002418 SemaObj->TentativeDefinitionList.push_back(Var->getDeclName());
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00002419 }
Douglas Gregor14c22f22009-04-22 22:18:58 +00002420
2421 // If there were any locally-scoped external declarations,
2422 // deserialize them and add them to Sema's table of locally-scoped
2423 // external declarations.
2424 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
2425 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
2426 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
2427 }
Douglas Gregorb81c1702009-04-27 20:06:05 +00002428
2429 // If there were any ext_vector type declarations, deserialize them
2430 // and add them to Sema's vector of such declarations.
2431 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
2432 SemaObj->ExtVectorDecls.push_back(
2433 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
Douglas Gregor668c1a42009-04-21 22:25:48 +00002434}
2435
2436IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
2437 // Try to find this name within our on-disk hash table
Mike Stump1eb44332009-09-09 15:08:12 +00002438 PCHIdentifierLookupTable *IdTable
Douglas Gregor668c1a42009-04-21 22:25:48 +00002439 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
2440 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
2441 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
2442 if (Pos == IdTable->end())
2443 return 0;
2444
2445 // Dereferencing the iterator has the effect of building the
2446 // IdentifierInfo node and populating it with the various
2447 // declarations it needs.
2448 return *Pos;
2449}
2450
Mike Stump1eb44332009-09-09 15:08:12 +00002451std::pair<ObjCMethodList, ObjCMethodList>
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002452PCHReader::ReadMethodPool(Selector Sel) {
2453 if (!MethodPoolLookupTable)
2454 return std::pair<ObjCMethodList, ObjCMethodList>();
2455
2456 // Try to find this selector within our on-disk hash table.
2457 PCHMethodPoolLookupTable *PoolTable
2458 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
2459 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor83941df2009-04-25 17:48:32 +00002460 if (Pos == PoolTable->end()) {
2461 ++NumMethodPoolMisses;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002462 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor83941df2009-04-25 17:48:32 +00002463 }
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002464
Douglas Gregor83941df2009-04-25 17:48:32 +00002465 ++NumMethodPoolSelectorsRead;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002466 return *Pos;
2467}
2468
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002469void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregor668c1a42009-04-21 22:25:48 +00002470 assert(ID && "Non-zero identifier ID required");
Douglas Gregora02b1472009-04-28 21:53:25 +00002471 assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002472 IdentifiersLoaded[ID - 1] = II;
Douglas Gregor668c1a42009-04-21 22:25:48 +00002473}
2474
Douglas Gregord89275b2009-07-06 18:54:52 +00002475/// \brief Set the globally-visible declarations associated with the given
2476/// identifier.
2477///
2478/// If the PCH reader is currently in a state where the given declaration IDs
Mike Stump1eb44332009-09-09 15:08:12 +00002479/// cannot safely be resolved, they are queued until it is safe to resolve
Douglas Gregord89275b2009-07-06 18:54:52 +00002480/// them.
2481///
2482/// \param II an IdentifierInfo that refers to one or more globally-visible
2483/// declarations.
2484///
2485/// \param DeclIDs the set of declaration IDs with the name @p II that are
2486/// visible at global scope.
2487///
2488/// \param Nonrecursive should be true to indicate that the caller knows that
2489/// this call is non-recursive, and therefore the globally-visible declarations
2490/// will not be placed onto the pending queue.
Mike Stump1eb44332009-09-09 15:08:12 +00002491void
2492PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
Douglas Gregord89275b2009-07-06 18:54:52 +00002493 const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
2494 bool Nonrecursive) {
2495 if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
2496 PendingIdentifierInfos.push_back(PendingIdentifierInfo());
2497 PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
2498 PII.II = II;
2499 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
2500 PII.DeclIDs.push_back(DeclIDs[I]);
2501 return;
2502 }
Mike Stump1eb44332009-09-09 15:08:12 +00002503
Douglas Gregord89275b2009-07-06 18:54:52 +00002504 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
2505 NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
2506 if (SemaObj) {
2507 // Introduce this declaration into the translation-unit scope
2508 // and add it to the declaration chain for this identifier, so
2509 // that (unqualified) name lookup will find it.
2510 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
2511 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
2512 } else {
2513 // Queue this declaration so that it will be added to the
2514 // translation unit scope and identifier's declaration chain
2515 // once a Sema object is known.
2516 PreloadedDecls.push_back(D);
2517 }
2518 }
2519}
2520
Chris Lattner7356a312009-04-11 21:15:38 +00002521IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00002522 if (ID == 0)
2523 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +00002524
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002525 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002526 Error("no identifier table in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00002527 return 0;
2528 }
Mike Stump1eb44332009-09-09 15:08:12 +00002529
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002530 assert(PP && "Forgot to set Preprocessor ?");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002531 if (!IdentifiersLoaded[ID - 1]) {
2532 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00002533 const char *Str = IdentifierTableData + Offset;
Douglas Gregord6595a42009-04-25 21:04:17 +00002534
Douglas Gregor02fc7512009-04-28 20:01:51 +00002535 // All of the strings in the PCH file are preceded by a 16-bit
2536 // length. Extract that 16-bit length to avoid having to execute
2537 // strlen().
Ted Kremenek231bc0b2009-10-23 04:45:31 +00002538 // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
2539 // unsigned integers. This is important to avoid integer overflow when
2540 // we cast them to 'unsigned'.
Ted Kremenekff1ea462009-10-23 03:57:22 +00002541 const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
Douglas Gregor02fc7512009-04-28 20:01:51 +00002542 unsigned StrLen = (((unsigned) StrLenPtr[0])
2543 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
Mike Stump1eb44332009-09-09 15:08:12 +00002544 IdentifiersLoaded[ID - 1]
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002545 = &PP->getIdentifierTable().get(Str, Str + StrLen);
Douglas Gregorafaf3082009-04-11 00:14:32 +00002546 }
Mike Stump1eb44332009-09-09 15:08:12 +00002547
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002548 return IdentifiersLoaded[ID - 1];
Douglas Gregor2cf26342009-04-09 22:27:44 +00002549}
2550
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002551void PCHReader::ReadSLocEntry(unsigned ID) {
2552 ReadSLocEntryRecord(ID);
2553}
2554
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002555Selector PCHReader::DecodeSelector(unsigned ID) {
2556 if (ID == 0)
2557 return Selector();
Mike Stump1eb44332009-09-09 15:08:12 +00002558
Douglas Gregora02b1472009-04-28 21:53:25 +00002559 if (!MethodPoolLookupTableData)
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002560 return Selector();
Douglas Gregor83941df2009-04-25 17:48:32 +00002561
2562 if (ID > TotalNumSelectors) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002563 Error("selector ID out of range in PCH file");
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002564 return Selector();
2565 }
Douglas Gregor83941df2009-04-25 17:48:32 +00002566
2567 unsigned Index = ID - 1;
2568 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
2569 // Load this selector from the selector table.
2570 // FIXME: endianness portability issues with SelectorOffsets table
2571 PCHMethodPoolLookupTrait Trait(*this);
Mike Stump1eb44332009-09-09 15:08:12 +00002572 SelectorsLoaded[Index]
Douglas Gregor83941df2009-04-25 17:48:32 +00002573 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
2574 }
2575
2576 return SelectorsLoaded[Index];
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002577}
2578
Mike Stump1eb44332009-09-09 15:08:12 +00002579DeclarationName
Douglas Gregor2cf26342009-04-09 22:27:44 +00002580PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
2581 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
2582 switch (Kind) {
2583 case DeclarationName::Identifier:
2584 return DeclarationName(GetIdentifierInfo(Record, Idx));
2585
2586 case DeclarationName::ObjCZeroArgSelector:
2587 case DeclarationName::ObjCOneArgSelector:
2588 case DeclarationName::ObjCMultiArgSelector:
Steve Naroffa7503a72009-04-23 15:15:40 +00002589 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002590
2591 case DeclarationName::CXXConstructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002592 return Context->DeclarationNames.getCXXConstructorName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002593 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002594
2595 case DeclarationName::CXXDestructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002596 return Context->DeclarationNames.getCXXDestructorName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002597 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002598
2599 case DeclarationName::CXXConversionFunctionName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002600 return Context->DeclarationNames.getCXXConversionFunctionName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002601 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002602
2603 case DeclarationName::CXXOperatorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002604 return Context->DeclarationNames.getCXXOperatorName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002605 (OverloadedOperatorKind)Record[Idx++]);
2606
2607 case DeclarationName::CXXUsingDirective:
2608 return DeclarationName::getUsingDirectiveName();
2609 }
2610
2611 // Required to silence GCC warning
2612 return DeclarationName();
2613}
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002614
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00002615/// \brief Read an integral value
2616llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
2617 unsigned BitWidth = Record[Idx++];
2618 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
2619 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
2620 Idx += NumWords;
2621 return Result;
2622}
2623
2624/// \brief Read a signed integral value
2625llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
2626 bool isUnsigned = Record[Idx++];
2627 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
2628}
2629
Douglas Gregor17fc2232009-04-14 21:55:33 +00002630/// \brief Read a floating-point value
2631llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregor17fc2232009-04-14 21:55:33 +00002632 return llvm::APFloat(ReadAPInt(Record, Idx));
2633}
2634
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002635// \brief Read a string
2636std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
2637 unsigned Len = Record[Idx++];
Jay Foadbeaaccd2009-05-21 09:52:38 +00002638 std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002639 Idx += Len;
2640 return Result;
2641}
2642
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002643DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00002644 return Diag(SourceLocation(), DiagID);
2645}
2646
2647DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002648 return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002649}
Douglas Gregor025452f2009-04-17 00:04:06 +00002650
Douglas Gregor668c1a42009-04-21 22:25:48 +00002651/// \brief Retrieve the identifier table associated with the
2652/// preprocessor.
2653IdentifierTable &PCHReader::getIdentifierTable() {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002654 assert(PP && "Forgot to set Preprocessor ?");
2655 return PP->getIdentifierTable();
Douglas Gregor668c1a42009-04-21 22:25:48 +00002656}
2657
Douglas Gregor025452f2009-04-17 00:04:06 +00002658/// \brief Record that the given ID maps to the given switch-case
2659/// statement.
2660void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
2661 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
2662 SwitchCaseStmts[ID] = SC;
2663}
2664
2665/// \brief Retrieve the switch-case statement with the given ID.
2666SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
2667 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
2668 return SwitchCaseStmts[ID];
2669}
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002670
2671/// \brief Record that the given label statement has been
2672/// deserialized and has the given ID.
2673void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
Mike Stump1eb44332009-09-09 15:08:12 +00002674 assert(LabelStmts.find(ID) == LabelStmts.end() &&
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002675 "Deserialized label twice");
2676 LabelStmts[ID] = S;
2677
2678 // If we've already seen any goto statements that point to this
2679 // label, resolve them now.
2680 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
2681 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
2682 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
2683 Goto->second->setLabel(S);
2684 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002685
2686 // If we've already seen any address-label statements that point to
2687 // this label, resolve them now.
2688 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
Mike Stump1eb44332009-09-09 15:08:12 +00002689 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002690 = UnresolvedAddrLabelExprs.equal_range(ID);
Mike Stump1eb44332009-09-09 15:08:12 +00002691 for (AddrLabelIter AddrLabel = AddrLabels.first;
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002692 AddrLabel != AddrLabels.second; ++AddrLabel)
2693 AddrLabel->second->setLabel(S);
2694 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002695}
2696
2697/// \brief Set the label of the given statement to the label
2698/// identified by ID.
2699///
2700/// Depending on the order in which the label and other statements
2701/// referencing that label occur, this operation may complete
2702/// immediately (updating the statement) or it may queue the
2703/// statement to be back-patched later.
2704void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
2705 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2706 if (Label != LabelStmts.end()) {
2707 // We've already seen this label, so set the label of the goto and
2708 // we're done.
2709 S->setLabel(Label->second);
2710 } else {
2711 // We haven't seen this label yet, so add this goto to the set of
2712 // unresolved goto statements.
2713 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2714 }
2715}
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002716
2717/// \brief Set the label of the given expression to the label
2718/// identified by ID.
2719///
2720/// Depending on the order in which the label and other statements
2721/// referencing that label occur, this operation may complete
2722/// immediately (updating the statement) or it may queue the
2723/// statement to be back-patched later.
2724void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2725 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2726 if (Label != LabelStmts.end()) {
2727 // We've already seen this label, so set the label of the
2728 // label-address expression and we're done.
2729 S->setLabel(Label->second);
2730 } else {
2731 // We haven't seen this label yet, so add this label-address
2732 // expression to the set of unresolved label-address expressions.
2733 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2734 }
2735}
Douglas Gregord89275b2009-07-06 18:54:52 +00002736
2737
Mike Stump1eb44332009-09-09 15:08:12 +00002738PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
Douglas Gregord89275b2009-07-06 18:54:52 +00002739 : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
2740 Reader.CurrentlyLoadingTypeOrDecl = this;
2741}
2742
2743PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
2744 if (!Parent) {
2745 // If any identifiers with corresponding top-level declarations have
2746 // been loaded, load those declarations now.
2747 while (!Reader.PendingIdentifierInfos.empty()) {
2748 Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
2749 Reader.PendingIdentifierInfos.front().DeclIDs,
2750 true);
2751 Reader.PendingIdentifierInfos.pop_front();
2752 }
2753 }
2754
Mike Stump1eb44332009-09-09 15:08:12 +00002755 Reader.CurrentlyLoadingTypeOrDecl = Parent;
Douglas Gregord89275b2009-07-06 18:54:52 +00002756}