blob: 780890de2abf46f7af793e7f83daaab24112554f [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"
Daniel Dunbarc7162932009-11-11 23:58:53 +000016#include "clang/Frontend/Utils.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000017#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere
Douglas Gregorfdd01722009-04-14 00:24:19 +000018#include "clang/AST/ASTConsumer.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000019#include "clang/AST/ASTContext.h"
Douglas Gregor0b748912009-04-14 21:18:50 +000020#include "clang/AST/Expr.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000021#include "clang/AST/Type.h"
John McCalla1ee0c52009-10-16 21:56:05 +000022#include "clang/AST/TypeLocVisitor.h"
Chris Lattner42d42b52009-04-10 21:41:48 +000023#include "clang/Lex/MacroInfo.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000024#include "clang/Lex/Preprocessor.h"
Steve Naroff83d63c72009-04-24 20:03:17 +000025#include "clang/Lex/HeaderSearch.h"
Douglas Gregor668c1a42009-04-21 22:25:48 +000026#include "clang/Basic/OnDiskHashTable.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000027#include "clang/Basic/SourceManager.h"
Douglas Gregorbd945002009-04-13 16:31:14 +000028#include "clang/Basic/SourceManagerInternals.h"
Douglas Gregor14f79002009-04-10 03:52:48 +000029#include "clang/Basic/FileManager.h"
Douglas Gregor2bec0412009-04-10 21:16:55 +000030#include "clang/Basic/TargetInfo.h"
Douglas Gregor445e23e2009-10-05 21:07:28 +000031#include "clang/Basic/Version.h"
Daniel Dunbar2596e422009-10-17 23:52:28 +000032#include "llvm/ADT/StringExtras.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000033#include "llvm/Bitcode/BitstreamReader.h"
34#include "llvm/Support/Compiler.h"
35#include "llvm/Support/MemoryBuffer.h"
John McCall833ca992009-10-29 08:12:44 +000036#include "llvm/Support/ErrorHandling.h"
Douglas Gregor2cf26342009-04-09 22:27:44 +000037#include <algorithm>
Douglas Gregore721f952009-04-28 18:58:38 +000038#include <iterator>
Douglas Gregor2cf26342009-04-09 22:27:44 +000039#include <cstdio>
Douglas Gregor4fed3f42009-04-27 18:38:38 +000040#include <sys/stat.h>
Douglas Gregor2cf26342009-04-09 22:27:44 +000041using namespace clang;
42
43//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000044// PCH reader validator implementation
45//===----------------------------------------------------------------------===//
46
47PCHReaderListener::~PCHReaderListener() {}
48
49bool
50PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) {
51 const LangOptions &PPLangOpts = PP.getLangOptions();
52#define PARSE_LANGOPT_BENIGN(Option)
53#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \
54 if (PPLangOpts.Option != LangOpts.Option) { \
55 Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \
56 return true; \
57 }
58
59 PARSE_LANGOPT_BENIGN(Trigraphs);
60 PARSE_LANGOPT_BENIGN(BCPLComment);
61 PARSE_LANGOPT_BENIGN(DollarIdents);
62 PARSE_LANGOPT_BENIGN(AsmPreprocessor);
63 PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions);
64 PARSE_LANGOPT_BENIGN(ImplicitInt);
65 PARSE_LANGOPT_BENIGN(Digraphs);
66 PARSE_LANGOPT_BENIGN(HexFloats);
67 PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99);
68 PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions);
69 PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus);
70 PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x);
71 PARSE_LANGOPT_BENIGN(CXXOperatorName);
72 PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c);
73 PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2);
74 PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi);
75 PARSE_LANGOPT_BENIGN(PascalStrings);
76 PARSE_LANGOPT_BENIGN(WritableStrings);
Mike Stump1eb44332009-09-09 15:08:12 +000077 PARSE_LANGOPT_IMPORTANT(LaxVectorConversions,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000078 diag::warn_pch_lax_vector_conversions);
Nate Begeman69cfb9b2009-06-25 22:57:40 +000079 PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000080 PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions);
81 PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime);
82 PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding);
83 PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins);
Mike Stump1eb44332009-09-09 15:08:12 +000084 PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000085 diag::warn_pch_thread_safe_statics);
Daniel Dunbar5345c392009-09-03 04:54:28 +000086 PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000087 PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks);
88 PARSE_LANGOPT_BENIGN(EmitAllDecls);
89 PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno);
90 PARSE_LANGOPT_IMPORTANT(OverflowChecking, diag::warn_pch_overflow_checking);
Mike Stump1eb44332009-09-09 15:08:12 +000091 PARSE_LANGOPT_IMPORTANT(HeinousExtensions,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +000092 diag::warn_pch_heinous_extensions);
93 // FIXME: Most of the options below are benign if the macro wasn't
94 // used. Unfortunately, this means that a PCH compiled without
95 // optimization can't be used with optimization turned on, even
96 // though the only thing that changes is whether __OPTIMIZE__ was
97 // defined... but if __OPTIMIZE__ never showed up in the header, it
98 // doesn't matter. We could consider making this some special kind
99 // of check.
100 PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize);
101 PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size);
102 PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static);
103 PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level);
104 PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline);
105 PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline);
106 PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control);
107 PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed);
John Thompsona6fda122009-11-05 20:14:16 +0000108 PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000109 if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000110 Reader.Diag(diag::warn_pch_gc_mode)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000111 << LangOpts.getGCMode() << PPLangOpts.getGCMode();
112 return true;
113 }
114 PARSE_LANGOPT_BENIGN(getVisibilityMode());
Daniel Dunbarab8e2812009-09-21 04:16:19 +0000115 PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(),
116 diag::warn_pch_stack_protector);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000117 PARSE_LANGOPT_BENIGN(InstantiationDepth);
Nate Begeman69cfb9b2009-06-25 22:57:40 +0000118 PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl);
Daniel Dunbarab8e2812009-09-21 04:16:19 +0000119 PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000120#undef PARSE_LANGOPT_IRRELEVANT
121#undef PARSE_LANGOPT_BENIGN
122
123 return false;
124}
125
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000126bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) {
127 if (Triple == PP.getTargetInfo().getTriple().str())
128 return false;
129
130 Reader.Diag(diag::warn_pch_target_triple)
131 << Triple << PP.getTargetInfo().getTriple().str();
132 return true;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000133}
134
135/// \brief Split the given string into a vector of lines, eliminating
136/// any empty lines in the process.
137///
138/// \param Str the string to split.
139/// \param Len the length of Str.
140/// \param KeepEmptyLines true if empty lines should be included
141/// \returns a vector of lines, with the line endings removed
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000142static std::vector<llvm::StringRef> splitLines(llvm::StringRef Str,
143 bool KeepEmptyLines = false) {
144 std::vector<llvm::StringRef> Lines;
145
146 while (!Str.empty()) {
147 std::pair<llvm::StringRef, llvm::StringRef> split = Str.split('\n');
148
149 if (KeepEmptyLines || !split.first.empty())
150 Lines.push_back(split.first);
151
152 Str = split.second;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000153 }
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000154
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000155 return Lines;
156}
157
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000158bool PCHValidator::ReadPredefinesBuffer(llvm::StringRef PCHPredef,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000159 FileID PCHBufferID,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000160 llvm::StringRef OriginalFileName,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000161 std::string &SuggestedPredefines) {
Daniel Dunbarc7162932009-11-11 23:58:53 +0000162 // We are in the context of an implicit include, so the predefines buffer will
163 // have a #include entry for the PCH file itself (as normalized by the
164 // preprocessor initialization). Find it and skip over it in the checking
165 // below.
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000166 llvm::SmallString<256> PCHInclude;
167 PCHInclude += "#include \"";
Daniel Dunbarc7162932009-11-11 23:58:53 +0000168 PCHInclude += NormalizeDashIncludePath(OriginalFileName);
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000169 PCHInclude += "\"\n";
170 std::pair<llvm::StringRef,llvm::StringRef> Split =
171 llvm::StringRef(PP.getPredefines()).split(PCHInclude.str());
172 llvm::StringRef Left = Split.first, Right = Split.second;
173 assert(Left != PP.getPredefines() && "Missing PCH include entry!");
174
175 // If the predefines is equal to the joined left and right halves, we're done!
176 if (Left.size() + Right.size() == PCHPredef.size() &&
177 PCHPredef.startswith(Left) && PCHPredef.endswith(Right))
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000178 return false;
179
180 SourceManager &SourceMgr = PP.getSourceManager();
Mike Stump1eb44332009-09-09 15:08:12 +0000181
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000182 // The predefines buffers are different. Determine what the differences are,
183 // and whether they require us to reject the PCH file.
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000184 std::vector<llvm::StringRef> PCHLines = splitLines(PCHPredef);
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000185 std::vector<llvm::StringRef> CmdLineLines = splitLines(Left);
186 std::vector<llvm::StringRef> CmdLineLinesRight = splitLines(Right);
187 CmdLineLines.insert(CmdLineLines.end(),
188 CmdLineLinesRight.begin(), CmdLineLinesRight.end());
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000189
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000190 // Sort both sets of predefined buffer lines, since we allow some extra
191 // definitions and they may appear at any point in the output.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000192 std::sort(CmdLineLines.begin(), CmdLineLines.end());
193 std::sort(PCHLines.begin(), PCHLines.end());
194
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000195 // Determine which predefines that were used to build the PCH file are missing
196 // from the command line.
197 std::vector<llvm::StringRef> MissingPredefines;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000198 std::set_difference(PCHLines.begin(), PCHLines.end(),
199 CmdLineLines.begin(), CmdLineLines.end(),
200 std::back_inserter(MissingPredefines));
201
202 bool MissingDefines = false;
203 bool ConflictingDefines = false;
204 for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) {
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000205 llvm::StringRef Missing = MissingPredefines[I];
206 if (!Missing.startswith("#define ")) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000207 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
208 return true;
209 }
Mike Stump1eb44332009-09-09 15:08:12 +0000210
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000211 // This is a macro definition. Determine the name of the macro we're
212 // defining.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000213 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump1eb44332009-09-09 15:08:12 +0000214 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000215 = Missing.find_first_of("( \n\r", StartOfMacroName);
216 assert(EndOfMacroName != std::string::npos &&
217 "Couldn't find the end of the macro name");
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000218 llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000219
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000220 // Determine whether this macro was given a different definition on the
221 // command line.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000222 std::string MacroDefStart = "#define " + MacroName.str();
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000223 std::string::size_type MacroDefLen = MacroDefStart.size();
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000224 std::vector<llvm::StringRef>::iterator ConflictPos
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000225 = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(),
226 MacroDefStart);
227 for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) {
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000228 if (!ConflictPos->startswith(MacroDefStart)) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000229 // Different macro; we're done.
230 ConflictPos = CmdLineLines.end();
Mike Stump1eb44332009-09-09 15:08:12 +0000231 break;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000232 }
Mike Stump1eb44332009-09-09 15:08:12 +0000233
234 assert(ConflictPos->size() > MacroDefLen &&
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000235 "Invalid #define in predefines buffer?");
Mike Stump1eb44332009-09-09 15:08:12 +0000236 if ((*ConflictPos)[MacroDefLen] != ' ' &&
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000237 (*ConflictPos)[MacroDefLen] != '(')
238 continue; // Longer macro name; keep trying.
Mike Stump1eb44332009-09-09 15:08:12 +0000239
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000240 // We found a conflicting macro definition.
241 break;
242 }
Mike Stump1eb44332009-09-09 15:08:12 +0000243
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000244 if (ConflictPos != CmdLineLines.end()) {
245 Reader.Diag(diag::warn_cmdline_conflicting_macro_def)
246 << MacroName;
247
248 // Show the definition of this macro within the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000249 llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
250 assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
251 SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
252 .getFileLocWithOffset(Offset);
253 Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000254
255 ConflictingDefines = true;
256 continue;
257 }
Mike Stump1eb44332009-09-09 15:08:12 +0000258
Daniel Dunbar10014aa2009-11-11 03:45:59 +0000259 // If the macro doesn't conflict, then we'll just pick up the macro
260 // definition from the PCH file. Warn the user that they made a mistake.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000261 if (ConflictingDefines)
262 continue; // Don't complain if there are already conflicting defs
Mike Stump1eb44332009-09-09 15:08:12 +0000263
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000264 if (!MissingDefines) {
265 Reader.Diag(diag::warn_cmdline_missing_macro_defs);
266 MissingDefines = true;
267 }
268
269 // Show the definition of this macro within the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000270 llvm::StringRef::size_type Offset = PCHPredef.find(Missing);
271 assert(Offset != llvm::StringRef::npos && "Unable to find macro!");
272 SourceLocation PCHMissingLoc = SourceMgr.getLocForStartOfFile(PCHBufferID)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000273 .getFileLocWithOffset(Offset);
274 Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch);
275 }
Mike Stump1eb44332009-09-09 15:08:12 +0000276
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000277 if (ConflictingDefines)
278 return true;
Mike Stump1eb44332009-09-09 15:08:12 +0000279
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000280 // Determine what predefines were introduced based on command-line
281 // parameters that were not present when building the PCH
282 // file. Extra #defines are okay, so long as the identifiers being
283 // defined were not used within the precompiled header.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000284 std::vector<llvm::StringRef> ExtraPredefines;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000285 std::set_difference(CmdLineLines.begin(), CmdLineLines.end(),
286 PCHLines.begin(), PCHLines.end(),
Mike Stump1eb44332009-09-09 15:08:12 +0000287 std::back_inserter(ExtraPredefines));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000288 for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) {
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000289 llvm::StringRef &Extra = ExtraPredefines[I];
290 if (!Extra.startswith("#define ")) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000291 Reader.Diag(diag::warn_pch_compiler_options_mismatch);
292 return true;
293 }
294
295 // This is an extra macro definition. Determine the name of the
296 // macro we're defining.
297 std::string::size_type StartOfMacroName = strlen("#define ");
Mike Stump1eb44332009-09-09 15:08:12 +0000298 std::string::size_type EndOfMacroName
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000299 = Extra.find_first_of("( \n\r", StartOfMacroName);
300 assert(EndOfMacroName != std::string::npos &&
301 "Couldn't find the end of the macro name");
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000302 llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000303
304 // Check whether this name was used somewhere in the PCH file. If
305 // so, defining it as a macro could change behavior, so we reject
306 // the PCH file.
Daniel Dunbar4d5936a2009-11-11 05:26:28 +0000307 if (IdentifierInfo *II = Reader.get(MacroName)) {
Daniel Dunbar4fda42e2009-11-11 00:52:00 +0000308 Reader.Diag(diag::warn_macro_name_used_in_pch) << II;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000309 return true;
310 }
311
312 // Add this definition to the suggested predefines buffer.
313 SuggestedPredefines += Extra;
314 SuggestedPredefines += '\n';
315 }
316
317 // If we get here, it's because the predefines buffer had compatible
318 // contents. Accept the PCH file.
319 return false;
320}
321
322void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI) {
323 PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, NumHeaderInfos++);
324}
325
326void PCHValidator::ReadCounter(unsigned Value) {
327 PP.setCounterValue(Value);
328}
329
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000330//===----------------------------------------------------------------------===//
Douglas Gregor668c1a42009-04-21 22:25:48 +0000331// PCH reader implementation
332//===----------------------------------------------------------------------===//
333
Mike Stump1eb44332009-09-09 15:08:12 +0000334PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,
335 const char *isysroot)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000336 : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),
337 FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()),
Douglas Gregor52e71082009-10-16 18:18:30 +0000338 SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000339 IdentifierTableData(0), IdentifierLookupTable(0),
340 IdentifierOffsets(0),
341 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
342 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000343 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump1eb44332009-09-09 15:08:12 +0000344 NumStatHits(0), NumStatMisses(0),
345 NumSLocEntriesRead(0), NumStatementsRead(0),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000346 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000347 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump1eb44332009-09-09 15:08:12 +0000348 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000349 RelocatablePCH = false;
350}
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000351
352PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,
Mike Stump1eb44332009-09-09 15:08:12 +0000353 Diagnostic &Diags, const char *isysroot)
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000354 : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags),
Douglas Gregor52e71082009-10-16 18:18:30 +0000355 SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),
Chris Lattner4c6f9522009-04-27 05:14:47 +0000356 IdentifierTableData(0), IdentifierLookupTable(0),
357 IdentifierOffsets(0),
358 MethodPoolLookupTable(0), MethodPoolLookupTableData(0),
359 TotalSelectorsInMethodPool(0), SelectorOffsets(0),
Douglas Gregore650c8c2009-07-07 00:12:59 +0000360 TotalNumSelectors(0), Comments(0), NumComments(0), isysroot(isysroot),
Mike Stump1eb44332009-09-09 15:08:12 +0000361 NumStatHits(0), NumStatMisses(0),
362 NumSLocEntriesRead(0), NumStatementsRead(0),
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000363 NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0),
Douglas Gregord89275b2009-07-06 18:54:52 +0000364 NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0),
Mike Stump1eb44332009-09-09 15:08:12 +0000365 CurrentlyLoadingTypeOrDecl(0) {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000366 RelocatablePCH = false;
367}
Chris Lattner4c6f9522009-04-27 05:14:47 +0000368
369PCHReader::~PCHReader() {}
370
Chris Lattnerda930612009-04-27 05:58:23 +0000371Expr *PCHReader::ReadDeclExpr() {
372 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
373}
374
375Expr *PCHReader::ReadTypeExpr() {
Douglas Gregor61d60ee2009-10-17 00:13:19 +0000376 return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
Chris Lattner4c6f9522009-04-27 05:14:47 +0000377}
378
379
Douglas Gregor668c1a42009-04-21 22:25:48 +0000380namespace {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000381class VISIBILITY_HIDDEN PCHMethodPoolLookupTrait {
382 PCHReader &Reader;
383
384public:
385 typedef std::pair<ObjCMethodList, ObjCMethodList> data_type;
386
387 typedef Selector external_key_type;
388 typedef external_key_type internal_key_type;
389
390 explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { }
Mike Stump1eb44332009-09-09 15:08:12 +0000391
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000392 static bool EqualKey(const internal_key_type& a,
393 const internal_key_type& b) {
394 return a == b;
395 }
Mike Stump1eb44332009-09-09 15:08:12 +0000396
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000397 static unsigned ComputeHash(Selector Sel) {
398 unsigned N = Sel.getNumArgs();
399 if (N == 0)
400 ++N;
401 unsigned R = 5381;
402 for (unsigned I = 0; I != N; ++I)
403 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I))
Daniel Dunbar2596e422009-10-17 23:52:28 +0000404 R = llvm::HashString(II->getName(), R);
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000405 return R;
406 }
Mike Stump1eb44332009-09-09 15:08:12 +0000407
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000408 // This hopefully will just get inlined and removed by the optimizer.
409 static const internal_key_type&
410 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump1eb44332009-09-09 15:08:12 +0000411
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000412 static std::pair<unsigned, unsigned>
413 ReadKeyDataLength(const unsigned char*& d) {
414 using namespace clang::io;
415 unsigned KeyLen = ReadUnalignedLE16(d);
416 unsigned DataLen = ReadUnalignedLE16(d);
417 return std::make_pair(KeyLen, DataLen);
418 }
Mike Stump1eb44332009-09-09 15:08:12 +0000419
Douglas Gregor83941df2009-04-25 17:48:32 +0000420 internal_key_type ReadKey(const unsigned char* d, unsigned) {
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000421 using namespace clang::io;
Chris Lattnerd1d64a02009-04-27 21:45:14 +0000422 SelectorTable &SelTable = Reader.getContext()->Selectors;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000423 unsigned N = ReadUnalignedLE16(d);
Mike Stump1eb44332009-09-09 15:08:12 +0000424 IdentifierInfo *FirstII
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000425 = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d));
426 if (N == 0)
427 return SelTable.getNullarySelector(FirstII);
428 else if (N == 1)
429 return SelTable.getUnarySelector(FirstII);
430
431 llvm::SmallVector<IdentifierInfo *, 16> Args;
432 Args.push_back(FirstII);
433 for (unsigned I = 1; I != N; ++I)
434 Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)));
435
Douglas Gregor75fdb232009-05-22 22:45:36 +0000436 return SelTable.getSelector(N, Args.data());
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000437 }
Mike Stump1eb44332009-09-09 15:08:12 +0000438
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000439 data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) {
440 using namespace clang::io;
441 unsigned NumInstanceMethods = ReadUnalignedLE16(d);
442 unsigned NumFactoryMethods = ReadUnalignedLE16(d);
443
444 data_type Result;
445
446 // Load instance methods
447 ObjCMethodList *Prev = 0;
448 for (unsigned I = 0; I != NumInstanceMethods; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000449 ObjCMethodDecl *Method
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000450 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
451 if (!Result.first.Method) {
452 // This is the first method, which is the easy case.
453 Result.first.Method = Method;
454 Prev = &Result.first;
455 continue;
456 }
457
458 Prev->Next = new ObjCMethodList(Method, 0);
459 Prev = Prev->Next;
460 }
461
462 // Load factory methods
463 Prev = 0;
464 for (unsigned I = 0; I != NumFactoryMethods; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000465 ObjCMethodDecl *Method
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000466 = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d)));
467 if (!Result.second.Method) {
468 // This is the first method, which is the easy case.
469 Result.second.Method = Method;
470 Prev = &Result.second;
471 continue;
472 }
473
474 Prev->Next = new ObjCMethodList(Method, 0);
475 Prev = Prev->Next;
476 }
477
478 return Result;
479 }
480};
Mike Stump1eb44332009-09-09 15:08:12 +0000481
482} // end anonymous namespace
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000483
484/// \brief The on-disk hash table used for the global method pool.
Mike Stump1eb44332009-09-09 15:08:12 +0000485typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait>
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +0000486 PCHMethodPoolLookupTable;
487
488namespace {
Douglas Gregor668c1a42009-04-21 22:25:48 +0000489class VISIBILITY_HIDDEN PCHIdentifierLookupTrait {
490 PCHReader &Reader;
491
492 // If we know the IdentifierInfo in advance, it is here and we will
493 // not build a new one. Used when deserializing information about an
494 // identifier that was constructed before the PCH file was read.
495 IdentifierInfo *KnownII;
496
497public:
498 typedef IdentifierInfo * data_type;
499
500 typedef const std::pair<const char*, unsigned> external_key_type;
501
502 typedef external_key_type internal_key_type;
503
Mike Stump1eb44332009-09-09 15:08:12 +0000504 explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0)
Douglas Gregor668c1a42009-04-21 22:25:48 +0000505 : Reader(Reader), KnownII(II) { }
Mike Stump1eb44332009-09-09 15:08:12 +0000506
Douglas Gregor668c1a42009-04-21 22:25:48 +0000507 static bool EqualKey(const internal_key_type& a,
508 const internal_key_type& b) {
509 return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0
510 : false;
511 }
Mike Stump1eb44332009-09-09 15:08:12 +0000512
Douglas Gregor668c1a42009-04-21 22:25:48 +0000513 static unsigned ComputeHash(const internal_key_type& a) {
Daniel Dunbar2596e422009-10-17 23:52:28 +0000514 return llvm::HashString(llvm::StringRef(a.first, a.second));
Douglas Gregor668c1a42009-04-21 22:25:48 +0000515 }
Mike Stump1eb44332009-09-09 15:08:12 +0000516
Douglas Gregor668c1a42009-04-21 22:25:48 +0000517 // This hopefully will just get inlined and removed by the optimizer.
518 static const internal_key_type&
519 GetInternalKey(const external_key_type& x) { return x; }
Mike Stump1eb44332009-09-09 15:08:12 +0000520
Douglas Gregor668c1a42009-04-21 22:25:48 +0000521 static std::pair<unsigned, unsigned>
522 ReadKeyDataLength(const unsigned char*& d) {
523 using namespace clang::io;
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000524 unsigned DataLen = ReadUnalignedLE16(d);
Douglas Gregord6595a42009-04-25 21:04:17 +0000525 unsigned KeyLen = ReadUnalignedLE16(d);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000526 return std::make_pair(KeyLen, DataLen);
527 }
Mike Stump1eb44332009-09-09 15:08:12 +0000528
Douglas Gregor668c1a42009-04-21 22:25:48 +0000529 static std::pair<const char*, unsigned>
530 ReadKey(const unsigned char* d, unsigned n) {
531 assert(n >= 2 && d[n-1] == '\0');
532 return std::make_pair((const char*) d, n-1);
533 }
Mike Stump1eb44332009-09-09 15:08:12 +0000534
535 IdentifierInfo *ReadData(const internal_key_type& k,
Douglas Gregor668c1a42009-04-21 22:25:48 +0000536 const unsigned char* d,
537 unsigned DataLen) {
538 using namespace clang::io;
Douglas Gregora92193e2009-04-28 21:18:29 +0000539 pch::IdentID ID = ReadUnalignedLE32(d);
540 bool IsInteresting = ID & 0x01;
541
542 // Wipe out the "is interesting" bit.
543 ID = ID >> 1;
544
545 if (!IsInteresting) {
546 // For unintersting identifiers, just build the IdentifierInfo
547 // and associate it with the persistent ID.
548 IdentifierInfo *II = KnownII;
549 if (!II)
550 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
551 k.first, k.first + k.second);
552 Reader.SetIdentifierInfo(ID, II);
553 return II;
554 }
555
Douglas Gregor5998da52009-04-28 21:32:13 +0000556 unsigned Bits = ReadUnalignedLE16(d);
Douglas Gregor2deaea32009-04-22 18:49:13 +0000557 bool CPlusPlusOperatorKeyword = Bits & 0x01;
558 Bits >>= 1;
559 bool Poisoned = Bits & 0x01;
560 Bits >>= 1;
561 bool ExtensionToken = Bits & 0x01;
562 Bits >>= 1;
563 bool hasMacroDefinition = Bits & 0x01;
564 Bits >>= 1;
565 unsigned ObjCOrBuiltinID = Bits & 0x3FF;
566 Bits >>= 10;
Mike Stump1eb44332009-09-09 15:08:12 +0000567
Douglas Gregor2deaea32009-04-22 18:49:13 +0000568 assert(Bits == 0 && "Extra bits in the identifier?");
Douglas Gregor5998da52009-04-28 21:32:13 +0000569 DataLen -= 6;
Douglas Gregor668c1a42009-04-21 22:25:48 +0000570
571 // Build the IdentifierInfo itself and link the identifier ID with
572 // the new IdentifierInfo.
573 IdentifierInfo *II = KnownII;
574 if (!II)
Douglas Gregor5f8e3302009-04-25 20:26:24 +0000575 II = &Reader.getIdentifierTable().CreateIdentifierInfo(
576 k.first, k.first + k.second);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000577 Reader.SetIdentifierInfo(ID, II);
578
Douglas Gregor2deaea32009-04-22 18:49:13 +0000579 // Set or check the various bits in the IdentifierInfo structure.
580 // FIXME: Load token IDs lazily, too?
Douglas Gregor2deaea32009-04-22 18:49:13 +0000581 II->setObjCOrBuiltinID(ObjCOrBuiltinID);
Mike Stump1eb44332009-09-09 15:08:12 +0000582 assert(II->isExtensionToken() == ExtensionToken &&
Douglas Gregor2deaea32009-04-22 18:49:13 +0000583 "Incorrect extension token flag");
584 (void)ExtensionToken;
585 II->setIsPoisoned(Poisoned);
586 assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword &&
587 "Incorrect C++ operator keyword flag");
588 (void)CPlusPlusOperatorKeyword;
589
Douglas Gregor37e26842009-04-21 23:56:24 +0000590 // If this identifier is a macro, deserialize the macro
591 // definition.
592 if (hasMacroDefinition) {
Douglas Gregor5998da52009-04-28 21:32:13 +0000593 uint32_t Offset = ReadUnalignedLE32(d);
Douglas Gregor37e26842009-04-21 23:56:24 +0000594 Reader.ReadMacroRecord(Offset);
Douglas Gregor5998da52009-04-28 21:32:13 +0000595 DataLen -= 4;
Douglas Gregor37e26842009-04-21 23:56:24 +0000596 }
Douglas Gregor668c1a42009-04-21 22:25:48 +0000597
598 // Read all of the declarations visible at global scope with this
599 // name.
Chris Lattner6bf690f2009-04-27 22:17:41 +0000600 if (Reader.getContext() == 0) return II;
Douglas Gregord89275b2009-07-06 18:54:52 +0000601 if (DataLen > 0) {
602 llvm::SmallVector<uint32_t, 4> DeclIDs;
603 for (; DataLen > 0; DataLen -= 4)
604 DeclIDs.push_back(ReadUnalignedLE32(d));
605 Reader.SetGloballyVisibleDecls(II, DeclIDs);
Douglas Gregor668c1a42009-04-21 22:25:48 +0000606 }
Mike Stump1eb44332009-09-09 15:08:12 +0000607
Douglas Gregor668c1a42009-04-21 22:25:48 +0000608 return II;
609 }
610};
Mike Stump1eb44332009-09-09 15:08:12 +0000611
612} // end anonymous namespace
Douglas Gregor668c1a42009-04-21 22:25:48 +0000613
614/// \brief The on-disk hash table used to contain information about
615/// all of the identifiers in the program.
Mike Stump1eb44332009-09-09 15:08:12 +0000616typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait>
Douglas Gregor668c1a42009-04-21 22:25:48 +0000617 PCHIdentifierLookupTable;
618
Douglas Gregora02b1472009-04-28 21:53:25 +0000619bool PCHReader::Error(const char *Msg) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000620 unsigned DiagID = Diags.getCustomDiagID(Diagnostic::Fatal, Msg);
621 Diag(DiagID);
Douglas Gregor2cf26342009-04-09 22:27:44 +0000622 return true;
623}
624
Douglas Gregore1d918e2009-04-10 23:10:45 +0000625/// \brief Check the contents of the predefines buffer against the
626/// contents of the predefines buffer used to build the PCH file.
627///
628/// The contents of the two predefines buffers should be the same. If
629/// not, then some command-line option changed the preprocessor state
630/// and we must reject the PCH file.
631///
632/// \param PCHPredef The start of the predefines buffer in the PCH
633/// file.
634///
635/// \param PCHPredefLen The length of the predefines buffer in the PCH
636/// file.
637///
638/// \param PCHBufferID The FileID for the PCH predefines buffer.
639///
640/// \returns true if there was a mismatch (in which case the PCH file
641/// should be ignored), or false otherwise.
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000642bool PCHReader::CheckPredefinesBuffer(llvm::StringRef PCHPredef,
Douglas Gregore1d918e2009-04-10 23:10:45 +0000643 FileID PCHBufferID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000644 if (Listener)
Daniel Dunbardc3c0d22009-11-11 00:52:11 +0000645 return Listener->ReadPredefinesBuffer(PCHPredef, PCHBufferID,
Daniel Dunbar7b5a1212009-11-11 05:29:04 +0000646 ActualOriginalFileName,
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000647 SuggestedPredefines);
Douglas Gregore721f952009-04-28 18:58:38 +0000648 return false;
Douglas Gregore1d918e2009-04-10 23:10:45 +0000649}
650
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000651//===----------------------------------------------------------------------===//
652// Source Manager Deserialization
653//===----------------------------------------------------------------------===//
654
Douglas Gregorbd945002009-04-13 16:31:14 +0000655/// \brief Read the line table in the source manager block.
656/// \returns true if ther was an error.
Douglas Gregore650c8c2009-07-07 00:12:59 +0000657bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000658 unsigned Idx = 0;
659 LineTableInfo &LineTable = SourceMgr.getLineTable();
660
661 // Parse the file names
Douglas Gregorff0a9872009-04-13 17:12:42 +0000662 std::map<int, int> FileIDs;
663 for (int I = 0, N = Record[Idx++]; I != N; ++I) {
Douglas Gregorbd945002009-04-13 16:31:14 +0000664 // Extract the file name
665 unsigned FilenameLen = Record[Idx++];
666 std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen);
667 Idx += FilenameLen;
Douglas Gregore650c8c2009-07-07 00:12:59 +0000668 MaybeAddSystemRootToFilename(Filename);
Mike Stump1eb44332009-09-09 15:08:12 +0000669 FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(),
Douglas Gregorff0a9872009-04-13 17:12:42 +0000670 Filename.size());
Douglas Gregorbd945002009-04-13 16:31:14 +0000671 }
672
673 // Parse the line entries
674 std::vector<LineEntry> Entries;
675 while (Idx < Record.size()) {
Douglas Gregorff0a9872009-04-13 17:12:42 +0000676 int FID = FileIDs[Record[Idx++]];
Douglas Gregorbd945002009-04-13 16:31:14 +0000677
678 // Extract the line entries
679 unsigned NumEntries = Record[Idx++];
680 Entries.clear();
681 Entries.reserve(NumEntries);
682 for (unsigned I = 0; I != NumEntries; ++I) {
683 unsigned FileOffset = Record[Idx++];
684 unsigned LineNo = Record[Idx++];
685 int FilenameID = Record[Idx++];
Mike Stump1eb44332009-09-09 15:08:12 +0000686 SrcMgr::CharacteristicKind FileKind
Douglas Gregorbd945002009-04-13 16:31:14 +0000687 = (SrcMgr::CharacteristicKind)Record[Idx++];
688 unsigned IncludeOffset = Record[Idx++];
689 Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID,
690 FileKind, IncludeOffset));
691 }
692 LineTable.AddEntry(FID, Entries);
693 }
694
695 return false;
696}
697
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000698namespace {
699
700class VISIBILITY_HIDDEN PCHStatData {
701public:
702 const bool hasStat;
703 const ino_t ino;
704 const dev_t dev;
705 const mode_t mode;
706 const time_t mtime;
707 const off_t size;
Mike Stump1eb44332009-09-09 15:08:12 +0000708
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000709 PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s)
Mike Stump1eb44332009-09-09 15:08:12 +0000710 : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {}
711
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000712 PCHStatData()
713 : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {}
714};
715
716class VISIBILITY_HIDDEN PCHStatLookupTrait {
717 public:
718 typedef const char *external_key_type;
719 typedef const char *internal_key_type;
720
721 typedef PCHStatData data_type;
722
723 static unsigned ComputeHash(const char *path) {
Daniel Dunbar2596e422009-10-17 23:52:28 +0000724 return llvm::HashString(path);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000725 }
726
727 static internal_key_type GetInternalKey(const char *path) { return path; }
728
729 static bool EqualKey(internal_key_type a, internal_key_type b) {
730 return strcmp(a, b) == 0;
731 }
732
733 static std::pair<unsigned, unsigned>
734 ReadKeyDataLength(const unsigned char*& d) {
735 unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d);
736 unsigned DataLen = (unsigned) *d++;
737 return std::make_pair(KeyLen + 1, DataLen);
738 }
739
740 static internal_key_type ReadKey(const unsigned char *d, unsigned) {
741 return (const char *)d;
742 }
743
744 static data_type ReadData(const internal_key_type, const unsigned char *d,
745 unsigned /*DataLen*/) {
746 using namespace clang::io;
747
748 if (*d++ == 1)
749 return data_type();
750
751 ino_t ino = (ino_t) ReadUnalignedLE32(d);
752 dev_t dev = (dev_t) ReadUnalignedLE32(d);
753 mode_t mode = (mode_t) ReadUnalignedLE16(d);
Mike Stump1eb44332009-09-09 15:08:12 +0000754 time_t mtime = (time_t) ReadUnalignedLE64(d);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000755 off_t size = (off_t) ReadUnalignedLE64(d);
756 return data_type(ino, dev, mode, mtime, size);
757 }
758};
759
760/// \brief stat() cache for precompiled headers.
761///
762/// This cache is very similar to the stat cache used by pretokenized
763/// headers.
764class VISIBILITY_HIDDEN PCHStatCache : public StatSysCallCache {
765 typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy;
766 CacheTy *Cache;
767
768 unsigned &NumStatHits, &NumStatMisses;
Mike Stump1eb44332009-09-09 15:08:12 +0000769public:
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000770 PCHStatCache(const unsigned char *Buckets,
771 const unsigned char *Base,
772 unsigned &NumStatHits,
Mike Stump1eb44332009-09-09 15:08:12 +0000773 unsigned &NumStatMisses)
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000774 : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) {
775 Cache = CacheTy::Create(Buckets, Base);
776 }
777
778 ~PCHStatCache() { delete Cache; }
Mike Stump1eb44332009-09-09 15:08:12 +0000779
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000780 int stat(const char *path, struct stat *buf) {
781 // Do the lookup for the file's data in the PCH file.
782 CacheTy::iterator I = Cache->find(path);
783
784 // If we don't get a hit in the PCH file just forward to 'stat'.
785 if (I == Cache->end()) {
786 ++NumStatMisses;
Douglas Gregor52e71082009-10-16 18:18:30 +0000787 return StatSysCallCache::stat(path, buf);
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000788 }
Mike Stump1eb44332009-09-09 15:08:12 +0000789
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000790 ++NumStatHits;
791 PCHStatData Data = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000792
Douglas Gregor4fed3f42009-04-27 18:38:38 +0000793 if (!Data.hasStat)
794 return 1;
795
796 buf->st_ino = Data.ino;
797 buf->st_dev = Data.dev;
798 buf->st_mtime = Data.mtime;
799 buf->st_mode = Data.mode;
800 buf->st_size = Data.size;
801 return 0;
802 }
803};
804} // end anonymous namespace
805
806
Douglas Gregor14f79002009-04-10 03:52:48 +0000807/// \brief Read the source manager block
Douglas Gregore1d918e2009-04-10 23:10:45 +0000808PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() {
Douglas Gregor14f79002009-04-10 03:52:48 +0000809 using namespace SrcMgr;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000810
811 // Set the source-location entry cursor to the current position in
812 // the stream. This cursor will be used to read the contents of the
813 // source manager block initially, and then lazily read
814 // source-location entries as needed.
815 SLocEntryCursor = Stream;
816
817 // The stream itself is going to skip over the source manager block.
818 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000819 Error("malformed block record in PCH file");
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000820 return Failure;
821 }
822
823 // Enter the source manager block.
824 if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000825 Error("malformed source manager block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000826 return Failure;
827 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000828
Douglas Gregor14f79002009-04-10 03:52:48 +0000829 RecordData Record;
830 while (true) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000831 unsigned Code = SLocEntryCursor.ReadCode();
Douglas Gregor14f79002009-04-10 03:52:48 +0000832 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000833 if (SLocEntryCursor.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000834 Error("error at end of Source Manager block in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000835 return Failure;
836 }
Douglas Gregore1d918e2009-04-10 23:10:45 +0000837 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000838 }
Mike Stump1eb44332009-09-09 15:08:12 +0000839
Douglas Gregor14f79002009-04-10 03:52:48 +0000840 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
841 // No known subblocks, always skip them.
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000842 SLocEntryCursor.ReadSubBlockID();
843 if (SLocEntryCursor.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000844 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +0000845 return Failure;
846 }
Douglas Gregor14f79002009-04-10 03:52:48 +0000847 continue;
848 }
Mike Stump1eb44332009-09-09 15:08:12 +0000849
Douglas Gregor14f79002009-04-10 03:52:48 +0000850 if (Code == llvm::bitc::DEFINE_ABBREV) {
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000851 SLocEntryCursor.ReadAbbrevRecord();
Douglas Gregor14f79002009-04-10 03:52:48 +0000852 continue;
853 }
Mike Stump1eb44332009-09-09 15:08:12 +0000854
Douglas Gregor14f79002009-04-10 03:52:48 +0000855 // Read a record.
856 const char *BlobStart;
857 unsigned BlobLen;
858 Record.clear();
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000859 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
Douglas Gregor14f79002009-04-10 03:52:48 +0000860 default: // Default behavior: ignore.
861 break;
862
Chris Lattner2c78b872009-04-14 23:22:57 +0000863 case pch::SM_LINE_TABLE:
Douglas Gregore650c8c2009-07-07 00:12:59 +0000864 if (ParseLineTable(Record))
Douglas Gregorbd945002009-04-13 16:31:14 +0000865 return Failure;
Chris Lattner2c78b872009-04-14 23:22:57 +0000866 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000867
868 case pch::SM_HEADER_FILE_INFO: {
869 HeaderFileInfo HFI;
870 HFI.isImport = Record[0];
871 HFI.DirInfo = Record[1];
872 HFI.NumIncludes = Record[2];
873 HFI.ControllingMacroID = Record[3];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +0000874 if (Listener)
875 Listener->ReadHeaderFileInfo(HFI);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +0000876 break;
877 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000878
879 case pch::SM_SLOC_FILE_ENTRY:
880 case pch::SM_SLOC_BUFFER_ENTRY:
881 case pch::SM_SLOC_INSTANTIATION_ENTRY:
882 // Once we hit one of the source location entries, we're done.
883 return Success;
Douglas Gregor14f79002009-04-10 03:52:48 +0000884 }
885 }
886}
887
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000888/// \brief Read in the source location entry with the given ID.
889PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) {
890 if (ID == 0)
891 return Success;
892
893 if (ID > TotalNumSLocEntries) {
894 Error("source location entry ID out-of-range for PCH file");
895 return Failure;
896 }
897
898 ++NumSLocEntriesRead;
899 SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]);
900 unsigned Code = SLocEntryCursor.ReadCode();
901 if (Code == llvm::bitc::END_BLOCK ||
902 Code == llvm::bitc::ENTER_SUBBLOCK ||
903 Code == llvm::bitc::DEFINE_ABBREV) {
904 Error("incorrectly-formatted source location entry in PCH file");
905 return Failure;
906 }
907
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000908 RecordData Record;
909 const char *BlobStart;
910 unsigned BlobLen;
911 switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) {
912 default:
913 Error("incorrectly-formatted source location entry in PCH file");
914 return Failure;
915
916 case pch::SM_SLOC_FILE_ENTRY: {
Douglas Gregore650c8c2009-07-07 00:12:59 +0000917 std::string Filename(BlobStart, BlobStart + BlobLen);
918 MaybeAddSystemRootToFilename(Filename);
919 const FileEntry *File = FileMgr.getFile(Filename);
Chris Lattnerd3555ae2009-06-15 04:35:16 +0000920 if (File == 0) {
921 std::string ErrorStr = "could not find file '";
Douglas Gregore650c8c2009-07-07 00:12:59 +0000922 ErrorStr += Filename;
Chris Lattnerd3555ae2009-06-15 04:35:16 +0000923 ErrorStr += "' referenced by PCH file";
924 Error(ErrorStr.c_str());
925 return Failure;
926 }
Mike Stump1eb44332009-09-09 15:08:12 +0000927
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000928 FileID FID = SourceMgr.createFileID(File,
929 SourceLocation::getFromRawEncoding(Record[1]),
930 (SrcMgr::CharacteristicKind)Record[2],
931 ID, Record[0]);
932 if (Record[3])
933 const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile())
934 .setHasLineDirectives();
935
936 break;
937 }
938
939 case pch::SM_SLOC_BUFFER_ENTRY: {
940 const char *Name = BlobStart;
941 unsigned Offset = Record[0];
942 unsigned Code = SLocEntryCursor.ReadCode();
943 Record.clear();
Mike Stump1eb44332009-09-09 15:08:12 +0000944 unsigned RecCode
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000945 = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen);
946 assert(RecCode == pch::SM_SLOC_BUFFER_BLOB && "Ill-formed PCH file");
947 (void)RecCode;
948 llvm::MemoryBuffer *Buffer
Mike Stump1eb44332009-09-09 15:08:12 +0000949 = llvm::MemoryBuffer::getMemBuffer(BlobStart,
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000950 BlobStart + BlobLen - 1,
951 Name);
952 FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset);
Mike Stump1eb44332009-09-09 15:08:12 +0000953
Douglas Gregor92b059e2009-04-28 20:33:11 +0000954 if (strcmp(Name, "<built-in>") == 0) {
955 PCHPredefinesBufferID = BufferID;
956 PCHPredefines = BlobStart;
957 PCHPredefinesLen = BlobLen - 1;
958 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000959
960 break;
961 }
962
963 case pch::SM_SLOC_INSTANTIATION_ENTRY: {
Mike Stump1eb44332009-09-09 15:08:12 +0000964 SourceLocation SpellingLoc
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000965 = SourceLocation::getFromRawEncoding(Record[1]);
966 SourceMgr.createInstantiationLoc(SpellingLoc,
967 SourceLocation::getFromRawEncoding(Record[2]),
968 SourceLocation::getFromRawEncoding(Record[3]),
969 Record[4],
970 ID,
971 Record[0]);
972 break;
Mike Stump1eb44332009-09-09 15:08:12 +0000973 }
Douglas Gregor7f94b0b2009-04-27 06:38:32 +0000974 }
975
976 return Success;
977}
978
Chris Lattner6367f6d2009-04-27 01:05:14 +0000979/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the
980/// specified cursor. Read the abbreviations that are at the top of the block
981/// and then leave the cursor pointing into the block.
982bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor,
983 unsigned BlockID) {
984 if (Cursor.EnterSubBlock(BlockID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +0000985 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +0000986 return Failure;
987 }
Mike Stump1eb44332009-09-09 15:08:12 +0000988
Chris Lattner6367f6d2009-04-27 01:05:14 +0000989 while (true) {
990 unsigned Code = Cursor.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +0000991
Chris Lattner6367f6d2009-04-27 01:05:14 +0000992 // We expect all abbrevs to be at the start of the block.
993 if (Code != llvm::bitc::DEFINE_ABBREV)
994 return false;
995 Cursor.ReadAbbrevRecord();
996 }
997}
998
Douglas Gregor37e26842009-04-21 23:56:24 +0000999void PCHReader::ReadMacroRecord(uint64_t Offset) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001000 assert(PP && "Forgot to set Preprocessor ?");
Mike Stump1eb44332009-09-09 15:08:12 +00001001
Douglas Gregor37e26842009-04-21 23:56:24 +00001002 // Keep track of where we are in the stream, then jump back there
1003 // after reading this macro.
1004 SavedStreamPosition SavedPosition(Stream);
1005
1006 Stream.JumpToBit(Offset);
1007 RecordData Record;
1008 llvm::SmallVector<IdentifierInfo*, 16> MacroArgs;
1009 MacroInfo *Macro = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001010
Douglas Gregor37e26842009-04-21 23:56:24 +00001011 while (true) {
1012 unsigned Code = Stream.ReadCode();
1013 switch (Code) {
1014 case llvm::bitc::END_BLOCK:
1015 return;
1016
1017 case llvm::bitc::ENTER_SUBBLOCK:
1018 // No known subblocks, always skip them.
1019 Stream.ReadSubBlockID();
1020 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001021 Error("malformed block record in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001022 return;
1023 }
1024 continue;
Mike Stump1eb44332009-09-09 15:08:12 +00001025
Douglas Gregor37e26842009-04-21 23:56:24 +00001026 case llvm::bitc::DEFINE_ABBREV:
1027 Stream.ReadAbbrevRecord();
1028 continue;
1029 default: break;
1030 }
1031
1032 // Read a record.
1033 Record.clear();
1034 pch::PreprocessorRecordTypes RecType =
1035 (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record);
1036 switch (RecType) {
Douglas Gregor37e26842009-04-21 23:56:24 +00001037 case pch::PP_MACRO_OBJECT_LIKE:
1038 case pch::PP_MACRO_FUNCTION_LIKE: {
1039 // If we already have a macro, that means that we've hit the end
1040 // of the definition of the macro we were looking for. We're
1041 // done.
1042 if (Macro)
1043 return;
1044
1045 IdentifierInfo *II = DecodeIdentifierInfo(Record[0]);
1046 if (II == 0) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001047 Error("macro must have a name in PCH file");
Douglas Gregor37e26842009-04-21 23:56:24 +00001048 return;
1049 }
1050 SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]);
1051 bool isUsed = Record[2];
Mike Stump1eb44332009-09-09 15:08:12 +00001052
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001053 MacroInfo *MI = PP->AllocateMacroInfo(Loc);
Douglas Gregor37e26842009-04-21 23:56:24 +00001054 MI->setIsUsed(isUsed);
Mike Stump1eb44332009-09-09 15:08:12 +00001055
Douglas Gregor37e26842009-04-21 23:56:24 +00001056 if (RecType == pch::PP_MACRO_FUNCTION_LIKE) {
1057 // Decode function-like macro info.
1058 bool isC99VarArgs = Record[3];
1059 bool isGNUVarArgs = Record[4];
1060 MacroArgs.clear();
1061 unsigned NumArgs = Record[5];
1062 for (unsigned i = 0; i != NumArgs; ++i)
1063 MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i]));
1064
1065 // Install function-like macro info.
1066 MI->setIsFunctionLike();
1067 if (isC99VarArgs) MI->setIsC99Varargs();
1068 if (isGNUVarArgs) MI->setIsGNUVarargs();
Douglas Gregor75fdb232009-05-22 22:45:36 +00001069 MI->setArgumentList(MacroArgs.data(), MacroArgs.size(),
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001070 PP->getPreprocessorAllocator());
Douglas Gregor37e26842009-04-21 23:56:24 +00001071 }
1072
1073 // Finally, install the macro.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001074 PP->setMacroInfo(II, MI);
Douglas Gregor37e26842009-04-21 23:56:24 +00001075
1076 // Remember that we saw this macro last so that we add the tokens that
1077 // form its body to it.
1078 Macro = MI;
1079 ++NumMacrosRead;
1080 break;
1081 }
Mike Stump1eb44332009-09-09 15:08:12 +00001082
Douglas Gregor37e26842009-04-21 23:56:24 +00001083 case pch::PP_TOKEN: {
1084 // If we see a TOKEN before a PP_MACRO_*, then the file is
1085 // erroneous, just pretend we didn't see this.
1086 if (Macro == 0) break;
Mike Stump1eb44332009-09-09 15:08:12 +00001087
Douglas Gregor37e26842009-04-21 23:56:24 +00001088 Token Tok;
1089 Tok.startToken();
1090 Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0]));
1091 Tok.setLength(Record[1]);
1092 if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2]))
1093 Tok.setIdentifierInfo(II);
1094 Tok.setKind((tok::TokenKind)Record[3]);
1095 Tok.setFlag((Token::TokenFlags)Record[4]);
1096 Macro->AddTokenToBody(Tok);
1097 break;
1098 }
Steve Naroff83d63c72009-04-24 20:03:17 +00001099 }
Douglas Gregor37e26842009-04-21 23:56:24 +00001100 }
1101}
1102
Douglas Gregore650c8c2009-07-07 00:12:59 +00001103/// \brief If we are loading a relocatable PCH file, and the filename is
1104/// not an absolute path, add the system root to the beginning of the file
1105/// name.
1106void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) {
1107 // If this is not a relocatable PCH file, there's nothing to do.
1108 if (!RelocatablePCH)
1109 return;
Mike Stump1eb44332009-09-09 15:08:12 +00001110
Douglas Gregore650c8c2009-07-07 00:12:59 +00001111 if (Filename.empty() || Filename[0] == '/' || Filename[0] == '<')
1112 return;
1113
1114 std::string FIXME = Filename;
Mike Stump1eb44332009-09-09 15:08:12 +00001115
Douglas Gregore650c8c2009-07-07 00:12:59 +00001116 if (isysroot == 0) {
1117 // If no system root was given, default to '/'
1118 Filename.insert(Filename.begin(), '/');
1119 return;
1120 }
Mike Stump1eb44332009-09-09 15:08:12 +00001121
Douglas Gregore650c8c2009-07-07 00:12:59 +00001122 unsigned Length = strlen(isysroot);
1123 if (isysroot[Length - 1] != '/')
1124 Filename.insert(Filename.begin(), '/');
Mike Stump1eb44332009-09-09 15:08:12 +00001125
Douglas Gregore650c8c2009-07-07 00:12:59 +00001126 Filename.insert(Filename.begin(), isysroot, isysroot + Length);
1127}
1128
Mike Stump1eb44332009-09-09 15:08:12 +00001129PCHReader::PCHReadResult
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001130PCHReader::ReadPCHBlock() {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001131 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001132 Error("malformed block record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001133 return Failure;
1134 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001135
1136 // Read all of the records and blocks for the PCH file.
Douglas Gregor8038d512009-04-10 17:25:41 +00001137 RecordData Record;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001138 while (!Stream.AtEndOfStream()) {
1139 unsigned Code = Stream.ReadCode();
1140 if (Code == llvm::bitc::END_BLOCK) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001141 if (Stream.ReadBlockEnd()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001142 Error("error at end of module block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001143 return Failure;
1144 }
Chris Lattner7356a312009-04-11 21:15:38 +00001145
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001146 return Success;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001147 }
1148
1149 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1150 switch (Stream.ReadSubBlockID()) {
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001151 case pch::DECLTYPES_BLOCK_ID:
Chris Lattner6367f6d2009-04-27 01:05:14 +00001152 // We lazily load the decls block, but we want to set up the
1153 // DeclsCursor cursor to point into it. Clone our current bitcode
1154 // cursor to it, enter the block and read the abbrevs in that block.
1155 // With the main cursor, we just skip over it.
1156 DeclsCursor = Stream;
1157 if (Stream.SkipBlock() || // Skip with the main cursor.
1158 // Read the abbrevs.
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001159 ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001160 Error("malformed block record in PCH file");
Chris Lattner6367f6d2009-04-27 01:05:14 +00001161 return Failure;
1162 }
1163 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001164
Chris Lattner7356a312009-04-11 21:15:38 +00001165 case pch::PREPROCESSOR_BLOCK_ID:
Chris Lattner7356a312009-04-11 21:15:38 +00001166 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001167 Error("malformed block record in PCH file");
Chris Lattner7356a312009-04-11 21:15:38 +00001168 return Failure;
1169 }
1170 break;
Steve Naroff90cd1bb2009-04-23 10:39:46 +00001171
Douglas Gregor14f79002009-04-10 03:52:48 +00001172 case pch::SOURCE_MANAGER_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001173 switch (ReadSourceManagerBlock()) {
1174 case Success:
1175 break;
1176
1177 case Failure:
Douglas Gregora02b1472009-04-28 21:53:25 +00001178 Error("malformed source manager block in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001179 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001180
1181 case IgnorePCH:
1182 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001183 }
Douglas Gregor14f79002009-04-10 03:52:48 +00001184 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001185 }
Douglas Gregor8038d512009-04-10 17:25:41 +00001186 continue;
1187 }
1188
1189 if (Code == llvm::bitc::DEFINE_ABBREV) {
1190 Stream.ReadAbbrevRecord();
1191 continue;
1192 }
1193
1194 // Read and process a record.
1195 Record.clear();
Douglas Gregor2bec0412009-04-10 21:16:55 +00001196 const char *BlobStart = 0;
1197 unsigned BlobLen = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001198 switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record,
Douglas Gregor2bec0412009-04-10 21:16:55 +00001199 &BlobStart, &BlobLen)) {
Douglas Gregor8038d512009-04-10 17:25:41 +00001200 default: // Default behavior: ignore.
1201 break;
1202
1203 case pch::TYPE_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001204 if (!TypesLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001205 Error("duplicate TYPE_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001206 return Failure;
1207 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001208 TypeOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001209 TypesLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001210 break;
1211
1212 case pch::DECL_OFFSET:
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001213 if (!DeclsLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001214 Error("duplicate DECL_OFFSET record in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001215 return Failure;
1216 }
Chris Lattnerc732f5a2009-04-27 18:24:17 +00001217 DeclOffsets = (const uint32_t *)BlobStart;
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00001218 DeclsLoaded.resize(Record[0]);
Douglas Gregor8038d512009-04-10 17:25:41 +00001219 break;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001220
1221 case pch::LANGUAGE_OPTIONS:
1222 if (ParseLanguageOptions(Record))
1223 return IgnorePCH;
1224 break;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001225
Douglas Gregorab41e632009-04-27 22:23:34 +00001226 case pch::METADATA: {
1227 if (Record[0] != pch::VERSION_MAJOR) {
1228 Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old
1229 : diag::warn_pch_version_too_new);
1230 return IgnorePCH;
1231 }
1232
Douglas Gregore650c8c2009-07-07 00:12:59 +00001233 RelocatablePCH = Record[4];
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001234 if (Listener) {
1235 std::string TargetTriple(BlobStart, BlobLen);
1236 if (Listener->ReadTargetTriple(TargetTriple))
1237 return IgnorePCH;
Douglas Gregor2bec0412009-04-10 21:16:55 +00001238 }
1239 break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001240 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001241
1242 case pch::IDENTIFIER_TABLE:
Douglas Gregor668c1a42009-04-21 22:25:48 +00001243 IdentifierTableData = BlobStart;
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001244 if (Record[0]) {
Mike Stump1eb44332009-09-09 15:08:12 +00001245 IdentifierLookupTable
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001246 = PCHIdentifierLookupTable::Create(
Douglas Gregor668c1a42009-04-21 22:25:48 +00001247 (const unsigned char *)IdentifierTableData + Record[0],
Mike Stump1eb44332009-09-09 15:08:12 +00001248 (const unsigned char *)IdentifierTableData,
Douglas Gregor668c1a42009-04-21 22:25:48 +00001249 PCHIdentifierLookupTrait(*this));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001250 if (PP)
1251 PP->getIdentifierTable().setExternalIdentifierLookup(this);
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001252 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001253 break;
1254
1255 case pch::IDENTIFIER_OFFSET:
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001256 if (!IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001257 Error("duplicate IDENTIFIER_OFFSET record in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00001258 return Failure;
1259 }
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00001260 IdentifierOffsets = (const uint32_t *)BlobStart;
1261 IdentifiersLoaded.resize(Record[0]);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001262 if (PP)
1263 PP->getHeaderSearchInfo().SetExternalLookup(this);
Douglas Gregorafaf3082009-04-11 00:14:32 +00001264 break;
Douglas Gregorfdd01722009-04-14 00:24:19 +00001265
1266 case pch::EXTERNAL_DEFINITIONS:
1267 if (!ExternalDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001268 Error("duplicate EXTERNAL_DEFINITIONS record in PCH file");
Douglas Gregorfdd01722009-04-14 00:24:19 +00001269 return Failure;
1270 }
1271 ExternalDefinitions.swap(Record);
1272 break;
Douglas Gregor3e1af842009-04-17 22:13:46 +00001273
Douglas Gregorad1de002009-04-18 05:55:16 +00001274 case pch::SPECIAL_TYPES:
1275 SpecialTypes.swap(Record);
1276 break;
1277
Douglas Gregor3e1af842009-04-17 22:13:46 +00001278 case pch::STATISTICS:
1279 TotalNumStatements = Record[0];
Douglas Gregor37e26842009-04-21 23:56:24 +00001280 TotalNumMacros = Record[1];
Douglas Gregor25123082009-04-22 22:34:57 +00001281 TotalLexicalDeclContexts = Record[2];
1282 TotalVisibleDeclContexts = Record[3];
Douglas Gregor3e1af842009-04-17 22:13:46 +00001283 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001284
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001285 case pch::TENTATIVE_DEFINITIONS:
1286 if (!TentativeDefinitions.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001287 Error("duplicate TENTATIVE_DEFINITIONS record in PCH file");
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00001288 return Failure;
1289 }
1290 TentativeDefinitions.swap(Record);
1291 break;
Douglas Gregor14c22f22009-04-22 22:18:58 +00001292
1293 case pch::LOCALLY_SCOPED_EXTERNAL_DECLS:
1294 if (!LocallyScopedExternalDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001295 Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file");
Douglas Gregor14c22f22009-04-22 22:18:58 +00001296 return Failure;
1297 }
1298 LocallyScopedExternalDecls.swap(Record);
1299 break;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001300
Douglas Gregor83941df2009-04-25 17:48:32 +00001301 case pch::SELECTOR_OFFSETS:
1302 SelectorOffsets = (const uint32_t *)BlobStart;
1303 TotalNumSelectors = Record[0];
1304 SelectorsLoaded.resize(TotalNumSelectors);
1305 break;
1306
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001307 case pch::METHOD_POOL:
Douglas Gregor83941df2009-04-25 17:48:32 +00001308 MethodPoolLookupTableData = (const unsigned char *)BlobStart;
1309 if (Record[0])
Mike Stump1eb44332009-09-09 15:08:12 +00001310 MethodPoolLookupTable
Douglas Gregor83941df2009-04-25 17:48:32 +00001311 = PCHMethodPoolLookupTable::Create(
1312 MethodPoolLookupTableData + Record[0],
Mike Stump1eb44332009-09-09 15:08:12 +00001313 MethodPoolLookupTableData,
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001314 PCHMethodPoolLookupTrait(*this));
Douglas Gregor83941df2009-04-25 17:48:32 +00001315 TotalSelectorsInMethodPool = Record[1];
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00001316 break;
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001317
1318 case pch::PP_COUNTER_VALUE:
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001319 if (!Record.empty() && Listener)
1320 Listener->ReadCounter(Record[0]);
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001321 break;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001322
1323 case pch::SOURCE_LOCATION_OFFSETS:
Chris Lattner090d9b52009-04-27 19:01:47 +00001324 SLocOffsets = (const uint32_t *)BlobStart;
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001325 TotalNumSLocEntries = Record[0];
Douglas Gregor445e23e2009-10-05 21:07:28 +00001326 SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00001327 break;
1328
1329 case pch::SOURCE_LOCATION_PRELOADS:
1330 for (unsigned I = 0, N = Record.size(); I != N; ++I) {
1331 PCHReadResult Result = ReadSLocEntryRecord(Record[I]);
1332 if (Result != Success)
1333 return Result;
1334 }
1335 break;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001336
Douglas Gregor52e71082009-10-16 18:18:30 +00001337 case pch::STAT_CACHE: {
1338 PCHStatCache *MyStatCache =
1339 new PCHStatCache((const unsigned char *)BlobStart + Record[0],
1340 (const unsigned char *)BlobStart,
1341 NumStatHits, NumStatMisses);
1342 FileMgr.addStatCache(MyStatCache);
1343 StatCache = MyStatCache;
Douglas Gregor4fed3f42009-04-27 18:38:38 +00001344 break;
Douglas Gregor52e71082009-10-16 18:18:30 +00001345 }
1346
Douglas Gregorb81c1702009-04-27 20:06:05 +00001347 case pch::EXT_VECTOR_DECLS:
1348 if (!ExtVectorDecls.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001349 Error("duplicate EXT_VECTOR_DECLS record in PCH file");
Douglas Gregorb81c1702009-04-27 20:06:05 +00001350 return Failure;
1351 }
1352 ExtVectorDecls.swap(Record);
1353 break;
1354
Douglas Gregorb64c1932009-05-12 01:31:05 +00001355 case pch::ORIGINAL_FILE_NAME:
Daniel Dunbar7b5a1212009-11-11 05:29:04 +00001356 ActualOriginalFileName.assign(BlobStart, BlobLen);
1357 OriginalFileName = ActualOriginalFileName;
Douglas Gregore650c8c2009-07-07 00:12:59 +00001358 MaybeAddSystemRootToFilename(OriginalFileName);
Douglas Gregorb64c1932009-05-12 01:31:05 +00001359 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001360
Douglas Gregor2e222532009-07-02 17:08:52 +00001361 case pch::COMMENT_RANGES:
1362 Comments = (SourceRange *)BlobStart;
1363 NumComments = BlobLen / sizeof(SourceRange);
1364 break;
Douglas Gregor445e23e2009-10-05 21:07:28 +00001365
1366 case pch::SVN_BRANCH_REVISION: {
1367 unsigned CurRevision = getClangSubversionRevision();
1368 if (Record[0] && CurRevision && Record[0] != CurRevision) {
1369 Diag(Record[0] < CurRevision? diag::warn_pch_version_too_old
1370 : diag::warn_pch_version_too_new);
1371 return IgnorePCH;
1372 }
1373
1374 const char *CurBranch = getClangSubversionPath();
1375 if (strncmp(CurBranch, BlobStart, BlobLen)) {
1376 std::string PCHBranch(BlobStart, BlobLen);
1377 Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch;
1378 return IgnorePCH;
1379 }
1380 break;
1381 }
Douglas Gregorafaf3082009-04-11 00:14:32 +00001382 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001383 }
Douglas Gregora02b1472009-04-28 21:53:25 +00001384 Error("premature end of bitstream in PCH file");
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001385 return Failure;
Douglas Gregor2cf26342009-04-09 22:27:44 +00001386}
1387
Douglas Gregore1d918e2009-04-10 23:10:45 +00001388PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001389 // Set the PCH file name.
1390 this->FileName = FileName;
1391
Douglas Gregor2cf26342009-04-09 22:27:44 +00001392 // Open the PCH file.
Daniel Dunbarf3c740e2009-09-22 05:38:01 +00001393 //
1394 // FIXME: This shouldn't be here, we should just take a raw_ostream.
Douglas Gregor2cf26342009-04-09 22:27:44 +00001395 std::string ErrStr;
Daniel Dunbar731ad8f2009-11-10 00:46:19 +00001396 Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr));
Douglas Gregore1d918e2009-04-10 23:10:45 +00001397 if (!Buffer) {
1398 Error(ErrStr.c_str());
1399 return IgnorePCH;
1400 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001401
1402 // Initialize the stream
Mike Stump1eb44332009-09-09 15:08:12 +00001403 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Chris Lattnerb9fa9172009-04-26 20:59:20 +00001404 (const unsigned char *)Buffer->getBufferEnd());
1405 Stream.init(StreamFile);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001406
1407 // Sniff for the signature.
1408 if (Stream.Read(8) != 'C' ||
1409 Stream.Read(8) != 'P' ||
1410 Stream.Read(8) != 'C' ||
Douglas Gregore1d918e2009-04-10 23:10:45 +00001411 Stream.Read(8) != 'H') {
Douglas Gregora02b1472009-04-28 21:53:25 +00001412 Diag(diag::err_not_a_pch_file) << FileName;
1413 return Failure;
Douglas Gregore1d918e2009-04-10 23:10:45 +00001414 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001415
Douglas Gregor2cf26342009-04-09 22:27:44 +00001416 while (!Stream.AtEndOfStream()) {
1417 unsigned Code = Stream.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +00001418
Douglas Gregore1d918e2009-04-10 23:10:45 +00001419 if (Code != llvm::bitc::ENTER_SUBBLOCK) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001420 Error("invalid record at top-level of PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001421 return Failure;
1422 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001423
1424 unsigned BlockID = Stream.ReadSubBlockID();
Douglas Gregor668c1a42009-04-21 22:25:48 +00001425
Douglas Gregor2cf26342009-04-09 22:27:44 +00001426 // We only know the PCH subblock ID.
1427 switch (BlockID) {
1428 case llvm::bitc::BLOCKINFO_BLOCK_ID:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001429 if (Stream.ReadBlockInfoBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001430 Error("malformed BlockInfoBlock in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001431 return Failure;
1432 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001433 break;
1434 case pch::PCH_BLOCK_ID:
Douglas Gregor2eafc1b2009-04-26 00:07:37 +00001435 switch (ReadPCHBlock()) {
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001436 case Success:
1437 break;
1438
1439 case Failure:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001440 return Failure;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001441
1442 case IgnorePCH:
Douglas Gregor2bec0412009-04-10 21:16:55 +00001443 // FIXME: We could consider reading through to the end of this
1444 // PCH block, skipping subblocks, to see if there are other
1445 // PCH blocks elsewhere.
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001446
1447 // Clear out any preallocated source location entries, so that
1448 // the source manager does not try to resolve them later.
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001449 SourceMgr.ClearPreallocatedSLocEntries();
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001450
1451 // Remove the stat cache.
Douglas Gregor52e71082009-10-16 18:18:30 +00001452 if (StatCache)
1453 FileMgr.removeStatCache((PCHStatCache*)StatCache);
Douglas Gregor2bf1eb02009-04-27 21:28:04 +00001454
Douglas Gregore1d918e2009-04-10 23:10:45 +00001455 return IgnorePCH;
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001456 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001457 break;
1458 default:
Douglas Gregore1d918e2009-04-10 23:10:45 +00001459 if (Stream.SkipBlock()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001460 Error("malformed block record in PCH file");
Douglas Gregore1d918e2009-04-10 23:10:45 +00001461 return Failure;
1462 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001463 break;
1464 }
Mike Stump1eb44332009-09-09 15:08:12 +00001465 }
1466
Douglas Gregor92b059e2009-04-28 20:33:11 +00001467 // Check the predefines buffer.
Daniel Dunbardc3c0d22009-11-11 00:52:11 +00001468 if (CheckPredefinesBuffer(llvm::StringRef(PCHPredefines, PCHPredefinesLen),
Douglas Gregor92b059e2009-04-28 20:33:11 +00001469 PCHPredefinesBufferID))
1470 return IgnorePCH;
Mike Stump1eb44332009-09-09 15:08:12 +00001471
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001472 if (PP) {
Zhongxing Xu08996212009-07-18 09:26:51 +00001473 // Initialization of keywords and pragmas occurs before the
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001474 // PCH file is read, so there may be some identifiers that were
1475 // loaded into the IdentifierTable before we intercepted the
1476 // creation of identifiers. Iterate through the list of known
1477 // identifiers and determine whether we have to establish
1478 // preprocessor definitions or top-level identifier declaration
1479 // chains for those identifiers.
1480 //
1481 // We copy the IdentifierInfo pointers to a small vector first,
1482 // since de-serializing declarations or macro definitions can add
1483 // new entries into the identifier table, invalidating the
1484 // iterators.
1485 llvm::SmallVector<IdentifierInfo *, 128> Identifiers;
1486 for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(),
1487 IdEnd = PP->getIdentifierTable().end();
1488 Id != IdEnd; ++Id)
1489 Identifiers.push_back(Id->second);
Mike Stump1eb44332009-09-09 15:08:12 +00001490 PCHIdentifierLookupTable *IdTable
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001491 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
1492 for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) {
1493 IdentifierInfo *II = Identifiers[I];
1494 // Look in the on-disk hash table for an entry for
1495 PCHIdentifierLookupTrait Info(*this, II);
Daniel Dunbare013d682009-10-18 20:26:12 +00001496 std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001497 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);
1498 if (Pos == IdTable->end())
1499 continue;
Mike Stump1eb44332009-09-09 15:08:12 +00001500
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001501 // Dereferencing the iterator has the effect of populating the
1502 // IdentifierInfo node with the various declarations it needs.
1503 (void)*Pos;
1504 }
Douglas Gregor668c1a42009-04-21 22:25:48 +00001505 }
1506
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001507 if (Context)
1508 InitializeContext(*Context);
Douglas Gregor0b748912009-04-14 21:18:50 +00001509
Douglas Gregor668c1a42009-04-21 22:25:48 +00001510 return Success;
Douglas Gregor0b748912009-04-14 21:18:50 +00001511}
1512
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001513void PCHReader::InitializeContext(ASTContext &Ctx) {
1514 Context = &Ctx;
1515 assert(Context && "Passed null context!");
1516
1517 assert(PP && "Forgot to set Preprocessor ?");
1518 PP->getIdentifierTable().setExternalIdentifierLookup(this);
1519 PP->getHeaderSearchInfo().SetExternalLookup(this);
Mike Stump1eb44332009-09-09 15:08:12 +00001520
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001521 // Load the translation unit declaration
1522 ReadDeclRecord(DeclOffsets[0], 0);
1523
1524 // Load the special types.
1525 Context->setBuiltinVaListType(
1526 GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST]));
1527 if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID])
1528 Context->setObjCIdType(GetType(Id));
1529 if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR])
1530 Context->setObjCSelType(GetType(Sel));
1531 if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL])
1532 Context->setObjCProtoType(GetType(Proto));
1533 if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS])
1534 Context->setObjCClassType(GetType(Class));
Steve Naroff14108da2009-07-10 23:34:53 +00001535
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001536 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING])
1537 Context->setCFConstantStringType(GetType(String));
Mike Stump1eb44332009-09-09 15:08:12 +00001538 if (unsigned FastEnum
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001539 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE])
1540 Context->setObjCFastEnumerationStateType(GetType(FastEnum));
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001541 if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) {
1542 QualType FileType = GetType(File);
1543 assert(!FileType.isNull() && "FILE type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001544 if (const TypedefType *Typedef = FileType->getAs<TypedefType>())
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001545 Context->setFILEDecl(Typedef->getDecl());
1546 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001547 const TagType *Tag = FileType->getAs<TagType>();
Douglas Gregorc29f77b2009-07-07 16:35:42 +00001548 assert(Tag && "Invalid FILE type in PCH file");
1549 Context->setFILEDecl(Tag->getDecl());
1550 }
1551 }
Mike Stump782fa302009-07-28 02:25:19 +00001552 if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) {
1553 QualType Jmp_bufType = GetType(Jmp_buf);
1554 assert(!Jmp_bufType.isNull() && "jmp_bug type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001555 if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>())
Mike Stump782fa302009-07-28 02:25:19 +00001556 Context->setjmp_bufDecl(Typedef->getDecl());
1557 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001558 const TagType *Tag = Jmp_bufType->getAs<TagType>();
Mike Stump782fa302009-07-28 02:25:19 +00001559 assert(Tag && "Invalid jmp_bug type in PCH file");
1560 Context->setjmp_bufDecl(Tag->getDecl());
1561 }
1562 }
1563 if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) {
1564 QualType Sigjmp_bufType = GetType(Sigjmp_buf);
1565 assert(!Sigjmp_bufType.isNull() && "sigjmp_buf type is NULL");
John McCall183700f2009-09-21 23:43:11 +00001566 if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>())
Mike Stump782fa302009-07-28 02:25:19 +00001567 Context->setsigjmp_bufDecl(Typedef->getDecl());
1568 else {
Ted Kremenek6217b802009-07-29 21:53:49 +00001569 const TagType *Tag = Sigjmp_bufType->getAs<TagType>();
Mike Stump782fa302009-07-28 02:25:19 +00001570 assert(Tag && "Invalid sigjmp_buf type in PCH file");
1571 Context->setsigjmp_bufDecl(Tag->getDecl());
1572 }
1573 }
Mike Stump1eb44332009-09-09 15:08:12 +00001574 if (unsigned ObjCIdRedef
Douglas Gregord1571ac2009-08-21 00:27:50 +00001575 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION])
1576 Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef);
Mike Stump1eb44332009-09-09 15:08:12 +00001577 if (unsigned ObjCClassRedef
Douglas Gregord1571ac2009-08-21 00:27:50 +00001578 = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])
1579 Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef);
Mike Stumpadaaad32009-10-20 02:12:22 +00001580 if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR])
1581 Context->setBlockDescriptorType(GetType(String));
Mike Stump083c25e2009-10-22 00:49:09 +00001582 if (unsigned String
1583 = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR])
1584 Context->setBlockDescriptorExtendedType(GetType(String));
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001585}
1586
Douglas Gregorb64c1932009-05-12 01:31:05 +00001587/// \brief Retrieve the name of the original source file name
1588/// directly from the PCH file, without actually loading the PCH
1589/// file.
1590std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName) {
1591 // Open the PCH file.
1592 std::string ErrStr;
1593 llvm::OwningPtr<llvm::MemoryBuffer> Buffer;
1594 Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr));
1595 if (!Buffer) {
1596 fprintf(stderr, "error: %s\n", ErrStr.c_str());
1597 return std::string();
1598 }
1599
1600 // Initialize the stream
1601 llvm::BitstreamReader StreamFile;
1602 llvm::BitstreamCursor Stream;
Mike Stump1eb44332009-09-09 15:08:12 +00001603 StreamFile.init((const unsigned char *)Buffer->getBufferStart(),
Douglas Gregorb64c1932009-05-12 01:31:05 +00001604 (const unsigned char *)Buffer->getBufferEnd());
1605 Stream.init(StreamFile);
1606
1607 // Sniff for the signature.
1608 if (Stream.Read(8) != 'C' ||
1609 Stream.Read(8) != 'P' ||
1610 Stream.Read(8) != 'C' ||
1611 Stream.Read(8) != 'H') {
Mike Stump1eb44332009-09-09 15:08:12 +00001612 fprintf(stderr,
Douglas Gregorb64c1932009-05-12 01:31:05 +00001613 "error: '%s' does not appear to be a precompiled header file\n",
1614 PCHFileName.c_str());
1615 return std::string();
1616 }
1617
1618 RecordData Record;
1619 while (!Stream.AtEndOfStream()) {
1620 unsigned Code = Stream.ReadCode();
Mike Stump1eb44332009-09-09 15:08:12 +00001621
Douglas Gregorb64c1932009-05-12 01:31:05 +00001622 if (Code == llvm::bitc::ENTER_SUBBLOCK) {
1623 unsigned BlockID = Stream.ReadSubBlockID();
Mike Stump1eb44332009-09-09 15:08:12 +00001624
Douglas Gregorb64c1932009-05-12 01:31:05 +00001625 // We only know the PCH subblock ID.
1626 switch (BlockID) {
1627 case pch::PCH_BLOCK_ID:
1628 if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
1629 fprintf(stderr, "error: malformed block record in PCH file\n");
1630 return std::string();
1631 }
1632 break;
Mike Stump1eb44332009-09-09 15:08:12 +00001633
Douglas Gregorb64c1932009-05-12 01:31:05 +00001634 default:
1635 if (Stream.SkipBlock()) {
1636 fprintf(stderr, "error: malformed block record in PCH file\n");
1637 return std::string();
1638 }
1639 break;
1640 }
1641 continue;
1642 }
1643
1644 if (Code == llvm::bitc::END_BLOCK) {
1645 if (Stream.ReadBlockEnd()) {
1646 fprintf(stderr, "error: error at end of module block in PCH file\n");
1647 return std::string();
1648 }
1649 continue;
1650 }
1651
1652 if (Code == llvm::bitc::DEFINE_ABBREV) {
1653 Stream.ReadAbbrevRecord();
1654 continue;
1655 }
1656
1657 Record.clear();
1658 const char *BlobStart = 0;
1659 unsigned BlobLen = 0;
Mike Stump1eb44332009-09-09 15:08:12 +00001660 if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen)
Douglas Gregorb64c1932009-05-12 01:31:05 +00001661 == pch::ORIGINAL_FILE_NAME)
1662 return std::string(BlobStart, BlobLen);
Mike Stump1eb44332009-09-09 15:08:12 +00001663 }
Douglas Gregorb64c1932009-05-12 01:31:05 +00001664
1665 return std::string();
1666}
1667
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001668/// \brief Parse the record that corresponds to a LangOptions data
1669/// structure.
1670///
1671/// This routine compares the language options used to generate the
1672/// PCH file against the language options set for the current
1673/// compilation. For each option, we classify differences between the
1674/// two compiler states as either "benign" or "important". Benign
1675/// differences don't matter, and we accept them without complaint
1676/// (and without modifying the language options). Differences between
1677/// the states for important options cause the PCH file to be
1678/// unusable, so we emit a warning and return true to indicate that
1679/// there was an error.
1680///
1681/// \returns true if the PCH file is unacceptable, false otherwise.
1682bool PCHReader::ParseLanguageOptions(
1683 const llvm::SmallVectorImpl<uint64_t> &Record) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001684 if (Listener) {
1685 LangOptions LangOpts;
Mike Stump1eb44332009-09-09 15:08:12 +00001686
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001687 #define PARSE_LANGOPT(Option) \
1688 LangOpts.Option = Record[Idx]; \
1689 ++Idx
Mike Stump1eb44332009-09-09 15:08:12 +00001690
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001691 unsigned Idx = 0;
1692 PARSE_LANGOPT(Trigraphs);
1693 PARSE_LANGOPT(BCPLComment);
1694 PARSE_LANGOPT(DollarIdents);
1695 PARSE_LANGOPT(AsmPreprocessor);
1696 PARSE_LANGOPT(GNUMode);
1697 PARSE_LANGOPT(ImplicitInt);
1698 PARSE_LANGOPT(Digraphs);
1699 PARSE_LANGOPT(HexFloats);
1700 PARSE_LANGOPT(C99);
1701 PARSE_LANGOPT(Microsoft);
1702 PARSE_LANGOPT(CPlusPlus);
1703 PARSE_LANGOPT(CPlusPlus0x);
1704 PARSE_LANGOPT(CXXOperatorNames);
1705 PARSE_LANGOPT(ObjC1);
1706 PARSE_LANGOPT(ObjC2);
1707 PARSE_LANGOPT(ObjCNonFragileABI);
1708 PARSE_LANGOPT(PascalStrings);
1709 PARSE_LANGOPT(WritableStrings);
1710 PARSE_LANGOPT(LaxVectorConversions);
Nate Begemanb9e7e632009-06-25 23:01:11 +00001711 PARSE_LANGOPT(AltiVec);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001712 PARSE_LANGOPT(Exceptions);
1713 PARSE_LANGOPT(NeXTRuntime);
1714 PARSE_LANGOPT(Freestanding);
1715 PARSE_LANGOPT(NoBuiltin);
1716 PARSE_LANGOPT(ThreadsafeStatics);
Douglas Gregor972d9542009-09-03 14:36:33 +00001717 PARSE_LANGOPT(POSIXThreads);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001718 PARSE_LANGOPT(Blocks);
1719 PARSE_LANGOPT(EmitAllDecls);
1720 PARSE_LANGOPT(MathErrno);
1721 PARSE_LANGOPT(OverflowChecking);
1722 PARSE_LANGOPT(HeinousExtensions);
1723 PARSE_LANGOPT(Optimize);
1724 PARSE_LANGOPT(OptimizeSize);
1725 PARSE_LANGOPT(Static);
1726 PARSE_LANGOPT(PICLevel);
1727 PARSE_LANGOPT(GNUInline);
1728 PARSE_LANGOPT(NoInline);
1729 PARSE_LANGOPT(AccessControl);
1730 PARSE_LANGOPT(CharIsSigned);
John Thompsona6fda122009-11-05 20:14:16 +00001731 PARSE_LANGOPT(ShortWChar);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001732 LangOpts.setGCMode((LangOptions::GCMode)Record[Idx]);
1733 ++Idx;
1734 LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx]);
1735 ++Idx;
Daniel Dunbarab8e2812009-09-21 04:16:19 +00001736 LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
1737 Record[Idx]);
1738 ++Idx;
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001739 PARSE_LANGOPT(InstantiationDepth);
Nate Begemanb9e7e632009-06-25 23:01:11 +00001740 PARSE_LANGOPT(OpenCL);
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001741 #undef PARSE_LANGOPT
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001742
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00001743 return Listener->ReadLanguageOptions(LangOpts);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001744 }
Douglas Gregor0a0428e2009-04-10 20:39:37 +00001745
1746 return false;
1747}
1748
Douglas Gregor2e222532009-07-02 17:08:52 +00001749void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {
1750 Comments.resize(NumComments);
1751 std::copy(this->Comments, this->Comments + NumComments,
1752 Comments.begin());
1753}
1754
Douglas Gregor2cf26342009-04-09 22:27:44 +00001755/// \brief Read and return the type at the given offset.
1756///
1757/// This routine actually reads the record corresponding to the type
1758/// at the given offset in the bitstream. It is a helper routine for
1759/// GetType, which deals with reading type IDs.
1760QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
Douglas Gregor0b748912009-04-14 21:18:50 +00001761 // Keep track of where we are in the stream, then jump back there
1762 // after reading this type.
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001763 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00001764
Douglas Gregord89275b2009-07-06 18:54:52 +00001765 // Note that we are loading a type record.
1766 LoadingTypeOrDecl Loading(*this);
Mike Stump1eb44332009-09-09 15:08:12 +00001767
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001768 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001769 RecordData Record;
Douglas Gregor61d60ee2009-10-17 00:13:19 +00001770 unsigned Code = DeclsCursor.ReadCode();
1771 switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
Douglas Gregor6d473962009-04-15 22:00:08 +00001772 case pch::TYPE_EXT_QUAL: {
John McCall0953e762009-09-24 19:53:00 +00001773 assert(Record.size() == 2 &&
Douglas Gregor6d473962009-04-15 22:00:08 +00001774 "Incorrect encoding of extended qualifier type");
1775 QualType Base = GetType(Record[0]);
John McCall0953e762009-09-24 19:53:00 +00001776 Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]);
1777 return Context->getQualifiedType(Base, Quals);
Douglas Gregor6d473962009-04-15 22:00:08 +00001778 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001779
Douglas Gregor2cf26342009-04-09 22:27:44 +00001780 case pch::TYPE_FIXED_WIDTH_INT: {
1781 assert(Record.size() == 2 && "Incorrect encoding of fixed-width int type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001782 return Context->getFixedWidthIntType(Record[0], Record[1]);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001783 }
1784
1785 case pch::TYPE_COMPLEX: {
1786 assert(Record.size() == 1 && "Incorrect encoding of complex type");
1787 QualType ElemType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001788 return Context->getComplexType(ElemType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001789 }
1790
1791 case pch::TYPE_POINTER: {
1792 assert(Record.size() == 1 && "Incorrect encoding of pointer type");
1793 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001794 return Context->getPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001795 }
1796
1797 case pch::TYPE_BLOCK_POINTER: {
1798 assert(Record.size() == 1 && "Incorrect encoding of block pointer type");
1799 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001800 return Context->getBlockPointerType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001801 }
1802
1803 case pch::TYPE_LVALUE_REFERENCE: {
1804 assert(Record.size() == 1 && "Incorrect encoding of lvalue reference type");
1805 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001806 return Context->getLValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001807 }
1808
1809 case pch::TYPE_RVALUE_REFERENCE: {
1810 assert(Record.size() == 1 && "Incorrect encoding of rvalue reference type");
1811 QualType PointeeType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001812 return Context->getRValueReferenceType(PointeeType);
Douglas Gregor2cf26342009-04-09 22:27:44 +00001813 }
1814
1815 case pch::TYPE_MEMBER_POINTER: {
1816 assert(Record.size() == 1 && "Incorrect encoding of member pointer type");
1817 QualType PointeeType = GetType(Record[0]);
1818 QualType ClassType = GetType(Record[1]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001819 return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr());
Douglas Gregor2cf26342009-04-09 22:27:44 +00001820 }
1821
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001822 case pch::TYPE_CONSTANT_ARRAY: {
1823 QualType ElementType = GetType(Record[0]);
1824 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1825 unsigned IndexTypeQuals = Record[2];
1826 unsigned Idx = 3;
1827 llvm::APInt Size = ReadAPInt(Record, Idx);
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001828 return Context->getConstantArrayType(ElementType, Size,
1829 ASM, IndexTypeQuals);
1830 }
1831
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001832 case pch::TYPE_INCOMPLETE_ARRAY: {
1833 QualType ElementType = GetType(Record[0]);
1834 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1835 unsigned IndexTypeQuals = Record[2];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001836 return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001837 }
1838
1839 case pch::TYPE_VARIABLE_ARRAY: {
Douglas Gregor0b748912009-04-14 21:18:50 +00001840 QualType ElementType = GetType(Record[0]);
1841 ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1];
1842 unsigned IndexTypeQuals = Record[2];
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001843 SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]);
1844 SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001845 return Context->getVariableArrayType(ElementType, ReadTypeExpr(),
Douglas Gregor7e7eb3d2009-07-06 15:59:29 +00001846 ASM, IndexTypeQuals,
1847 SourceRange(LBLoc, RBLoc));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001848 }
1849
1850 case pch::TYPE_VECTOR: {
1851 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001852 Error("incorrect encoding of vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001853 return QualType();
1854 }
1855
1856 QualType ElementType = GetType(Record[0]);
1857 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001858 return Context->getVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001859 }
1860
1861 case pch::TYPE_EXT_VECTOR: {
1862 if (Record.size() != 2) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001863 Error("incorrect encoding of extended vector type in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001864 return QualType();
1865 }
1866
1867 QualType ElementType = GetType(Record[0]);
1868 unsigned NumElements = Record[1];
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001869 return Context->getExtVectorType(ElementType, NumElements);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001870 }
1871
1872 case pch::TYPE_FUNCTION_NO_PROTO: {
1873 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001874 Error("incorrect encoding of no-proto function type");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001875 return QualType();
1876 }
1877 QualType ResultType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001878 return Context->getFunctionNoProtoType(ResultType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001879 }
1880
1881 case pch::TYPE_FUNCTION_PROTO: {
1882 QualType ResultType = GetType(Record[0]);
1883 unsigned Idx = 1;
1884 unsigned NumParams = Record[Idx++];
1885 llvm::SmallVector<QualType, 16> ParamTypes;
1886 for (unsigned I = 0; I != NumParams; ++I)
1887 ParamTypes.push_back(GetType(Record[Idx++]));
1888 bool isVariadic = Record[Idx++];
1889 unsigned Quals = Record[Idx++];
Sebastian Redl465226e2009-05-27 22:11:52 +00001890 bool hasExceptionSpec = Record[Idx++];
1891 bool hasAnyExceptionSpec = Record[Idx++];
1892 unsigned NumExceptions = Record[Idx++];
1893 llvm::SmallVector<QualType, 2> Exceptions;
1894 for (unsigned I = 0; I != NumExceptions; ++I)
1895 Exceptions.push_back(GetType(Record[Idx++]));
Jay Foadbeaaccd2009-05-21 09:52:38 +00001896 return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams,
Sebastian Redl465226e2009-05-27 22:11:52 +00001897 isVariadic, Quals, hasExceptionSpec,
1898 hasAnyExceptionSpec, NumExceptions,
1899 Exceptions.data());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001900 }
1901
1902 case pch::TYPE_TYPEDEF:
Douglas Gregora02b1472009-04-28 21:53:25 +00001903 assert(Record.size() == 1 && "incorrect encoding of typedef type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001904 return Context->getTypeDeclType(cast<TypedefDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001905
1906 case pch::TYPE_TYPEOF_EXPR:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001907 return Context->getTypeOfExprType(ReadTypeExpr());
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001908
1909 case pch::TYPE_TYPEOF: {
1910 if (Record.size() != 1) {
Douglas Gregora02b1472009-04-28 21:53:25 +00001911 Error("incorrect encoding of typeof(type) in PCH file");
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001912 return QualType();
1913 }
1914 QualType UnderlyingType = GetType(Record[0]);
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001915 return Context->getTypeOfType(UnderlyingType);
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001916 }
Mike Stump1eb44332009-09-09 15:08:12 +00001917
Anders Carlsson395b4752009-06-24 19:06:50 +00001918 case pch::TYPE_DECLTYPE:
1919 return Context->getDecltypeType(ReadTypeExpr());
1920
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001921 case pch::TYPE_RECORD:
Douglas Gregora02b1472009-04-28 21:53:25 +00001922 assert(Record.size() == 1 && "incorrect encoding of record type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001923 return Context->getTypeDeclType(cast<RecordDecl>(GetDecl(Record[0])));
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001924
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001925 case pch::TYPE_ENUM:
Douglas Gregora02b1472009-04-28 21:53:25 +00001926 assert(Record.size() == 1 && "incorrect encoding of enum type");
Chris Lattnerd1d64a02009-04-27 21:45:14 +00001927 return Context->getTypeDeclType(cast<EnumDecl>(GetDecl(Record[0])));
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00001928
John McCall7da24312009-09-05 00:15:47 +00001929 case pch::TYPE_ELABORATED: {
1930 assert(Record.size() == 2 && "incorrect encoding of elaborated type");
1931 unsigned Tag = Record[1];
1932 return Context->getElaboratedType(GetType(Record[0]),
1933 (ElaboratedType::TagKind) Tag);
1934 }
1935
Steve Naroffc15cb2a2009-07-18 15:33:26 +00001936 case pch::TYPE_OBJC_INTERFACE: {
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001937 unsigned Idx = 0;
1938 ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++]));
1939 unsigned NumProtos = Record[Idx++];
1940 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1941 for (unsigned I = 0; I != NumProtos; ++I)
1942 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroffc15cb2a2009-07-18 15:33:26 +00001943 return Context->getObjCInterfaceType(ItfD, Protos.data(), NumProtos);
Chris Lattnerc6fa4452009-04-22 06:45:28 +00001944 }
Douglas Gregorb4e715b2009-04-13 20:46:52 +00001945
Steve Naroffd1b3c2d2009-06-17 22:40:22 +00001946 case pch::TYPE_OBJC_OBJECT_POINTER: {
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001947 unsigned Idx = 0;
Steve Naroff14108da2009-07-10 23:34:53 +00001948 QualType OIT = GetType(Record[Idx++]);
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001949 unsigned NumProtos = Record[Idx++];
1950 llvm::SmallVector<ObjCProtocolDecl*, 4> Protos;
1951 for (unsigned I = 0; I != NumProtos; ++I)
1952 Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++])));
Steve Naroff14108da2009-07-10 23:34:53 +00001953 return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);
Chris Lattnerd7a3fcd2009-04-22 06:40:03 +00001954 }
Argyrios Kyrtzidis24fab412009-09-29 19:42:55 +00001955
John McCall49a832b2009-10-18 09:09:24 +00001956 case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {
1957 unsigned Idx = 0;
1958 QualType Parm = GetType(Record[Idx++]);
1959 QualType Replacement = GetType(Record[Idx++]);
1960 return
1961 Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm),
1962 Replacement);
1963 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001964 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00001965 // Suppress a GCC warning
1966 return QualType();
1967}
1968
John McCalla1ee0c52009-10-16 21:56:05 +00001969namespace {
1970
1971class TypeLocReader : public TypeLocVisitor<TypeLocReader> {
1972 PCHReader &Reader;
1973 const PCHReader::RecordData &Record;
1974 unsigned &Idx;
1975
1976public:
1977 TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record,
1978 unsigned &Idx)
1979 : Reader(Reader), Record(Record), Idx(Idx) { }
1980
John McCall51bd8032009-10-18 01:05:36 +00001981 // We want compile-time assurance that we've enumerated all of
1982 // these, so unfortunately we have to declare them first, then
1983 // define them out-of-line.
1984#define ABSTRACT_TYPELOC(CLASS, PARENT)
John McCalla1ee0c52009-10-16 21:56:05 +00001985#define TYPELOC(CLASS, PARENT) \
John McCall51bd8032009-10-18 01:05:36 +00001986 void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc);
John McCalla1ee0c52009-10-16 21:56:05 +00001987#include "clang/AST/TypeLocNodes.def"
1988
John McCall51bd8032009-10-18 01:05:36 +00001989 void VisitFunctionTypeLoc(FunctionTypeLoc);
1990 void VisitArrayTypeLoc(ArrayTypeLoc);
John McCalla1ee0c52009-10-16 21:56:05 +00001991};
1992
1993}
1994
John McCall51bd8032009-10-18 01:05:36 +00001995void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
John McCalla1ee0c52009-10-16 21:56:05 +00001996 // nothing to do
1997}
John McCall51bd8032009-10-18 01:05:36 +00001998void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
1999 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002000}
John McCall51bd8032009-10-18 01:05:36 +00002001void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) {
2002 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002003}
John McCall51bd8032009-10-18 01:05:36 +00002004void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) {
2005 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002006}
John McCall51bd8032009-10-18 01:05:36 +00002007void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) {
2008 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002009}
John McCall51bd8032009-10-18 01:05:36 +00002010void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
2011 TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002012}
John McCall51bd8032009-10-18 01:05:36 +00002013void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
2014 TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002015}
John McCall51bd8032009-10-18 01:05:36 +00002016void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
2017 TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002018}
John McCall51bd8032009-10-18 01:05:36 +00002019void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
2020 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002021}
John McCall51bd8032009-10-18 01:05:36 +00002022void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) {
2023 TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2024 TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002025 if (Record[Idx++])
John McCall51bd8032009-10-18 01:05:36 +00002026 TL.setSizeExpr(Reader.ReadDeclExpr());
Douglas Gregor61d60ee2009-10-17 00:13:19 +00002027 else
John McCall51bd8032009-10-18 01:05:36 +00002028 TL.setSizeExpr(0);
2029}
2030void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) {
2031 VisitArrayTypeLoc(TL);
2032}
2033void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) {
2034 VisitArrayTypeLoc(TL);
2035}
2036void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) {
2037 VisitArrayTypeLoc(TL);
2038}
2039void TypeLocReader::VisitDependentSizedArrayTypeLoc(
2040 DependentSizedArrayTypeLoc TL) {
2041 VisitArrayTypeLoc(TL);
2042}
2043void TypeLocReader::VisitDependentSizedExtVectorTypeLoc(
2044 DependentSizedExtVectorTypeLoc TL) {
2045 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2046}
2047void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
2048 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2049}
2050void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
2051 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2052}
2053void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
2054 TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2055 TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2056 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) {
John McCall86acc2a2009-10-23 01:28:53 +00002057 TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++])));
John McCall51bd8032009-10-18 01:05:36 +00002058 }
2059}
2060void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) {
2061 VisitFunctionTypeLoc(TL);
2062}
2063void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) {
2064 VisitFunctionTypeLoc(TL);
2065}
2066void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
2067 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2068}
2069void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
2070 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2071}
2072void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
2073 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2074}
2075void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) {
2076 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2077}
2078void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) {
2079 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2080}
2081void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) {
2082 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2083}
2084void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
2085 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2086}
2087void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) {
2088 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2089}
John McCall49a832b2009-10-18 09:09:24 +00002090void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc(
2091 SubstTemplateTypeParmTypeLoc TL) {
2092 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2093}
John McCall51bd8032009-10-18 01:05:36 +00002094void TypeLocReader::VisitTemplateSpecializationTypeLoc(
2095 TemplateSpecializationTypeLoc TL) {
John McCall833ca992009-10-29 08:12:44 +00002096 TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2097 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2098 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2099 for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i)
2100 TL.setArgLocInfo(i,
2101 Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(),
2102 Record, Idx));
John McCall51bd8032009-10-18 01:05:36 +00002103}
2104void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) {
2105 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2106}
2107void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) {
2108 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2109}
2110void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
2111 TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCall51bd8032009-10-18 01:05:36 +00002112 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2113 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2114 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2115 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
John McCalla1ee0c52009-10-16 21:56:05 +00002116}
John McCall54e14c42009-10-22 22:37:11 +00002117void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
2118 TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2119 TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2120 TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
2121 TL.setHasBaseTypeAsWritten(Record[Idx++]);
2122 TL.setHasProtocolsAsWritten(Record[Idx++]);
2123 if (TL.hasProtocolsAsWritten())
2124 for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i)
2125 TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++]));
2126}
John McCalla1ee0c52009-10-16 21:56:05 +00002127
2128DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,
2129 unsigned &Idx) {
2130 QualType InfoTy = GetType(Record[Idx++]);
2131 if (InfoTy.isNull())
2132 return 0;
2133
2134 DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy);
2135 TypeLocReader TLR(*this, Record, Idx);
2136 for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc())
2137 TLR.Visit(TL);
2138 return DInfo;
2139}
Douglas Gregor2cf26342009-04-09 22:27:44 +00002140
Douglas Gregor8038d512009-04-10 17:25:41 +00002141QualType PCHReader::GetType(pch::TypeID ID) {
John McCall0953e762009-09-24 19:53:00 +00002142 unsigned FastQuals = ID & Qualifiers::FastMask;
2143 unsigned Index = ID >> Qualifiers::FastWidth;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002144
2145 if (Index < pch::NUM_PREDEF_TYPE_IDS) {
2146 QualType T;
2147 switch ((pch::PredefinedTypeIDs)Index) {
2148 case pch::PREDEF_TYPE_NULL_ID: return QualType();
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002149 case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break;
2150 case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002151
2152 case pch::PREDEF_TYPE_CHAR_U_ID:
2153 case pch::PREDEF_TYPE_CHAR_S_ID:
2154 // FIXME: Check that the signedness of CharTy is correct!
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002155 T = Context->CharTy;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002156 break;
2157
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002158 case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break;
2159 case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break;
2160 case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break;
2161 case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break;
2162 case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00002163 case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002164 case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break;
2165 case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break;
2166 case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break;
2167 case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break;
2168 case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break;
2169 case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break;
Chris Lattner2df9ced2009-04-30 02:43:43 +00002170 case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break;
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002171 case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break;
2172 case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break;
2173 case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break;
2174 case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break;
2175 case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break;
Sebastian Redl6e8ed162009-05-10 18:38:11 +00002176 case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break;
Alisdair Meredithf5c209d2009-07-14 06:30:34 +00002177 case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break;
2178 case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break;
Steve Naroffde2e22d2009-07-15 18:40:39 +00002179 case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break;
2180 case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002181 }
2182
2183 assert(!T.isNull() && "Unknown predefined type");
John McCall0953e762009-09-24 19:53:00 +00002184 return T.withFastQualifiers(FastQuals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002185 }
2186
2187 Index -= pch::NUM_PREDEF_TYPE_IDS;
Steve Naroffc15cb2a2009-07-18 15:33:26 +00002188 //assert(Index < TypesLoaded.size() && "Type index out-of-range");
John McCall0953e762009-09-24 19:53:00 +00002189 if (TypesLoaded[Index].isNull())
2190 TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]);
Mike Stump1eb44332009-09-09 15:08:12 +00002191
John McCall0953e762009-09-24 19:53:00 +00002192 return TypesLoaded[Index].withFastQualifiers(FastQuals);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002193}
2194
John McCall833ca992009-10-29 08:12:44 +00002195TemplateArgumentLocInfo
2196PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind,
2197 const RecordData &Record,
2198 unsigned &Index) {
2199 switch (Kind) {
2200 case TemplateArgument::Expression:
2201 return ReadDeclExpr();
2202 case TemplateArgument::Type:
2203 return GetDeclaratorInfo(Record, Index);
Douglas Gregor788cd062009-11-11 01:00:40 +00002204 case TemplateArgument::Template: {
2205 SourceLocation
2206 QualStart = SourceLocation::getFromRawEncoding(Record[Index++]),
2207 QualEnd = SourceLocation::getFromRawEncoding(Record[Index++]),
2208 TemplateNameLoc = SourceLocation::getFromRawEncoding(Record[Index++]);
2209 return TemplateArgumentLocInfo(SourceRange(QualStart, QualEnd),
2210 TemplateNameLoc);
2211 }
John McCall833ca992009-10-29 08:12:44 +00002212 case TemplateArgument::Null:
2213 case TemplateArgument::Integral:
2214 case TemplateArgument::Declaration:
2215 case TemplateArgument::Pack:
2216 return TemplateArgumentLocInfo();
2217 }
2218 llvm::llvm_unreachable("unexpected template argument loc");
2219 return TemplateArgumentLocInfo();
2220}
2221
Douglas Gregor8038d512009-04-10 17:25:41 +00002222Decl *PCHReader::GetDecl(pch::DeclID ID) {
Douglas Gregor2cf26342009-04-09 22:27:44 +00002223 if (ID == 0)
2224 return 0;
2225
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002226 if (ID > DeclsLoaded.size()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002227 Error("declaration ID out-of-range for PCH file");
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002228 return 0;
2229 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00002230
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002231 unsigned Index = ID - 1;
2232 if (!DeclsLoaded[Index])
2233 ReadDeclRecord(DeclOffsets[Index], Index);
2234
2235 return DeclsLoaded[Index];
Douglas Gregor2cf26342009-04-09 22:27:44 +00002236}
2237
Chris Lattner887e2b32009-04-27 05:46:25 +00002238/// \brief Resolve the offset of a statement into a statement.
2239///
2240/// This operation will read a new statement from the external
2241/// source each time it is called, and is meant to be used via a
2242/// LazyOffsetPtr (which is used by Decls for the body of functions, etc).
2243Stmt *PCHReader::GetDeclStmt(uint64_t Offset) {
Chris Lattnerda930612009-04-27 05:58:23 +00002244 // Since we know tha this statement is part of a decl, make sure to use the
2245 // decl cursor to read it.
2246 DeclsCursor.JumpToBit(Offset);
2247 return ReadStmt(DeclsCursor);
Douglas Gregor250fc9c2009-04-18 00:07:54 +00002248}
2249
Douglas Gregor2cf26342009-04-09 22:27:44 +00002250bool PCHReader::ReadDeclsLexicallyInContext(DeclContext *DC,
Douglas Gregor8038d512009-04-10 17:25:41 +00002251 llvm::SmallVectorImpl<pch::DeclID> &Decls) {
Mike Stump1eb44332009-09-09 15:08:12 +00002252 assert(DC->hasExternalLexicalStorage() &&
Douglas Gregor2cf26342009-04-09 22:27:44 +00002253 "DeclContext has no lexical decls in storage");
2254 uint64_t Offset = DeclContextOffsets[DC].first;
2255 assert(Offset && "DeclContext has no lexical decls in storage");
2256
Douglas Gregor0b748912009-04-14 21:18:50 +00002257 // Keep track of where we are in the stream, then jump back there
2258 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002259 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00002260
Douglas Gregor2cf26342009-04-09 22:27:44 +00002261 // Load the record containing all of the declarations lexically in
2262 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002263 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002264 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002265 unsigned Code = DeclsCursor.ReadCode();
2266 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00002267 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002268 assert(RecCode == pch::DECL_CONTEXT_LEXICAL && "Expected lexical block");
2269
2270 // Load all of the declaration IDs
2271 Decls.clear();
2272 Decls.insert(Decls.end(), Record.begin(), Record.end());
Douglas Gregor25123082009-04-22 22:34:57 +00002273 ++NumLexicalDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002274 return false;
2275}
2276
2277bool PCHReader::ReadDeclsVisibleInContext(DeclContext *DC,
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002278 llvm::SmallVectorImpl<VisibleDeclaration> &Decls) {
Mike Stump1eb44332009-09-09 15:08:12 +00002279 assert(DC->hasExternalVisibleStorage() &&
Douglas Gregor2cf26342009-04-09 22:27:44 +00002280 "DeclContext has no visible decls in storage");
2281 uint64_t Offset = DeclContextOffsets[DC].second;
2282 assert(Offset && "DeclContext has no visible decls in storage");
2283
Douglas Gregor0b748912009-04-14 21:18:50 +00002284 // Keep track of where we are in the stream, then jump back there
2285 // after reading this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002286 SavedStreamPosition SavedPosition(DeclsCursor);
Douglas Gregor0b748912009-04-14 21:18:50 +00002287
Douglas Gregor2cf26342009-04-09 22:27:44 +00002288 // Load the record containing all of the declarations visible in
2289 // this context.
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002290 DeclsCursor.JumpToBit(Offset);
Douglas Gregor2cf26342009-04-09 22:27:44 +00002291 RecordData Record;
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002292 unsigned Code = DeclsCursor.ReadCode();
2293 unsigned RecCode = DeclsCursor.ReadRecord(Code, Record);
Douglas Gregor6a2bfb22009-04-15 18:43:11 +00002294 (void)RecCode;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002295 assert(RecCode == pch::DECL_CONTEXT_VISIBLE && "Expected visible block");
2296 if (Record.size() == 0)
Mike Stump1eb44332009-09-09 15:08:12 +00002297 return false;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002298
2299 Decls.clear();
2300
2301 unsigned Idx = 0;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002302 while (Idx < Record.size()) {
2303 Decls.push_back(VisibleDeclaration());
2304 Decls.back().Name = ReadDeclarationName(Record, Idx);
2305
Douglas Gregor2cf26342009-04-09 22:27:44 +00002306 unsigned Size = Record[Idx++];
Chris Lattnerc47be9e2009-04-27 07:35:40 +00002307 llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002308 LoadedDecls.reserve(Size);
2309 for (unsigned I = 0; I < Size; ++I)
2310 LoadedDecls.push_back(Record[Idx++]);
2311 }
2312
Douglas Gregor25123082009-04-22 22:34:57 +00002313 ++NumVisibleDeclContextsRead;
Douglas Gregor2cf26342009-04-09 22:27:44 +00002314 return false;
2315}
2316
Douglas Gregorfdd01722009-04-14 00:24:19 +00002317void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) {
Douglas Gregor0af2ca42009-04-22 19:09:20 +00002318 this->Consumer = Consumer;
2319
Douglas Gregorfdd01722009-04-14 00:24:19 +00002320 if (!Consumer)
2321 return;
2322
2323 for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) {
Daniel Dunbar04a0b502009-09-17 03:06:44 +00002324 // Force deserialization of this decl, which will cause it to be passed to
2325 // the consumer (or queued).
2326 GetDecl(ExternalDefinitions[I]);
Douglas Gregorfdd01722009-04-14 00:24:19 +00002327 }
Douglas Gregorc62a2fe2009-04-25 00:41:30 +00002328
2329 for (unsigned I = 0, N = InterestingDecls.size(); I != N; ++I) {
2330 DeclGroupRef DG(InterestingDecls[I]);
2331 Consumer->HandleTopLevelDecl(DG);
2332 }
Douglas Gregorfdd01722009-04-14 00:24:19 +00002333}
2334
Douglas Gregor2cf26342009-04-09 22:27:44 +00002335void PCHReader::PrintStats() {
2336 std::fprintf(stderr, "*** PCH Statistics:\n");
2337
Mike Stump1eb44332009-09-09 15:08:12 +00002338 unsigned NumTypesLoaded
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002339 = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(),
John McCall0953e762009-09-24 19:53:00 +00002340 QualType());
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002341 unsigned NumDeclsLoaded
2342 = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(),
2343 (Decl *)0);
2344 unsigned NumIdentifiersLoaded
2345 = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(),
2346 IdentifiersLoaded.end(),
2347 (IdentifierInfo *)0);
Mike Stump1eb44332009-09-09 15:08:12 +00002348 unsigned NumSelectorsLoaded
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002349 = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(),
2350 SelectorsLoaded.end(),
2351 Selector());
Douglas Gregor2d41cc12009-04-13 20:50:16 +00002352
Douglas Gregor4fed3f42009-04-27 18:38:38 +00002353 std::fprintf(stderr, " %u stat cache hits\n", NumStatHits);
2354 std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses);
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002355 if (TotalNumSLocEntries)
2356 std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n",
2357 NumSLocEntriesRead, TotalNumSLocEntries,
2358 ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100));
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002359 if (!TypesLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002360 std::fprintf(stderr, " %u/%u types read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002361 NumTypesLoaded, (unsigned)TypesLoaded.size(),
2362 ((float)NumTypesLoaded/TypesLoaded.size() * 100));
2363 if (!DeclsLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002364 std::fprintf(stderr, " %u/%u declarations read (%f%%)\n",
Douglas Gregor8f5dc7f2009-04-25 18:35:21 +00002365 NumDeclsLoaded, (unsigned)DeclsLoaded.size(),
2366 ((float)NumDeclsLoaded/DeclsLoaded.size() * 100));
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002367 if (!IdentifiersLoaded.empty())
Douglas Gregor83941df2009-04-25 17:48:32 +00002368 std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n",
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002369 NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(),
2370 ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100));
Douglas Gregor83941df2009-04-25 17:48:32 +00002371 if (TotalNumSelectors)
2372 std::fprintf(stderr, " %u/%u selectors read (%f%%)\n",
2373 NumSelectorsLoaded, TotalNumSelectors,
2374 ((float)NumSelectorsLoaded/TotalNumSelectors * 100));
2375 if (TotalNumStatements)
2376 std::fprintf(stderr, " %u/%u statements read (%f%%)\n",
2377 NumStatementsRead, TotalNumStatements,
2378 ((float)NumStatementsRead/TotalNumStatements * 100));
2379 if (TotalNumMacros)
2380 std::fprintf(stderr, " %u/%u macros read (%f%%)\n",
2381 NumMacrosRead, TotalNumMacros,
2382 ((float)NumMacrosRead/TotalNumMacros * 100));
2383 if (TotalLexicalDeclContexts)
2384 std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n",
2385 NumLexicalDeclContextsRead, TotalLexicalDeclContexts,
2386 ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts
2387 * 100));
2388 if (TotalVisibleDeclContexts)
2389 std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n",
2390 NumVisibleDeclContextsRead, TotalVisibleDeclContexts,
2391 ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts
2392 * 100));
2393 if (TotalSelectorsInMethodPool) {
2394 std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n",
2395 NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool,
2396 ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool
2397 * 100));
2398 std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses);
2399 }
Douglas Gregor2cf26342009-04-09 22:27:44 +00002400 std::fprintf(stderr, "\n");
2401}
2402
Douglas Gregor668c1a42009-04-21 22:25:48 +00002403void PCHReader::InitializeSema(Sema &S) {
2404 SemaObj = &S;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002405 S.ExternalSource = this;
2406
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002407 // Makes sure any declarations that were deserialized "too early"
2408 // still get added to the identifier's declaration chains.
2409 for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) {
2410 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I]));
2411 SemaObj->IdResolver.AddDecl(PreloadedDecls[I]);
Douglas Gregor668c1a42009-04-21 22:25:48 +00002412 }
Douglas Gregor6cfc1a82009-04-22 21:15:06 +00002413 PreloadedDecls.clear();
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00002414
2415 // If there were any tentative definitions, deserialize them and add
2416 // them to Sema's table of tentative definitions.
2417 for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) {
2418 VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I]));
2419 SemaObj->TentativeDefinitions[Var->getDeclName()] = Var;
Chris Lattner63d65f82009-09-08 18:19:27 +00002420 SemaObj->TentativeDefinitionList.push_back(Var->getDeclName());
Douglas Gregor4c0e86b2009-04-22 22:02:47 +00002421 }
Douglas Gregor14c22f22009-04-22 22:18:58 +00002422
2423 // If there were any locally-scoped external declarations,
2424 // deserialize them and add them to Sema's table of locally-scoped
2425 // external declarations.
2426 for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) {
2427 NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I]));
2428 SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D;
2429 }
Douglas Gregorb81c1702009-04-27 20:06:05 +00002430
2431 // If there were any ext_vector type declarations, deserialize them
2432 // and add them to Sema's vector of such declarations.
2433 for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I)
2434 SemaObj->ExtVectorDecls.push_back(
2435 cast<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
Douglas Gregor668c1a42009-04-21 22:25:48 +00002436}
2437
2438IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) {
2439 // Try to find this name within our on-disk hash table
Mike Stump1eb44332009-09-09 15:08:12 +00002440 PCHIdentifierLookupTable *IdTable
Douglas Gregor668c1a42009-04-21 22:25:48 +00002441 = (PCHIdentifierLookupTable *)IdentifierLookupTable;
2442 std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart);
2443 PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key);
2444 if (Pos == IdTable->end())
2445 return 0;
2446
2447 // Dereferencing the iterator has the effect of building the
2448 // IdentifierInfo node and populating it with the various
2449 // declarations it needs.
2450 return *Pos;
2451}
2452
Mike Stump1eb44332009-09-09 15:08:12 +00002453std::pair<ObjCMethodList, ObjCMethodList>
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002454PCHReader::ReadMethodPool(Selector Sel) {
2455 if (!MethodPoolLookupTable)
2456 return std::pair<ObjCMethodList, ObjCMethodList>();
2457
2458 // Try to find this selector within our on-disk hash table.
2459 PCHMethodPoolLookupTable *PoolTable
2460 = (PCHMethodPoolLookupTable*)MethodPoolLookupTable;
2461 PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel);
Douglas Gregor83941df2009-04-25 17:48:32 +00002462 if (Pos == PoolTable->end()) {
2463 ++NumMethodPoolMisses;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002464 return std::pair<ObjCMethodList, ObjCMethodList>();;
Douglas Gregor83941df2009-04-25 17:48:32 +00002465 }
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002466
Douglas Gregor83941df2009-04-25 17:48:32 +00002467 ++NumMethodPoolSelectorsRead;
Douglas Gregorf0aaf7a2009-04-24 21:10:55 +00002468 return *Pos;
2469}
2470
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002471void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) {
Douglas Gregor668c1a42009-04-21 22:25:48 +00002472 assert(ID && "Non-zero identifier ID required");
Douglas Gregora02b1472009-04-28 21:53:25 +00002473 assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002474 IdentifiersLoaded[ID - 1] = II;
Douglas Gregor668c1a42009-04-21 22:25:48 +00002475}
2476
Douglas Gregord89275b2009-07-06 18:54:52 +00002477/// \brief Set the globally-visible declarations associated with the given
2478/// identifier.
2479///
2480/// If the PCH reader is currently in a state where the given declaration IDs
Mike Stump1eb44332009-09-09 15:08:12 +00002481/// cannot safely be resolved, they are queued until it is safe to resolve
Douglas Gregord89275b2009-07-06 18:54:52 +00002482/// them.
2483///
2484/// \param II an IdentifierInfo that refers to one or more globally-visible
2485/// declarations.
2486///
2487/// \param DeclIDs the set of declaration IDs with the name @p II that are
2488/// visible at global scope.
2489///
2490/// \param Nonrecursive should be true to indicate that the caller knows that
2491/// this call is non-recursive, and therefore the globally-visible declarations
2492/// will not be placed onto the pending queue.
Mike Stump1eb44332009-09-09 15:08:12 +00002493void
2494PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II,
Douglas Gregord89275b2009-07-06 18:54:52 +00002495 const llvm::SmallVectorImpl<uint32_t> &DeclIDs,
2496 bool Nonrecursive) {
2497 if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) {
2498 PendingIdentifierInfos.push_back(PendingIdentifierInfo());
2499 PendingIdentifierInfo &PII = PendingIdentifierInfos.back();
2500 PII.II = II;
2501 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I)
2502 PII.DeclIDs.push_back(DeclIDs[I]);
2503 return;
2504 }
Mike Stump1eb44332009-09-09 15:08:12 +00002505
Douglas Gregord89275b2009-07-06 18:54:52 +00002506 for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) {
2507 NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I]));
2508 if (SemaObj) {
2509 // Introduce this declaration into the translation-unit scope
2510 // and add it to the declaration chain for this identifier, so
2511 // that (unqualified) name lookup will find it.
2512 SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D));
2513 SemaObj->IdResolver.AddDeclToIdentifierChain(II, D);
2514 } else {
2515 // Queue this declaration so that it will be added to the
2516 // translation unit scope and identifier's declaration chain
2517 // once a Sema object is known.
2518 PreloadedDecls.push_back(D);
2519 }
2520 }
2521}
2522
Chris Lattner7356a312009-04-11 21:15:38 +00002523IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {
Douglas Gregorafaf3082009-04-11 00:14:32 +00002524 if (ID == 0)
2525 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +00002526
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002527 if (!IdentifierTableData || IdentifiersLoaded.empty()) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002528 Error("no identifier table in PCH file");
Douglas Gregorafaf3082009-04-11 00:14:32 +00002529 return 0;
2530 }
Mike Stump1eb44332009-09-09 15:08:12 +00002531
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002532 assert(PP && "Forgot to set Preprocessor ?");
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002533 if (!IdentifiersLoaded[ID - 1]) {
2534 uint32_t Offset = IdentifierOffsets[ID - 1];
Douglas Gregor17e1c5e2009-04-25 21:21:38 +00002535 const char *Str = IdentifierTableData + Offset;
Douglas Gregord6595a42009-04-25 21:04:17 +00002536
Douglas Gregor02fc7512009-04-28 20:01:51 +00002537 // All of the strings in the PCH file are preceded by a 16-bit
2538 // length. Extract that 16-bit length to avoid having to execute
2539 // strlen().
Ted Kremenek231bc0b2009-10-23 04:45:31 +00002540 // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as
2541 // unsigned integers. This is important to avoid integer overflow when
2542 // we cast them to 'unsigned'.
Ted Kremenekff1ea462009-10-23 03:57:22 +00002543 const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;
Douglas Gregor02fc7512009-04-28 20:01:51 +00002544 unsigned StrLen = (((unsigned) StrLenPtr[0])
2545 | (((unsigned) StrLenPtr[1]) << 8)) - 1;
Mike Stump1eb44332009-09-09 15:08:12 +00002546 IdentifiersLoaded[ID - 1]
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002547 = &PP->getIdentifierTable().get(Str, Str + StrLen);
Douglas Gregorafaf3082009-04-11 00:14:32 +00002548 }
Mike Stump1eb44332009-09-09 15:08:12 +00002549
Douglas Gregor2b3a5a82009-04-25 19:10:14 +00002550 return IdentifiersLoaded[ID - 1];
Douglas Gregor2cf26342009-04-09 22:27:44 +00002551}
2552
Douglas Gregor7f94b0b2009-04-27 06:38:32 +00002553void PCHReader::ReadSLocEntry(unsigned ID) {
2554 ReadSLocEntryRecord(ID);
2555}
2556
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002557Selector PCHReader::DecodeSelector(unsigned ID) {
2558 if (ID == 0)
2559 return Selector();
Mike Stump1eb44332009-09-09 15:08:12 +00002560
Douglas Gregora02b1472009-04-28 21:53:25 +00002561 if (!MethodPoolLookupTableData)
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002562 return Selector();
Douglas Gregor83941df2009-04-25 17:48:32 +00002563
2564 if (ID > TotalNumSelectors) {
Douglas Gregora02b1472009-04-28 21:53:25 +00002565 Error("selector ID out of range in PCH file");
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002566 return Selector();
2567 }
Douglas Gregor83941df2009-04-25 17:48:32 +00002568
2569 unsigned Index = ID - 1;
2570 if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) {
2571 // Load this selector from the selector table.
2572 // FIXME: endianness portability issues with SelectorOffsets table
2573 PCHMethodPoolLookupTrait Trait(*this);
Mike Stump1eb44332009-09-09 15:08:12 +00002574 SelectorsLoaded[Index]
Douglas Gregor83941df2009-04-25 17:48:32 +00002575 = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0);
2576 }
2577
2578 return SelectorsLoaded[Index];
Steve Naroff90cd1bb2009-04-23 10:39:46 +00002579}
2580
Mike Stump1eb44332009-09-09 15:08:12 +00002581DeclarationName
Douglas Gregor2cf26342009-04-09 22:27:44 +00002582PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
2583 DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];
2584 switch (Kind) {
2585 case DeclarationName::Identifier:
2586 return DeclarationName(GetIdentifierInfo(Record, Idx));
2587
2588 case DeclarationName::ObjCZeroArgSelector:
2589 case DeclarationName::ObjCOneArgSelector:
2590 case DeclarationName::ObjCMultiArgSelector:
Steve Naroffa7503a72009-04-23 15:15:40 +00002591 return DeclarationName(GetSelector(Record, Idx));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002592
2593 case DeclarationName::CXXConstructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002594 return Context->DeclarationNames.getCXXConstructorName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002595 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002596
2597 case DeclarationName::CXXDestructorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002598 return Context->DeclarationNames.getCXXDestructorName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002599 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002600
2601 case DeclarationName::CXXConversionFunctionName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002602 return Context->DeclarationNames.getCXXConversionFunctionName(
Douglas Gregor50d62d12009-08-05 05:36:45 +00002603 Context->getCanonicalType(GetType(Record[Idx++])));
Douglas Gregor2cf26342009-04-09 22:27:44 +00002604
2605 case DeclarationName::CXXOperatorName:
Chris Lattnerd1d64a02009-04-27 21:45:14 +00002606 return Context->DeclarationNames.getCXXOperatorName(
Douglas Gregor2cf26342009-04-09 22:27:44 +00002607 (OverloadedOperatorKind)Record[Idx++]);
2608
2609 case DeclarationName::CXXUsingDirective:
2610 return DeclarationName::getUsingDirectiveName();
2611 }
2612
2613 // Required to silence GCC warning
2614 return DeclarationName();
2615}
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002616
Douglas Gregor0a2b45e2009-04-13 18:14:40 +00002617/// \brief Read an integral value
2618llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) {
2619 unsigned BitWidth = Record[Idx++];
2620 unsigned NumWords = llvm::APInt::getNumWords(BitWidth);
2621 llvm::APInt Result(BitWidth, NumWords, &Record[Idx]);
2622 Idx += NumWords;
2623 return Result;
2624}
2625
2626/// \brief Read a signed integral value
2627llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) {
2628 bool isUnsigned = Record[Idx++];
2629 return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned);
2630}
2631
Douglas Gregor17fc2232009-04-14 21:55:33 +00002632/// \brief Read a floating-point value
2633llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) {
Douglas Gregor17fc2232009-04-14 21:55:33 +00002634 return llvm::APFloat(ReadAPInt(Record, Idx));
2635}
2636
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002637// \brief Read a string
2638std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) {
2639 unsigned Len = Record[Idx++];
Jay Foadbeaaccd2009-05-21 09:52:38 +00002640 std::string Result(Record.data() + Idx, Record.data() + Idx + Len);
Douglas Gregor68a2eb02009-04-15 21:30:51 +00002641 Idx += Len;
2642 return Result;
2643}
2644
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002645DiagnosticBuilder PCHReader::Diag(unsigned DiagID) {
Douglas Gregore1d918e2009-04-10 23:10:45 +00002646 return Diag(SourceLocation(), DiagID);
2647}
2648
2649DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002650 return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
Douglas Gregor0a0428e2009-04-10 20:39:37 +00002651}
Douglas Gregor025452f2009-04-17 00:04:06 +00002652
Douglas Gregor668c1a42009-04-21 22:25:48 +00002653/// \brief Retrieve the identifier table associated with the
2654/// preprocessor.
2655IdentifierTable &PCHReader::getIdentifierTable() {
Argyrios Kyrtzidis11e51102009-06-19 00:03:23 +00002656 assert(PP && "Forgot to set Preprocessor ?");
2657 return PP->getIdentifierTable();
Douglas Gregor668c1a42009-04-21 22:25:48 +00002658}
2659
Douglas Gregor025452f2009-04-17 00:04:06 +00002660/// \brief Record that the given ID maps to the given switch-case
2661/// statement.
2662void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) {
2663 assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID");
2664 SwitchCaseStmts[ID] = SC;
2665}
2666
2667/// \brief Retrieve the switch-case statement with the given ID.
2668SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) {
2669 assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID");
2670 return SwitchCaseStmts[ID];
2671}
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002672
2673/// \brief Record that the given label statement has been
2674/// deserialized and has the given ID.
2675void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) {
Mike Stump1eb44332009-09-09 15:08:12 +00002676 assert(LabelStmts.find(ID) == LabelStmts.end() &&
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002677 "Deserialized label twice");
2678 LabelStmts[ID] = S;
2679
2680 // If we've already seen any goto statements that point to this
2681 // label, resolve them now.
2682 typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter;
2683 std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID);
2684 for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto)
2685 Goto->second->setLabel(S);
2686 UnresolvedGotoStmts.erase(Gotos.first, Gotos.second);
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002687
2688 // If we've already seen any address-label statements that point to
2689 // this label, resolve them now.
2690 typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter;
Mike Stump1eb44332009-09-09 15:08:12 +00002691 std::pair<AddrLabelIter, AddrLabelIter> AddrLabels
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002692 = UnresolvedAddrLabelExprs.equal_range(ID);
Mike Stump1eb44332009-09-09 15:08:12 +00002693 for (AddrLabelIter AddrLabel = AddrLabels.first;
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002694 AddrLabel != AddrLabels.second; ++AddrLabel)
2695 AddrLabel->second->setLabel(S);
2696 UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second);
Douglas Gregor1de05fe2009-04-17 18:18:49 +00002697}
2698
2699/// \brief Set the label of the given statement to the label
2700/// identified by ID.
2701///
2702/// Depending on the order in which the label and other statements
2703/// referencing that label occur, this operation may complete
2704/// immediately (updating the statement) or it may queue the
2705/// statement to be back-patched later.
2706void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) {
2707 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2708 if (Label != LabelStmts.end()) {
2709 // We've already seen this label, so set the label of the goto and
2710 // we're done.
2711 S->setLabel(Label->second);
2712 } else {
2713 // We haven't seen this label yet, so add this goto to the set of
2714 // unresolved goto statements.
2715 UnresolvedGotoStmts.insert(std::make_pair(ID, S));
2716 }
2717}
Douglas Gregor7d5c2f22009-04-17 18:58:21 +00002718
2719/// \brief Set the label of the given expression to the label
2720/// identified by ID.
2721///
2722/// Depending on the order in which the label and other statements
2723/// referencing that label occur, this operation may complete
2724/// immediately (updating the statement) or it may queue the
2725/// statement to be back-patched later.
2726void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) {
2727 std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID);
2728 if (Label != LabelStmts.end()) {
2729 // We've already seen this label, so set the label of the
2730 // label-address expression and we're done.
2731 S->setLabel(Label->second);
2732 } else {
2733 // We haven't seen this label yet, so add this label-address
2734 // expression to the set of unresolved label-address expressions.
2735 UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S));
2736 }
2737}
Douglas Gregord89275b2009-07-06 18:54:52 +00002738
2739
Mike Stump1eb44332009-09-09 15:08:12 +00002740PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader)
Douglas Gregord89275b2009-07-06 18:54:52 +00002741 : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) {
2742 Reader.CurrentlyLoadingTypeOrDecl = this;
2743}
2744
2745PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() {
2746 if (!Parent) {
2747 // If any identifiers with corresponding top-level declarations have
2748 // been loaded, load those declarations now.
2749 while (!Reader.PendingIdentifierInfos.empty()) {
2750 Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II,
2751 Reader.PendingIdentifierInfos.front().DeclIDs,
2752 true);
2753 Reader.PendingIdentifierInfos.pop_front();
2754 }
2755 }
2756
Mike Stump1eb44332009-09-09 15:08:12 +00002757 Reader.CurrentlyLoadingTypeOrDecl = Parent;
Douglas Gregord89275b2009-07-06 18:54:52 +00002758}