diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp | 3469 |
1 files changed, 0 insertions, 3469 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp b/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp deleted file mode 100644 index 00aee49..0000000 --- a/contrib/llvm/tools/clang/lib/Frontend/PCHReader.cpp +++ /dev/null @@ -1,3469 +0,0 @@ -//===--- PCHReader.cpp - Precompiled Headers Reader -------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the PCHReader class, which reads a precompiled header. -// -//===----------------------------------------------------------------------===// - -#include "clang/Frontend/PCHReader.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/PCHDeserializationListener.h" -#include "clang/Frontend/Utils.h" -#include "../Sema/Sema.h" // FIXME: move Sema headers elsewhere -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/Expr.h" -#include "clang/AST/Type.h" -#include "clang/AST/TypeLocVisitor.h" -#include "clang/Lex/MacroInfo.h" -#include "clang/Lex/PreprocessingRecord.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Lex/HeaderSearch.h" -#include "clang/Basic/OnDiskHashTable.h" -#include "clang/Basic/SourceManager.h" -#include "clang/Basic/SourceManagerInternals.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/Bitcode/BitstreamReader.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/System/Path.h" -#include <algorithm> -#include <iterator> -#include <cstdio> -#include <sys/stat.h> -using namespace clang; - -//===----------------------------------------------------------------------===// -// PCH reader validator implementation -//===----------------------------------------------------------------------===// - -PCHReaderListener::~PCHReaderListener() {} - -bool -PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts) { - const LangOptions &PPLangOpts = PP.getLangOptions(); -#define PARSE_LANGOPT_BENIGN(Option) -#define PARSE_LANGOPT_IMPORTANT(Option, DiagID) \ - if (PPLangOpts.Option != LangOpts.Option) { \ - Reader.Diag(DiagID) << LangOpts.Option << PPLangOpts.Option; \ - return true; \ - } - - PARSE_LANGOPT_BENIGN(Trigraphs); - PARSE_LANGOPT_BENIGN(BCPLComment); - PARSE_LANGOPT_BENIGN(DollarIdents); - PARSE_LANGOPT_BENIGN(AsmPreprocessor); - PARSE_LANGOPT_IMPORTANT(GNUMode, diag::warn_pch_gnu_extensions); - PARSE_LANGOPT_IMPORTANT(GNUKeywords, diag::warn_pch_gnu_keywords); - PARSE_LANGOPT_BENIGN(ImplicitInt); - PARSE_LANGOPT_BENIGN(Digraphs); - PARSE_LANGOPT_BENIGN(HexFloats); - PARSE_LANGOPT_IMPORTANT(C99, diag::warn_pch_c99); - PARSE_LANGOPT_IMPORTANT(Microsoft, diag::warn_pch_microsoft_extensions); - PARSE_LANGOPT_IMPORTANT(CPlusPlus, diag::warn_pch_cplusplus); - PARSE_LANGOPT_IMPORTANT(CPlusPlus0x, diag::warn_pch_cplusplus0x); - PARSE_LANGOPT_BENIGN(CXXOperatorName); - PARSE_LANGOPT_IMPORTANT(ObjC1, diag::warn_pch_objective_c); - PARSE_LANGOPT_IMPORTANT(ObjC2, diag::warn_pch_objective_c2); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI, diag::warn_pch_nonfragile_abi); - PARSE_LANGOPT_IMPORTANT(ObjCNonFragileABI2, diag::warn_pch_nonfragile_abi2); - PARSE_LANGOPT_IMPORTANT(NoConstantCFStrings, - diag::warn_pch_no_constant_cfstrings); - PARSE_LANGOPT_BENIGN(PascalStrings); - PARSE_LANGOPT_BENIGN(WritableStrings); - PARSE_LANGOPT_IMPORTANT(LaxVectorConversions, - diag::warn_pch_lax_vector_conversions); - PARSE_LANGOPT_IMPORTANT(AltiVec, diag::warn_pch_altivec); - PARSE_LANGOPT_IMPORTANT(Exceptions, diag::warn_pch_exceptions); - PARSE_LANGOPT_IMPORTANT(SjLjExceptions, diag::warn_pch_sjlj_exceptions); - PARSE_LANGOPT_IMPORTANT(NeXTRuntime, diag::warn_pch_objc_runtime); - PARSE_LANGOPT_IMPORTANT(Freestanding, diag::warn_pch_freestanding); - PARSE_LANGOPT_IMPORTANT(NoBuiltin, diag::warn_pch_builtins); - PARSE_LANGOPT_IMPORTANT(ThreadsafeStatics, - diag::warn_pch_thread_safe_statics); - PARSE_LANGOPT_IMPORTANT(POSIXThreads, diag::warn_pch_posix_threads); - PARSE_LANGOPT_IMPORTANT(Blocks, diag::warn_pch_blocks); - PARSE_LANGOPT_BENIGN(EmitAllDecls); - PARSE_LANGOPT_IMPORTANT(MathErrno, diag::warn_pch_math_errno); - PARSE_LANGOPT_BENIGN(getSignedOverflowBehavior()); - PARSE_LANGOPT_IMPORTANT(HeinousExtensions, - diag::warn_pch_heinous_extensions); - // FIXME: Most of the options below are benign if the macro wasn't - // used. Unfortunately, this means that a PCH compiled without - // optimization can't be used with optimization turned on, even - // though the only thing that changes is whether __OPTIMIZE__ was - // defined... but if __OPTIMIZE__ never showed up in the header, it - // doesn't matter. We could consider making this some special kind - // of check. - PARSE_LANGOPT_IMPORTANT(Optimize, diag::warn_pch_optimize); - PARSE_LANGOPT_IMPORTANT(OptimizeSize, diag::warn_pch_optimize_size); - PARSE_LANGOPT_IMPORTANT(Static, diag::warn_pch_static); - PARSE_LANGOPT_IMPORTANT(PICLevel, diag::warn_pch_pic_level); - PARSE_LANGOPT_IMPORTANT(GNUInline, diag::warn_pch_gnu_inline); - PARSE_LANGOPT_IMPORTANT(NoInline, diag::warn_pch_no_inline); - PARSE_LANGOPT_IMPORTANT(AccessControl, diag::warn_pch_access_control); - PARSE_LANGOPT_IMPORTANT(CharIsSigned, diag::warn_pch_char_signed); - PARSE_LANGOPT_IMPORTANT(ShortWChar, diag::warn_pch_short_wchar); - if ((PPLangOpts.getGCMode() != 0) != (LangOpts.getGCMode() != 0)) { - Reader.Diag(diag::warn_pch_gc_mode) - << LangOpts.getGCMode() << PPLangOpts.getGCMode(); - return true; - } - PARSE_LANGOPT_BENIGN(getVisibilityMode()); - PARSE_LANGOPT_IMPORTANT(getStackProtectorMode(), - diag::warn_pch_stack_protector); - PARSE_LANGOPT_BENIGN(InstantiationDepth); - PARSE_LANGOPT_IMPORTANT(OpenCL, diag::warn_pch_opencl); - PARSE_LANGOPT_BENIGN(CatchUndefined); - PARSE_LANGOPT_IMPORTANT(ElideConstructors, diag::warn_pch_elide_constructors); - PARSE_LANGOPT_BENIGN(SpellChecking); -#undef PARSE_LANGOPT_IMPORTANT -#undef PARSE_LANGOPT_BENIGN - - return false; -} - -bool PCHValidator::ReadTargetTriple(llvm::StringRef Triple) { - if (Triple == PP.getTargetInfo().getTriple().str()) - return false; - - Reader.Diag(diag::warn_pch_target_triple) - << Triple << PP.getTargetInfo().getTriple().str(); - return true; -} - -struct EmptyStringRef { - bool operator ()(llvm::StringRef r) const { return r.empty(); } -}; -struct EmptyBlock { - bool operator ()(const PCHPredefinesBlock &r) const { return r.Data.empty(); } -}; - -static bool EqualConcatenations(llvm::SmallVector<llvm::StringRef, 2> L, - PCHPredefinesBlocks R) { - // First, sum up the lengths. - unsigned LL = 0, RL = 0; - for (unsigned I = 0, N = L.size(); I != N; ++I) { - LL += L[I].size(); - } - for (unsigned I = 0, N = R.size(); I != N; ++I) { - RL += R[I].Data.size(); - } - if (LL != RL) - return false; - if (LL == 0 && RL == 0) - return true; - - // Kick out empty parts, they confuse the algorithm below. - L.erase(std::remove_if(L.begin(), L.end(), EmptyStringRef()), L.end()); - R.erase(std::remove_if(R.begin(), R.end(), EmptyBlock()), R.end()); - - // Do it the hard way. At this point, both vectors must be non-empty. - llvm::StringRef LR = L[0], RR = R[0].Data; - unsigned LI = 0, RI = 0, LN = L.size(), RN = R.size(); - for (;;) { - // Compare the current pieces. - if (LR.size() == RR.size()) { - // If they're the same length, it's pretty easy. - if (LR != RR) - return false; - // Both pieces are done, advance. - ++LI; - ++RI; - // If either string is done, they're both done, since they're the same - // length. - if (LI == LN) { - assert(RI == RN && "Strings not the same length after all?"); - return true; - } - LR = L[LI]; - RR = R[RI].Data; - } else if (LR.size() < RR.size()) { - // Right piece is longer. - if (!RR.startswith(LR)) - return false; - ++LI; - assert(LI != LN && "Strings not the same length after all?"); - RR = RR.substr(LR.size()); - LR = L[LI]; - } else { - // Left piece is longer. - if (!LR.startswith(RR)) - return false; - ++RI; - assert(RI != RN && "Strings not the same length after all?"); - LR = LR.substr(RR.size()); - RR = R[RI].Data; - } - } -} - -static std::pair<FileID, llvm::StringRef::size_type> -FindMacro(const PCHPredefinesBlocks &Buffers, llvm::StringRef MacroDef) { - std::pair<FileID, llvm::StringRef::size_type> Res; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) { - Res.second = Buffers[I].Data.find(MacroDef); - if (Res.second != llvm::StringRef::npos) { - Res.first = Buffers[I].BufferID; - break; - } - } - return Res; -} - -bool PCHValidator::ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers, - llvm::StringRef OriginalFileName, - std::string &SuggestedPredefines) { - // We are in the context of an implicit include, so the predefines buffer will - // have a #include entry for the PCH file itself (as normalized by the - // preprocessor initialization). Find it and skip over it in the checking - // below. - llvm::SmallString<256> PCHInclude; - PCHInclude += "#include \""; - PCHInclude += NormalizeDashIncludePath(OriginalFileName); - PCHInclude += "\"\n"; - std::pair<llvm::StringRef,llvm::StringRef> Split = - llvm::StringRef(PP.getPredefines()).split(PCHInclude.str()); - llvm::StringRef Left = Split.first, Right = Split.second; - if (Left == PP.getPredefines()) { - Error("Missing PCH include entry!"); - return true; - } - - // If the concatenation of all the PCH buffers is equal to the adjusted - // command line, we're done. - // We build a SmallVector of the command line here, because we'll eventually - // need to support an arbitrary amount of pieces anyway (when we have chained - // PCH reading). - llvm::SmallVector<llvm::StringRef, 2> CommandLine; - CommandLine.push_back(Left); - CommandLine.push_back(Right); - if (EqualConcatenations(CommandLine, Buffers)) - return false; - - SourceManager &SourceMgr = PP.getSourceManager(); - - // The predefines buffers are different. Determine what the differences are, - // and whether they require us to reject the PCH file. - llvm::SmallVector<llvm::StringRef, 8> PCHLines; - for (unsigned I = 0, N = Buffers.size(); I != N; ++I) - Buffers[I].Data.split(PCHLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - llvm::SmallVector<llvm::StringRef, 8> CmdLineLines; - Left.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - Right.split(CmdLineLines, "\n", /*MaxSplit=*/-1, /*KeepEmpty=*/false); - - // Sort both sets of predefined buffer lines, since we allow some extra - // definitions and they may appear at any point in the output. - std::sort(CmdLineLines.begin(), CmdLineLines.end()); - std::sort(PCHLines.begin(), PCHLines.end()); - - // Determine which predefines that were used to build the PCH file are missing - // from the command line. - std::vector<llvm::StringRef> MissingPredefines; - std::set_difference(PCHLines.begin(), PCHLines.end(), - CmdLineLines.begin(), CmdLineLines.end(), - std::back_inserter(MissingPredefines)); - - bool MissingDefines = false; - bool ConflictingDefines = false; - for (unsigned I = 0, N = MissingPredefines.size(); I != N; ++I) { - llvm::StringRef Missing = MissingPredefines[I]; - if (!Missing.startswith("#define ")) { - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is a macro definition. Determine the name of the macro we're - // defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Missing.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Missing.slice(StartOfMacroName, EndOfMacroName); - - // Determine whether this macro was given a different definition on the - // command line. - std::string MacroDefStart = "#define " + MacroName.str(); - std::string::size_type MacroDefLen = MacroDefStart.size(); - llvm::SmallVector<llvm::StringRef, 8>::iterator ConflictPos - = std::lower_bound(CmdLineLines.begin(), CmdLineLines.end(), - MacroDefStart); - for (; ConflictPos != CmdLineLines.end(); ++ConflictPos) { - if (!ConflictPos->startswith(MacroDefStart)) { - // Different macro; we're done. - ConflictPos = CmdLineLines.end(); - break; - } - - assert(ConflictPos->size() > MacroDefLen && - "Invalid #define in predefines buffer?"); - if ((*ConflictPos)[MacroDefLen] != ' ' && - (*ConflictPos)[MacroDefLen] != '(') - continue; // Longer macro name; keep trying. - - // We found a conflicting macro definition. - break; - } - - if (ConflictPos != CmdLineLines.end()) { - Reader.Diag(diag::warn_cmdline_conflicting_macro_def) - << MacroName; - - // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_pch_macro_defined_as) << MacroName; - - ConflictingDefines = true; - continue; - } - - // If the macro doesn't conflict, then we'll just pick up the macro - // definition from the PCH file. Warn the user that they made a mistake. - if (ConflictingDefines) - continue; // Don't complain if there are already conflicting defs - - if (!MissingDefines) { - Reader.Diag(diag::warn_cmdline_missing_macro_defs); - MissingDefines = true; - } - - // Show the definition of this macro within the PCH file. - std::pair<FileID, llvm::StringRef::size_type> MacroLoc = - FindMacro(Buffers, Missing); - assert(MacroLoc.second!=llvm::StringRef::npos && "Unable to find macro!"); - SourceLocation PCHMissingLoc = - SourceMgr.getLocForStartOfFile(MacroLoc.first) - .getFileLocWithOffset(MacroLoc.second); - Reader.Diag(PCHMissingLoc, diag::note_using_macro_def_from_pch); - } - - if (ConflictingDefines) - return true; - - // Determine what predefines were introduced based on command-line - // parameters that were not present when building the PCH - // file. Extra #defines are okay, so long as the identifiers being - // defined were not used within the precompiled header. - std::vector<llvm::StringRef> ExtraPredefines; - std::set_difference(CmdLineLines.begin(), CmdLineLines.end(), - PCHLines.begin(), PCHLines.end(), - std::back_inserter(ExtraPredefines)); - for (unsigned I = 0, N = ExtraPredefines.size(); I != N; ++I) { - llvm::StringRef &Extra = ExtraPredefines[I]; - if (!Extra.startswith("#define ")) { - Reader.Diag(diag::warn_pch_compiler_options_mismatch); - return true; - } - - // This is an extra macro definition. Determine the name of the - // macro we're defining. - std::string::size_type StartOfMacroName = strlen("#define "); - std::string::size_type EndOfMacroName - = Extra.find_first_of("( \n\r", StartOfMacroName); - assert(EndOfMacroName != std::string::npos && - "Couldn't find the end of the macro name"); - llvm::StringRef MacroName = Extra.slice(StartOfMacroName, EndOfMacroName); - - // Check whether this name was used somewhere in the PCH file. If - // so, defining it as a macro could change behavior, so we reject - // the PCH file. - if (IdentifierInfo *II = Reader.get(MacroName)) { - Reader.Diag(diag::warn_macro_name_used_in_pch) << II; - return true; - } - - // Add this definition to the suggested predefines buffer. - SuggestedPredefines += Extra; - SuggestedPredefines += '\n'; - } - - // If we get here, it's because the predefines buffer had compatible - // contents. Accept the PCH file. - return false; -} - -void PCHValidator::ReadHeaderFileInfo(const HeaderFileInfo &HFI, - unsigned ID) { - PP.getHeaderSearchInfo().setHeaderFileInfoForUID(HFI, ID); - ++NumHeaderInfos; -} - -void PCHValidator::ReadCounter(unsigned Value) { - PP.setCounterValue(Value); -} - -//===----------------------------------------------------------------------===// -// PCH reader implementation -//===----------------------------------------------------------------------===// - -PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context, - const char *isysroot) - : Listener(new PCHValidator(PP, *this)), DeserializationListener(0), - SourceMgr(PP.getSourceManager()), FileMgr(PP.getFileManager()), - Diags(PP.getDiagnostics()), SemaObj(0), PP(&PP), Context(Context), - StatCache(0), Consumer(0), IdentifierTableData(0), IdentifierLookupTable(0), - IdentifierOffsets(0), - MethodPoolLookupTable(0), MethodPoolLookupTableData(0), - TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), MacroDefinitionOffsets(0), - NumPreallocatedPreprocessingEntities(0), - isysroot(isysroot), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), - NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), - CurrentlyLoadingTypeOrDecl(0) { - RelocatablePCH = false; -} - -PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, - Diagnostic &Diags, const char *isysroot) - : DeserializationListener(0), SourceMgr(SourceMgr), FileMgr(FileMgr), - Diags(Diags), SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0), - IdentifierTableData(0), IdentifierLookupTable(0), - IdentifierOffsets(0), - MethodPoolLookupTable(0), MethodPoolLookupTableData(0), - TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), MacroDefinitionOffsets(0), - NumPreallocatedPreprocessingEntities(0), - isysroot(isysroot), NumStatHits(0), NumStatMisses(0), - NumSLocEntriesRead(0), NumStatementsRead(0), - NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), - NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0), - CurrentlyLoadingTypeOrDecl(0) { - RelocatablePCH = false; -} - -PCHReader::~PCHReader() {} - - -namespace { -class PCHMethodPoolLookupTrait { - PCHReader &Reader; - -public: - typedef std::pair<ObjCMethodList, ObjCMethodList> data_type; - - typedef Selector external_key_type; - typedef external_key_type internal_key_type; - - explicit PCHMethodPoolLookupTrait(PCHReader &Reader) : Reader(Reader) { } - - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return a == b; - } - - static unsigned ComputeHash(Selector Sel) { - unsigned N = Sel.getNumArgs(); - if (N == 0) - ++N; - unsigned R = 5381; - for (unsigned I = 0; I != N; ++I) - if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) - R = llvm::HashString(II->getName(), R); - return R; - } - - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned KeyLen = ReadUnalignedLE16(d); - unsigned DataLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } - - internal_key_type ReadKey(const unsigned char* d, unsigned) { - using namespace clang::io; - SelectorTable &SelTable = Reader.getContext()->Selectors; - unsigned N = ReadUnalignedLE16(d); - IdentifierInfo *FirstII - = Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d)); - if (N == 0) - return SelTable.getNullarySelector(FirstII); - else if (N == 1) - return SelTable.getUnarySelector(FirstII); - - llvm::SmallVector<IdentifierInfo *, 16> Args; - Args.push_back(FirstII); - for (unsigned I = 1; I != N; ++I) - Args.push_back(Reader.DecodeIdentifierInfo(ReadUnalignedLE32(d))); - - return SelTable.getSelector(N, Args.data()); - } - - data_type ReadData(Selector, const unsigned char* d, unsigned DataLen) { - using namespace clang::io; - unsigned NumInstanceMethods = ReadUnalignedLE16(d); - unsigned NumFactoryMethods = ReadUnalignedLE16(d); - - data_type Result; - - // Load instance methods - ObjCMethodList *Prev = 0; - for (unsigned I = 0; I != NumInstanceMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.first.Method) { - // This is the first method, which is the easy case. - Result.first.Method = Method; - Prev = &Result.first; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - // Load factory methods - Prev = 0; - for (unsigned I = 0; I != NumFactoryMethods; ++I) { - ObjCMethodDecl *Method - = cast<ObjCMethodDecl>(Reader.GetDecl(ReadUnalignedLE32(d))); - if (!Result.second.Method) { - // This is the first method, which is the easy case. - Result.second.Method = Method; - Prev = &Result.second; - continue; - } - - ObjCMethodList *Mem = - Reader.getSema()->BumpAlloc.Allocate<ObjCMethodList>(); - Prev->Next = new (Mem) ObjCMethodList(Method, 0); - Prev = Prev->Next; - } - - return Result; - } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used for the global method pool. -typedef OnDiskChainedHashTable<PCHMethodPoolLookupTrait> - PCHMethodPoolLookupTable; - -namespace { -class PCHIdentifierLookupTrait { - PCHReader &Reader; - - // If we know the IdentifierInfo in advance, it is here and we will - // not build a new one. Used when deserializing information about an - // identifier that was constructed before the PCH file was read. - IdentifierInfo *KnownII; - -public: - typedef IdentifierInfo * data_type; - - typedef const std::pair<const char*, unsigned> external_key_type; - - typedef external_key_type internal_key_type; - - explicit PCHIdentifierLookupTrait(PCHReader &Reader, IdentifierInfo *II = 0) - : Reader(Reader), KnownII(II) { } - - static bool EqualKey(const internal_key_type& a, - const internal_key_type& b) { - return (a.second == b.second) ? memcmp(a.first, b.first, a.second) == 0 - : false; - } - - static unsigned ComputeHash(const internal_key_type& a) { - return llvm::HashString(llvm::StringRef(a.first, a.second)); - } - - // This hopefully will just get inlined and removed by the optimizer. - static const internal_key_type& - GetInternalKey(const external_key_type& x) { return x; } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - using namespace clang::io; - unsigned DataLen = ReadUnalignedLE16(d); - unsigned KeyLen = ReadUnalignedLE16(d); - return std::make_pair(KeyLen, DataLen); - } - - static std::pair<const char*, unsigned> - ReadKey(const unsigned char* d, unsigned n) { - assert(n >= 2 && d[n-1] == '\0'); - return std::make_pair((const char*) d, n-1); - } - - IdentifierInfo *ReadData(const internal_key_type& k, - const unsigned char* d, - unsigned DataLen) { - using namespace clang::io; - pch::IdentID ID = ReadUnalignedLE32(d); - bool IsInteresting = ID & 0x01; - - // Wipe out the "is interesting" bit. - ID = ID >> 1; - - if (!IsInteresting) { - // For unintersting identifiers, just build the IdentifierInfo - // and associate it with the persistent ID. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().CreateIdentifierInfo( - k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - return II; - } - - unsigned Bits = ReadUnalignedLE16(d); - bool CPlusPlusOperatorKeyword = Bits & 0x01; - Bits >>= 1; - bool Poisoned = Bits & 0x01; - Bits >>= 1; - bool ExtensionToken = Bits & 0x01; - Bits >>= 1; - bool hasMacroDefinition = Bits & 0x01; - Bits >>= 1; - unsigned ObjCOrBuiltinID = Bits & 0x3FF; - Bits >>= 10; - - assert(Bits == 0 && "Extra bits in the identifier?"); - DataLen -= 6; - - // Build the IdentifierInfo itself and link the identifier ID with - // the new IdentifierInfo. - IdentifierInfo *II = KnownII; - if (!II) - II = &Reader.getIdentifierTable().CreateIdentifierInfo( - k.first, k.first + k.second); - Reader.SetIdentifierInfo(ID, II); - - // Set or check the various bits in the IdentifierInfo structure. - // FIXME: Load token IDs lazily, too? - II->setObjCOrBuiltinID(ObjCOrBuiltinID); - assert(II->isExtensionToken() == ExtensionToken && - "Incorrect extension token flag"); - (void)ExtensionToken; - II->setIsPoisoned(Poisoned); - assert(II->isCPlusPlusOperatorKeyword() == CPlusPlusOperatorKeyword && - "Incorrect C++ operator keyword flag"); - (void)CPlusPlusOperatorKeyword; - - // If this identifier is a macro, deserialize the macro - // definition. - if (hasMacroDefinition) { - uint32_t Offset = ReadUnalignedLE32(d); - Reader.ReadMacroRecord(Offset); - DataLen -= 4; - } - - // Read all of the declarations visible at global scope with this - // name. - if (Reader.getContext() == 0) return II; - if (DataLen > 0) { - llvm::SmallVector<uint32_t, 4> DeclIDs; - for (; DataLen > 0; DataLen -= 4) - DeclIDs.push_back(ReadUnalignedLE32(d)); - Reader.SetGloballyVisibleDecls(II, DeclIDs); - } - - return II; - } -}; - -} // end anonymous namespace - -/// \brief The on-disk hash table used to contain information about -/// all of the identifiers in the program. -typedef OnDiskChainedHashTable<PCHIdentifierLookupTrait> - PCHIdentifierLookupTable; - -void PCHReader::Error(const char *Msg) { - Diag(diag::err_fe_pch_malformed) << Msg; -} - -/// \brief Check the contents of the concatenation of all predefines buffers in -/// the PCH chain against the contents of the predefines buffer of the current -/// compiler invocation. -/// -/// The contents should be the same. If not, then some command-line option -/// changed the preprocessor state and we must probably reject the PCH file. -/// -/// \returns true if there was a mismatch (in which case the PCH file -/// should be ignored), or false otherwise. -bool PCHReader::CheckPredefinesBuffers() { - if (Listener) - return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers, - ActualOriginalFileName, - SuggestedPredefines); - return false; -} - -//===----------------------------------------------------------------------===// -// Source Manager Deserialization -//===----------------------------------------------------------------------===// - -/// \brief Read the line table in the source manager block. -/// \returns true if ther was an error. -bool PCHReader::ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record) { - unsigned Idx = 0; - LineTableInfo &LineTable = SourceMgr.getLineTable(); - - // Parse the file names - std::map<int, int> FileIDs; - for (int I = 0, N = Record[Idx++]; I != N; ++I) { - // Extract the file name - unsigned FilenameLen = Record[Idx++]; - std::string Filename(&Record[Idx], &Record[Idx] + FilenameLen); - Idx += FilenameLen; - MaybeAddSystemRootToFilename(Filename); - FileIDs[I] = LineTable.getLineTableFilenameID(Filename.c_str(), - Filename.size()); - } - - // Parse the line entries - std::vector<LineEntry> Entries; - while (Idx < Record.size()) { - int FID = Record[Idx++]; - - // Extract the line entries - unsigned NumEntries = Record[Idx++]; - assert(NumEntries && "Numentries is 00000"); - Entries.clear(); - Entries.reserve(NumEntries); - for (unsigned I = 0; I != NumEntries; ++I) { - unsigned FileOffset = Record[Idx++]; - unsigned LineNo = Record[Idx++]; - int FilenameID = FileIDs[Record[Idx++]]; - SrcMgr::CharacteristicKind FileKind - = (SrcMgr::CharacteristicKind)Record[Idx++]; - unsigned IncludeOffset = Record[Idx++]; - Entries.push_back(LineEntry::get(FileOffset, LineNo, FilenameID, - FileKind, IncludeOffset)); - } - LineTable.AddEntry(FID, Entries); - } - - return false; -} - -namespace { - -class PCHStatData { -public: - const bool hasStat; - const ino_t ino; - const dev_t dev; - const mode_t mode; - const time_t mtime; - const off_t size; - - PCHStatData(ino_t i, dev_t d, mode_t mo, time_t m, off_t s) - : hasStat(true), ino(i), dev(d), mode(mo), mtime(m), size(s) {} - - PCHStatData() - : hasStat(false), ino(0), dev(0), mode(0), mtime(0), size(0) {} -}; - -class PCHStatLookupTrait { - public: - typedef const char *external_key_type; - typedef const char *internal_key_type; - - typedef PCHStatData data_type; - - static unsigned ComputeHash(const char *path) { - return llvm::HashString(path); - } - - static internal_key_type GetInternalKey(const char *path) { return path; } - - static bool EqualKey(internal_key_type a, internal_key_type b) { - return strcmp(a, b) == 0; - } - - static std::pair<unsigned, unsigned> - ReadKeyDataLength(const unsigned char*& d) { - unsigned KeyLen = (unsigned) clang::io::ReadUnalignedLE16(d); - unsigned DataLen = (unsigned) *d++; - return std::make_pair(KeyLen + 1, DataLen); - } - - static internal_key_type ReadKey(const unsigned char *d, unsigned) { - return (const char *)d; - } - - static data_type ReadData(const internal_key_type, const unsigned char *d, - unsigned /*DataLen*/) { - using namespace clang::io; - - if (*d++ == 1) - return data_type(); - - ino_t ino = (ino_t) ReadUnalignedLE32(d); - dev_t dev = (dev_t) ReadUnalignedLE32(d); - mode_t mode = (mode_t) ReadUnalignedLE16(d); - time_t mtime = (time_t) ReadUnalignedLE64(d); - off_t size = (off_t) ReadUnalignedLE64(d); - return data_type(ino, dev, mode, mtime, size); - } -}; - -/// \brief stat() cache for precompiled headers. -/// -/// This cache is very similar to the stat cache used by pretokenized -/// headers. -class PCHStatCache : public StatSysCallCache { - typedef OnDiskChainedHashTable<PCHStatLookupTrait> CacheTy; - CacheTy *Cache; - - unsigned &NumStatHits, &NumStatMisses; -public: - PCHStatCache(const unsigned char *Buckets, - const unsigned char *Base, - unsigned &NumStatHits, - unsigned &NumStatMisses) - : Cache(0), NumStatHits(NumStatHits), NumStatMisses(NumStatMisses) { - Cache = CacheTy::Create(Buckets, Base); - } - - ~PCHStatCache() { delete Cache; } - - int stat(const char *path, struct stat *buf) { - // Do the lookup for the file's data in the PCH file. - CacheTy::iterator I = Cache->find(path); - - // If we don't get a hit in the PCH file just forward to 'stat'. - if (I == Cache->end()) { - ++NumStatMisses; - return StatSysCallCache::stat(path, buf); - } - - ++NumStatHits; - PCHStatData Data = *I; - - if (!Data.hasStat) - return 1; - - buf->st_ino = Data.ino; - buf->st_dev = Data.dev; - buf->st_mtime = Data.mtime; - buf->st_mode = Data.mode; - buf->st_size = Data.size; - return 0; - } -}; -} // end anonymous namespace - - -/// \brief Read the source manager block -PCHReader::PCHReadResult PCHReader::ReadSourceManagerBlock() { - using namespace SrcMgr; - - // Set the source-location entry cursor to the current position in - // the stream. This cursor will be used to read the contents of the - // source manager block initially, and then lazily read - // source-location entries as needed. - SLocEntryCursor = Stream; - - // The stream itself is going to skip over the source manager block. - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - - // Enter the source manager block. - if (SLocEntryCursor.EnterSubBlock(pch::SOURCE_MANAGER_BLOCK_ID)) { - Error("malformed source manager block record in PCH file"); - return Failure; - } - - RecordData Record; - while (true) { - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (SLocEntryCursor.ReadBlockEnd()) { - Error("error at end of Source Manager block in PCH file"); - return Failure; - } - return Success; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - SLocEntryCursor.ReadSubBlockID(); - if (SLocEntryCursor.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - SLocEntryCursor.ReadAbbrevRecord(); - continue; - } - - // Read a record. - const char *BlobStart; - unsigned BlobLen; - Record.clear(); - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::SM_LINE_TABLE: - if (ParseLineTable(Record)) - return Failure; - break; - - case pch::SM_SLOC_FILE_ENTRY: - case pch::SM_SLOC_BUFFER_ENTRY: - case pch::SM_SLOC_INSTANTIATION_ENTRY: - // Once we hit one of the source location entries, we're done. - return Success; - } - } -} - -/// \brief Read in the source location entry with the given ID. -PCHReader::PCHReadResult PCHReader::ReadSLocEntryRecord(unsigned ID) { - if (ID == 0) - return Success; - - if (ID > TotalNumSLocEntries) { - Error("source location entry ID out-of-range for PCH file"); - return Failure; - } - - ++NumSLocEntriesRead; - SLocEntryCursor.JumpToBit(SLocOffsets[ID - 1]); - unsigned Code = SLocEntryCursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK || - Code == llvm::bitc::ENTER_SUBBLOCK || - Code == llvm::bitc::DEFINE_ABBREV) { - Error("incorrectly-formatted source location entry in PCH file"); - return Failure; - } - - RecordData Record; - const char *BlobStart; - unsigned BlobLen; - switch (SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: - Error("incorrectly-formatted source location entry in PCH file"); - return Failure; - - case pch::SM_SLOC_FILE_ENTRY: { - std::string Filename(BlobStart, BlobStart + BlobLen); - MaybeAddSystemRootToFilename(Filename); - const FileEntry *File = FileMgr.getFile(Filename); - if (File == 0) { - std::string ErrorStr = "could not find file '"; - ErrorStr += Filename; - ErrorStr += "' referenced by PCH file"; - Error(ErrorStr.c_str()); - return Failure; - } - - if (Record.size() < 10) { - Error("source location entry is incorrect"); - return Failure; - } - - if ((off_t)Record[4] != File->getSize() -#if !defined(LLVM_ON_WIN32) - // In our regression testing, the Windows file system seems to - // have inconsistent modification times that sometimes - // erroneously trigger this error-handling path. - || (time_t)Record[5] != File->getModificationTime() -#endif - ) { - Diag(diag::err_fe_pch_file_modified) - << Filename; - return Failure; - } - - FileID FID = SourceMgr.createFileID(File, - SourceLocation::getFromRawEncoding(Record[1]), - (SrcMgr::CharacteristicKind)Record[2], - ID, Record[0]); - if (Record[3]) - const_cast<SrcMgr::FileInfo&>(SourceMgr.getSLocEntry(FID).getFile()) - .setHasLineDirectives(); - - // Reconstruct header-search information for this file. - HeaderFileInfo HFI; - HFI.isImport = Record[6]; - HFI.DirInfo = Record[7]; - HFI.NumIncludes = Record[8]; - HFI.ControllingMacroID = Record[9]; - if (Listener) - Listener->ReadHeaderFileInfo(HFI, File->getUID()); - break; - } - - case pch::SM_SLOC_BUFFER_ENTRY: { - const char *Name = BlobStart; - unsigned Offset = Record[0]; - unsigned Code = SLocEntryCursor.ReadCode(); - Record.clear(); - unsigned RecCode - = SLocEntryCursor.ReadRecord(Code, Record, &BlobStart, &BlobLen); - - if (RecCode != pch::SM_SLOC_BUFFER_BLOB) { - Error("PCH record has invalid code"); - return Failure; - } - - llvm::MemoryBuffer *Buffer - = llvm::MemoryBuffer::getMemBuffer(llvm::StringRef(BlobStart, BlobLen - 1), - Name); - FileID BufferID = SourceMgr.createFileIDForMemBuffer(Buffer, ID, Offset); - - if (strcmp(Name, "<built-in>") == 0) { - PCHPredefinesBlock Block = { - BufferID, - llvm::StringRef(BlobStart, BlobLen - 1) - }; - PCHPredefinesBuffers.push_back(Block); - } - - break; - } - - case pch::SM_SLOC_INSTANTIATION_ENTRY: { - SourceLocation SpellingLoc - = SourceLocation::getFromRawEncoding(Record[1]); - SourceMgr.createInstantiationLoc(SpellingLoc, - SourceLocation::getFromRawEncoding(Record[2]), - SourceLocation::getFromRawEncoding(Record[3]), - Record[4], - ID, - Record[0]); - break; - } - } - - return Success; -} - -/// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the -/// specified cursor. Read the abbreviations that are at the top of the block -/// and then leave the cursor pointing into the block. -bool PCHReader::ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, - unsigned BlockID) { - if (Cursor.EnterSubBlock(BlockID)) { - Error("malformed block record in PCH file"); - return Failure; - } - - while (true) { - unsigned Code = Cursor.ReadCode(); - - // We expect all abbrevs to be at the start of the block. - if (Code != llvm::bitc::DEFINE_ABBREV) - return false; - Cursor.ReadAbbrevRecord(); - } -} - -void PCHReader::ReadMacroRecord(uint64_t Offset) { - assert(PP && "Forgot to set Preprocessor ?"); - - // Keep track of where we are in the stream, then jump back there - // after reading this macro. - SavedStreamPosition SavedPosition(Stream); - - Stream.JumpToBit(Offset); - RecordData Record; - llvm::SmallVector<IdentifierInfo*, 16> MacroArgs; - MacroInfo *Macro = 0; - - while (true) { - unsigned Code = Stream.ReadCode(); - switch (Code) { - case llvm::bitc::END_BLOCK: - return; - - case llvm::bitc::ENTER_SUBBLOCK: - // No known subblocks, always skip them. - Stream.ReadSubBlockID(); - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return; - } - continue; - - case llvm::bitc::DEFINE_ABBREV: - Stream.ReadAbbrevRecord(); - continue; - default: break; - } - - // Read a record. - Record.clear(); - pch::PreprocessorRecordTypes RecType = - (pch::PreprocessorRecordTypes)Stream.ReadRecord(Code, Record); - switch (RecType) { - case pch::PP_MACRO_OBJECT_LIKE: - case pch::PP_MACRO_FUNCTION_LIKE: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - IdentifierInfo *II = DecodeIdentifierInfo(Record[0]); - if (II == 0) { - Error("macro must have a name in PCH file"); - return; - } - SourceLocation Loc = SourceLocation::getFromRawEncoding(Record[1]); - bool isUsed = Record[2]; - - MacroInfo *MI = PP->AllocateMacroInfo(Loc); - MI->setIsUsed(isUsed); - - unsigned NextIndex = 3; - if (RecType == pch::PP_MACRO_FUNCTION_LIKE) { - // Decode function-like macro info. - bool isC99VarArgs = Record[3]; - bool isGNUVarArgs = Record[4]; - MacroArgs.clear(); - unsigned NumArgs = Record[5]; - NextIndex = 6 + NumArgs; - for (unsigned i = 0; i != NumArgs; ++i) - MacroArgs.push_back(DecodeIdentifierInfo(Record[6+i])); - - // Install function-like macro info. - MI->setIsFunctionLike(); - if (isC99VarArgs) MI->setIsC99Varargs(); - if (isGNUVarArgs) MI->setIsGNUVarargs(); - MI->setArgumentList(MacroArgs.data(), MacroArgs.size(), - PP->getPreprocessorAllocator()); - } - - // Finally, install the macro. - PP->setMacroInfo(II, MI); - - // Remember that we saw this macro last so that we add the tokens that - // form its body to it. - Macro = MI; - - if (NextIndex + 1 == Record.size() && PP->getPreprocessingRecord()) { - // We have a macro definition. Load it now. - PP->getPreprocessingRecord()->RegisterMacroDefinition(Macro, - getMacroDefinition(Record[NextIndex])); - } - - ++NumMacrosRead; - break; - } - - case pch::PP_TOKEN: { - // If we see a TOKEN before a PP_MACRO_*, then the file is - // erroneous, just pretend we didn't see this. - if (Macro == 0) break; - - Token Tok; - Tok.startToken(); - Tok.setLocation(SourceLocation::getFromRawEncoding(Record[0])); - Tok.setLength(Record[1]); - if (IdentifierInfo *II = DecodeIdentifierInfo(Record[2])) - Tok.setIdentifierInfo(II); - Tok.setKind((tok::TokenKind)Record[3]); - Tok.setFlag((Token::TokenFlags)Record[4]); - Macro->AddTokenToBody(Tok); - break; - } - - case pch::PP_MACRO_INSTANTIATION: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in PCH file"); - return; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PPRec.getPreprocessedEntity(Record[0])) - return; - - MacroInstantiation *MI - = new (PPRec) MacroInstantiation(DecodeIdentifierInfo(Record[3]), - SourceRange( - SourceLocation::getFromRawEncoding(Record[1]), - SourceLocation::getFromRawEncoding(Record[2])), - getMacroDefinition(Record[4])); - PPRec.SetPreallocatedEntity(Record[0], MI); - return; - } - - case pch::PP_MACRO_DEFINITION: { - // If we already have a macro, that means that we've hit the end - // of the definition of the macro we were looking for. We're - // done. - if (Macro) - return; - - if (!PP->getPreprocessingRecord()) { - Error("missing preprocessing record in PCH file"); - return; - } - - PreprocessingRecord &PPRec = *PP->getPreprocessingRecord(); - if (PPRec.getPreprocessedEntity(Record[0])) - return; - - if (Record[1] >= MacroDefinitionsLoaded.size()) { - Error("out-of-bounds macro definition record"); - return; - } - - MacroDefinition *MD - = new (PPRec) MacroDefinition(DecodeIdentifierInfo(Record[4]), - SourceLocation::getFromRawEncoding(Record[5]), - SourceRange( - SourceLocation::getFromRawEncoding(Record[2]), - SourceLocation::getFromRawEncoding(Record[3]))); - PPRec.SetPreallocatedEntity(Record[0], MD); - MacroDefinitionsLoaded[Record[1]] = MD; - return; - } - } - } -} - -void PCHReader::ReadDefinedMacros() { - // If there was no preprocessor block, do nothing. - if (!MacroCursor.getBitStreamReader()) - return; - - llvm::BitstreamCursor Cursor = MacroCursor; - if (Cursor.EnterSubBlock(pch::PREPROCESSOR_BLOCK_ID)) { - Error("malformed preprocessor block record in PCH file"); - return; - } - - RecordData Record; - while (true) { - unsigned Code = Cursor.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Cursor.ReadBlockEnd()) - Error("error at end of preprocessor block in PCH file"); - return; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - // No known subblocks, always skip them. - Cursor.ReadSubBlockID(); - if (Cursor.SkipBlock()) { - Error("malformed block record in PCH file"); - return; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Cursor.ReadAbbrevRecord(); - continue; - } - - // Read a record. - const char *BlobStart; - unsigned BlobLen; - Record.clear(); - switch (Cursor.ReadRecord(Code, Record, &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::PP_MACRO_OBJECT_LIKE: - case pch::PP_MACRO_FUNCTION_LIKE: - DecodeIdentifierInfo(Record[0]); - break; - - case pch::PP_TOKEN: - // Ignore tokens. - break; - - case pch::PP_MACRO_INSTANTIATION: - case pch::PP_MACRO_DEFINITION: - // Read the macro record. - ReadMacroRecord(Cursor.GetCurrentBitNo()); - break; - } - } -} - -MacroDefinition *PCHReader::getMacroDefinition(pch::IdentID ID) { - if (ID == 0 || ID >= MacroDefinitionsLoaded.size()) - return 0; - - if (!MacroDefinitionsLoaded[ID]) - ReadMacroRecord(MacroDefinitionOffsets[ID]); - - return MacroDefinitionsLoaded[ID]; -} - -/// \brief If we are loading a relocatable PCH file, and the filename is -/// not an absolute path, add the system root to the beginning of the file -/// name. -void PCHReader::MaybeAddSystemRootToFilename(std::string &Filename) { - // If this is not a relocatable PCH file, there's nothing to do. - if (!RelocatablePCH) - return; - - if (Filename.empty() || llvm::sys::Path(Filename).isAbsolute()) - return; - - if (isysroot == 0) { - // If no system root was given, default to '/' - Filename.insert(Filename.begin(), '/'); - return; - } - - unsigned Length = strlen(isysroot); - if (isysroot[Length - 1] != '/') - Filename.insert(Filename.begin(), '/'); - - Filename.insert(Filename.begin(), isysroot, isysroot + Length); -} - -PCHReader::PCHReadResult -PCHReader::ReadPCHBlock() { - if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { - Error("malformed block record in PCH file"); - return Failure; - } - - // Read all of the records and blocks for the PCH file. - RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Error("error at end of module block in PCH file"); - return Failure; - } - - return Success; - } - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - switch (Stream.ReadSubBlockID()) { - case pch::DECLTYPES_BLOCK_ID: - // We lazily load the decls block, but we want to set up the - // DeclsCursor cursor to point into it. Clone our current bitcode - // cursor to it, enter the block and read the abbrevs in that block. - // With the main cursor, we just skip over it. - DeclsCursor = Stream; - if (Stream.SkipBlock() || // Skip with the main cursor. - // Read the abbrevs. - ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - - case pch::PREPROCESSOR_BLOCK_ID: - MacroCursor = Stream; - if (PP) - PP->setExternalSource(this); - - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - - case pch::SOURCE_MANAGER_BLOCK_ID: - switch (ReadSourceManagerBlock()) { - case Success: - break; - - case Failure: - Error("malformed source manager block in PCH file"); - return Failure; - - case IgnorePCH: - return IgnorePCH; - } - break; - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; - } - - // Read and process a record. - Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - switch ((pch::PCHRecordTypes)Stream.ReadRecord(Code, Record, - &BlobStart, &BlobLen)) { - default: // Default behavior: ignore. - break; - - case pch::TYPE_OFFSET: - if (!TypesLoaded.empty()) { - Error("duplicate TYPE_OFFSET record in PCH file"); - return Failure; - } - TypeOffsets = (const uint32_t *)BlobStart; - TypesLoaded.resize(Record[0]); - break; - - case pch::DECL_OFFSET: - if (!DeclsLoaded.empty()) { - Error("duplicate DECL_OFFSET record in PCH file"); - return Failure; - } - DeclOffsets = (const uint32_t *)BlobStart; - DeclsLoaded.resize(Record[0]); - break; - - case pch::LANGUAGE_OPTIONS: - if (ParseLanguageOptions(Record)) - return IgnorePCH; - break; - - case pch::METADATA: { - if (Record[0] != pch::VERSION_MAJOR) { - Diag(Record[0] < pch::VERSION_MAJOR? diag::warn_pch_version_too_old - : diag::warn_pch_version_too_new); - return IgnorePCH; - } - - RelocatablePCH = Record[4]; - if (Listener) { - std::string TargetTriple(BlobStart, BlobLen); - if (Listener->ReadTargetTriple(TargetTriple)) - return IgnorePCH; - } - break; - } - - case pch::IDENTIFIER_TABLE: - IdentifierTableData = BlobStart; - if (Record[0]) { - IdentifierLookupTable - = PCHIdentifierLookupTable::Create( - (const unsigned char *)IdentifierTableData + Record[0], - (const unsigned char *)IdentifierTableData, - PCHIdentifierLookupTrait(*this)); - if (PP) - PP->getIdentifierTable().setExternalIdentifierLookup(this); - } - break; - - case pch::IDENTIFIER_OFFSET: - if (!IdentifiersLoaded.empty()) { - Error("duplicate IDENTIFIER_OFFSET record in PCH file"); - return Failure; - } - IdentifierOffsets = (const uint32_t *)BlobStart; - IdentifiersLoaded.resize(Record[0]); - if (PP) - PP->getHeaderSearchInfo().SetExternalLookup(this); - break; - - case pch::EXTERNAL_DEFINITIONS: - if (!ExternalDefinitions.empty()) { - Error("duplicate EXTERNAL_DEFINITIONS record in PCH file"); - return Failure; - } - ExternalDefinitions.swap(Record); - break; - - case pch::SPECIAL_TYPES: - SpecialTypes.swap(Record); - break; - - case pch::STATISTICS: - TotalNumStatements = Record[0]; - TotalNumMacros = Record[1]; - TotalLexicalDeclContexts = Record[2]; - TotalVisibleDeclContexts = Record[3]; - break; - - case pch::TENTATIVE_DEFINITIONS: - if (!TentativeDefinitions.empty()) { - Error("duplicate TENTATIVE_DEFINITIONS record in PCH file"); - return Failure; - } - TentativeDefinitions.swap(Record); - break; - - case pch::UNUSED_STATIC_FUNCS: - if (!UnusedStaticFuncs.empty()) { - Error("duplicate UNUSED_STATIC_FUNCS record in PCH file"); - return Failure; - } - UnusedStaticFuncs.swap(Record); - break; - - case pch::LOCALLY_SCOPED_EXTERNAL_DECLS: - if (!LocallyScopedExternalDecls.empty()) { - Error("duplicate LOCALLY_SCOPED_EXTERNAL_DECLS record in PCH file"); - return Failure; - } - LocallyScopedExternalDecls.swap(Record); - break; - - case pch::SELECTOR_OFFSETS: - SelectorOffsets = (const uint32_t *)BlobStart; - TotalNumSelectors = Record[0]; - SelectorsLoaded.resize(TotalNumSelectors); - break; - - case pch::METHOD_POOL: - MethodPoolLookupTableData = (const unsigned char *)BlobStart; - if (Record[0]) - MethodPoolLookupTable - = PCHMethodPoolLookupTable::Create( - MethodPoolLookupTableData + Record[0], - MethodPoolLookupTableData, - PCHMethodPoolLookupTrait(*this)); - TotalSelectorsInMethodPool = Record[1]; - break; - - case pch::PP_COUNTER_VALUE: - if (!Record.empty() && Listener) - Listener->ReadCounter(Record[0]); - break; - - case pch::SOURCE_LOCATION_OFFSETS: - SLocOffsets = (const uint32_t *)BlobStart; - TotalNumSLocEntries = Record[0]; - SourceMgr.PreallocateSLocEntries(this, TotalNumSLocEntries, Record[1]); - break; - - case pch::SOURCE_LOCATION_PRELOADS: - for (unsigned I = 0, N = Record.size(); I != N; ++I) { - PCHReadResult Result = ReadSLocEntryRecord(Record[I]); - if (Result != Success) - return Result; - } - break; - - case pch::STAT_CACHE: { - PCHStatCache *MyStatCache = - new PCHStatCache((const unsigned char *)BlobStart + Record[0], - (const unsigned char *)BlobStart, - NumStatHits, NumStatMisses); - FileMgr.addStatCache(MyStatCache); - StatCache = MyStatCache; - break; - } - - case pch::EXT_VECTOR_DECLS: - if (!ExtVectorDecls.empty()) { - Error("duplicate EXT_VECTOR_DECLS record in PCH file"); - return Failure; - } - ExtVectorDecls.swap(Record); - break; - - case pch::VTABLE_USES: - if (!VTableUses.empty()) { - Error("duplicate VTABLE_USES record in PCH file"); - return Failure; - } - VTableUses.swap(Record); - break; - - case pch::DYNAMIC_CLASSES: - if (!DynamicClasses.empty()) { - Error("duplicate DYNAMIC_CLASSES record in PCH file"); - return Failure; - } - DynamicClasses.swap(Record); - break; - - case pch::ORIGINAL_FILE_NAME: - ActualOriginalFileName.assign(BlobStart, BlobLen); - OriginalFileName = ActualOriginalFileName; - MaybeAddSystemRootToFilename(OriginalFileName); - break; - - case pch::VERSION_CONTROL_BRANCH_REVISION: { - const std::string &CurBranch = getClangFullRepositoryVersion(); - llvm::StringRef PCHBranch(BlobStart, BlobLen); - if (llvm::StringRef(CurBranch) != PCHBranch) { - Diag(diag::warn_pch_different_branch) << PCHBranch << CurBranch; - return IgnorePCH; - } - break; - } - - case pch::MACRO_DEFINITION_OFFSETS: - MacroDefinitionOffsets = (const uint32_t *)BlobStart; - if (PP) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, Record[0]); - } else { - NumPreallocatedPreprocessingEntities = Record[0]; - } - - MacroDefinitionsLoaded.resize(Record[1]); - break; - } - } - Error("premature end of bitstream in PCH file"); - return Failure; -} - -PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) { - // Set the PCH file name. - this->FileName = FileName; - - // Open the PCH file. - // - // FIXME: This shouldn't be here, we should just take a raw_ostream. - std::string ErrStr; - Buffer.reset(llvm::MemoryBuffer::getFileOrSTDIN(FileName, &ErrStr)); - if (!Buffer) { - Error(ErrStr.c_str()); - return IgnorePCH; - } - - // Initialize the stream - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); - - // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { - Diag(diag::err_not_a_pch_file) << FileName; - return Failure; - } - - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code != llvm::bitc::ENTER_SUBBLOCK) { - Error("invalid record at top-level of PCH file"); - return Failure; - } - - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the PCH subblock ID. - switch (BlockID) { - case llvm::bitc::BLOCKINFO_BLOCK_ID: - if (Stream.ReadBlockInfoBlock()) { - Error("malformed BlockInfoBlock in PCH file"); - return Failure; - } - break; - case pch::PCH_BLOCK_ID: - switch (ReadPCHBlock()) { - case Success: - break; - - case Failure: - return Failure; - - case IgnorePCH: - // FIXME: We could consider reading through to the end of this - // PCH block, skipping subblocks, to see if there are other - // PCH blocks elsewhere. - - // Clear out any preallocated source location entries, so that - // the source manager does not try to resolve them later. - SourceMgr.ClearPreallocatedSLocEntries(); - - // Remove the stat cache. - if (StatCache) - FileMgr.removeStatCache((PCHStatCache*)StatCache); - - return IgnorePCH; - } - break; - default: - if (Stream.SkipBlock()) { - Error("malformed block record in PCH file"); - return Failure; - } - break; - } - } - - // Check the predefines buffer. - if (CheckPredefinesBuffers()) - return IgnorePCH; - - if (PP) { - // Initialization of keywords and pragmas occurs before the - // PCH file is read, so there may be some identifiers that were - // loaded into the IdentifierTable before we intercepted the - // creation of identifiers. Iterate through the list of known - // identifiers and determine whether we have to establish - // preprocessor definitions or top-level identifier declaration - // chains for those identifiers. - // - // We copy the IdentifierInfo pointers to a small vector first, - // since de-serializing declarations or macro definitions can add - // new entries into the identifier table, invalidating the - // iterators. - llvm::SmallVector<IdentifierInfo *, 128> Identifiers; - for (IdentifierTable::iterator Id = PP->getIdentifierTable().begin(), - IdEnd = PP->getIdentifierTable().end(); - Id != IdEnd; ++Id) - Identifiers.push_back(Id->second); - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)IdentifierLookupTable; - for (unsigned I = 0, N = Identifiers.size(); I != N; ++I) { - IdentifierInfo *II = Identifiers[I]; - // Look in the on-disk hash table for an entry for - PCHIdentifierLookupTrait Info(*this, II); - std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength()); - PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info); - if (Pos == IdTable->end()) - continue; - - // Dereferencing the iterator has the effect of populating the - // IdentifierInfo node with the various declarations it needs. - (void)*Pos; - } - } - - if (Context) - InitializeContext(*Context); - - return Success; -} - -void PCHReader::setPreprocessor(Preprocessor &pp) { - PP = &pp; - - if (NumPreallocatedPreprocessingEntities) { - if (!PP->getPreprocessingRecord()) - PP->createPreprocessingRecord(); - PP->getPreprocessingRecord()->SetExternalSource(*this, - NumPreallocatedPreprocessingEntities); - NumPreallocatedPreprocessingEntities = 0; - } -} - -void PCHReader::InitializeContext(ASTContext &Ctx) { - Context = &Ctx; - assert(Context && "Passed null context!"); - - assert(PP && "Forgot to set Preprocessor ?"); - PP->getIdentifierTable().setExternalIdentifierLookup(this); - PP->getHeaderSearchInfo().SetExternalLookup(this); - PP->setExternalSource(this); - - // Load the translation unit declaration - GetTranslationUnitDecl(); - - // Load the special types. - Context->setBuiltinVaListType( - GetType(SpecialTypes[pch::SPECIAL_TYPE_BUILTIN_VA_LIST])); - if (unsigned Id = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID]) - Context->setObjCIdType(GetType(Id)); - if (unsigned Sel = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SELECTOR]) - Context->setObjCSelType(GetType(Sel)); - if (unsigned Proto = SpecialTypes[pch::SPECIAL_TYPE_OBJC_PROTOCOL]) - Context->setObjCProtoType(GetType(Proto)); - if (unsigned Class = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS]) - Context->setObjCClassType(GetType(Class)); - - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_CF_CONSTANT_STRING]) - Context->setCFConstantStringType(GetType(String)); - if (unsigned FastEnum - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_FAST_ENUMERATION_STATE]) - Context->setObjCFastEnumerationStateType(GetType(FastEnum)); - if (unsigned File = SpecialTypes[pch::SPECIAL_TYPE_FILE]) { - QualType FileType = GetType(File); - if (FileType.isNull()) { - Error("FILE type is NULL"); - return; - } - if (const TypedefType *Typedef = FileType->getAs<TypedefType>()) - Context->setFILEDecl(Typedef->getDecl()); - else { - const TagType *Tag = FileType->getAs<TagType>(); - if (!Tag) { - Error("Invalid FILE type in PCH file"); - return; - } - Context->setFILEDecl(Tag->getDecl()); - } - } - if (unsigned Jmp_buf = SpecialTypes[pch::SPECIAL_TYPE_jmp_buf]) { - QualType Jmp_bufType = GetType(Jmp_buf); - if (Jmp_bufType.isNull()) { - Error("jmp_bug type is NULL"); - return; - } - if (const TypedefType *Typedef = Jmp_bufType->getAs<TypedefType>()) - Context->setjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Jmp_bufType->getAs<TagType>(); - if (!Tag) { - Error("Invalid jmp_bug type in PCH file"); - return; - } - Context->setjmp_bufDecl(Tag->getDecl()); - } - } - if (unsigned Sigjmp_buf = SpecialTypes[pch::SPECIAL_TYPE_sigjmp_buf]) { - QualType Sigjmp_bufType = GetType(Sigjmp_buf); - if (Sigjmp_bufType.isNull()) { - Error("sigjmp_buf type is NULL"); - return; - } - if (const TypedefType *Typedef = Sigjmp_bufType->getAs<TypedefType>()) - Context->setsigjmp_bufDecl(Typedef->getDecl()); - else { - const TagType *Tag = Sigjmp_bufType->getAs<TagType>(); - assert(Tag && "Invalid sigjmp_buf type in PCH file"); - Context->setsigjmp_bufDecl(Tag->getDecl()); - } - } - if (unsigned ObjCIdRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_ID_REDEFINITION]) - Context->ObjCIdRedefinitionType = GetType(ObjCIdRedef); - if (unsigned ObjCClassRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION]) - Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) - Context->setBlockDescriptorType(GetType(String)); - if (unsigned String - = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) - Context->setBlockDescriptorExtendedType(GetType(String)); - if (unsigned ObjCSelRedef - = SpecialTypes[pch::SPECIAL_TYPE_OBJC_SEL_REDEFINITION]) - Context->ObjCSelRedefinitionType = GetType(ObjCSelRedef); - if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_NS_CONSTANT_STRING]) - Context->setNSConstantStringType(GetType(String)); - - if (SpecialTypes[pch::SPECIAL_TYPE_INT128_INSTALLED]) - Context->setInt128Installed(); -} - -/// \brief Retrieve the name of the original source file name -/// directly from the PCH file, without actually loading the PCH -/// file. -std::string PCHReader::getOriginalSourceFile(const std::string &PCHFileName, - Diagnostic &Diags) { - // Open the PCH file. - std::string ErrStr; - llvm::OwningPtr<llvm::MemoryBuffer> Buffer; - Buffer.reset(llvm::MemoryBuffer::getFile(PCHFileName.c_str(), &ErrStr)); - if (!Buffer) { - Diags.Report(diag::err_fe_unable_to_read_pch_file) << ErrStr; - return std::string(); - } - - // Initialize the stream - llvm::BitstreamReader StreamFile; - llvm::BitstreamCursor Stream; - StreamFile.init((const unsigned char *)Buffer->getBufferStart(), - (const unsigned char *)Buffer->getBufferEnd()); - Stream.init(StreamFile); - - // Sniff for the signature. - if (Stream.Read(8) != 'C' || - Stream.Read(8) != 'P' || - Stream.Read(8) != 'C' || - Stream.Read(8) != 'H') { - Diags.Report(diag::err_fe_not_a_pch_file) << PCHFileName; - return std::string(); - } - - RecordData Record; - while (!Stream.AtEndOfStream()) { - unsigned Code = Stream.ReadCode(); - - if (Code == llvm::bitc::ENTER_SUBBLOCK) { - unsigned BlockID = Stream.ReadSubBlockID(); - - // We only know the PCH subblock ID. - switch (BlockID) { - case pch::PCH_BLOCK_ID: - if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) { - Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName; - return std::string(); - } - break; - - default: - if (Stream.SkipBlock()) { - Diags.Report(diag::err_fe_pch_malformed_block) << PCHFileName; - return std::string(); - } - break; - } - continue; - } - - if (Code == llvm::bitc::END_BLOCK) { - if (Stream.ReadBlockEnd()) { - Diags.Report(diag::err_fe_pch_error_at_end_block) << PCHFileName; - return std::string(); - } - continue; - } - - if (Code == llvm::bitc::DEFINE_ABBREV) { - Stream.ReadAbbrevRecord(); - continue; - } - - Record.clear(); - const char *BlobStart = 0; - unsigned BlobLen = 0; - if (Stream.ReadRecord(Code, Record, &BlobStart, &BlobLen) - == pch::ORIGINAL_FILE_NAME) - return std::string(BlobStart, BlobLen); - } - - return std::string(); -} - -/// \brief Parse the record that corresponds to a LangOptions data -/// structure. -/// -/// This routine compares the language options used to generate the -/// PCH file against the language options set for the current -/// compilation. For each option, we classify differences between the -/// two compiler states as either "benign" or "important". Benign -/// differences don't matter, and we accept them without complaint -/// (and without modifying the language options). Differences between -/// the states for important options cause the PCH file to be -/// unusable, so we emit a warning and return true to indicate that -/// there was an error. -/// -/// \returns true if the PCH file is unacceptable, false otherwise. -bool PCHReader::ParseLanguageOptions( - const llvm::SmallVectorImpl<uint64_t> &Record) { - if (Listener) { - LangOptions LangOpts; - - #define PARSE_LANGOPT(Option) \ - LangOpts.Option = Record[Idx]; \ - ++Idx - - unsigned Idx = 0; - PARSE_LANGOPT(Trigraphs); - PARSE_LANGOPT(BCPLComment); - PARSE_LANGOPT(DollarIdents); - PARSE_LANGOPT(AsmPreprocessor); - PARSE_LANGOPT(GNUMode); - PARSE_LANGOPT(GNUKeywords); - PARSE_LANGOPT(ImplicitInt); - PARSE_LANGOPT(Digraphs); - PARSE_LANGOPT(HexFloats); - PARSE_LANGOPT(C99); - PARSE_LANGOPT(Microsoft); - PARSE_LANGOPT(CPlusPlus); - PARSE_LANGOPT(CPlusPlus0x); - PARSE_LANGOPT(CXXOperatorNames); - PARSE_LANGOPT(ObjC1); - PARSE_LANGOPT(ObjC2); - PARSE_LANGOPT(ObjCNonFragileABI); - PARSE_LANGOPT(ObjCNonFragileABI2); - PARSE_LANGOPT(NoConstantCFStrings); - PARSE_LANGOPT(PascalStrings); - PARSE_LANGOPT(WritableStrings); - PARSE_LANGOPT(LaxVectorConversions); - PARSE_LANGOPT(AltiVec); - PARSE_LANGOPT(Exceptions); - PARSE_LANGOPT(SjLjExceptions); - PARSE_LANGOPT(NeXTRuntime); - PARSE_LANGOPT(Freestanding); - PARSE_LANGOPT(NoBuiltin); - PARSE_LANGOPT(ThreadsafeStatics); - PARSE_LANGOPT(POSIXThreads); - PARSE_LANGOPT(Blocks); - PARSE_LANGOPT(EmitAllDecls); - PARSE_LANGOPT(MathErrno); - LangOpts.setSignedOverflowBehavior((LangOptions::SignedOverflowBehaviorTy) - Record[Idx++]); - PARSE_LANGOPT(HeinousExtensions); - PARSE_LANGOPT(Optimize); - PARSE_LANGOPT(OptimizeSize); - PARSE_LANGOPT(Static); - PARSE_LANGOPT(PICLevel); - PARSE_LANGOPT(GNUInline); - PARSE_LANGOPT(NoInline); - PARSE_LANGOPT(AccessControl); - PARSE_LANGOPT(CharIsSigned); - PARSE_LANGOPT(ShortWChar); - LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]); - LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]); - LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode) - Record[Idx++]); - PARSE_LANGOPT(InstantiationDepth); - PARSE_LANGOPT(OpenCL); - PARSE_LANGOPT(CatchUndefined); - // FIXME: Missing ElideConstructors?! - #undef PARSE_LANGOPT - - return Listener->ReadLanguageOptions(LangOpts); - } - - return false; -} - -void PCHReader::ReadPreprocessedEntities() { - ReadDefinedMacros(); -} - -/// \brief Read and return the type at the given offset. -/// -/// This routine actually reads the record corresponding to the type -/// at the given offset in the bitstream. It is a helper routine for -/// GetType, which deals with reading type IDs. -QualType PCHReader::ReadTypeRecord(uint64_t Offset) { - // Keep track of where we are in the stream, then jump back there - // after reading this type. - SavedStreamPosition SavedPosition(DeclsCursor); - - ReadingKindTracker ReadingKind(Read_Type, *this); - - // Note that we are loading a type record. - LoadingTypeOrDecl Loading(*this); - - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) { - case pch::TYPE_EXT_QUAL: { - if (Record.size() != 2) { - Error("Incorrect encoding of extended qualifier type"); - return QualType(); - } - QualType Base = GetType(Record[0]); - Qualifiers Quals = Qualifiers::fromOpaqueValue(Record[1]); - return Context->getQualifiedType(Base, Quals); - } - - case pch::TYPE_COMPLEX: { - if (Record.size() != 1) { - Error("Incorrect encoding of complex type"); - return QualType(); - } - QualType ElemType = GetType(Record[0]); - return Context->getComplexType(ElemType); - } - - case pch::TYPE_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getPointerType(PointeeType); - } - - case pch::TYPE_BLOCK_POINTER: { - if (Record.size() != 1) { - Error("Incorrect encoding of block pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getBlockPointerType(PointeeType); - } - - case pch::TYPE_LVALUE_REFERENCE: { - if (Record.size() != 1) { - Error("Incorrect encoding of lvalue reference type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getLValueReferenceType(PointeeType); - } - - case pch::TYPE_RVALUE_REFERENCE: { - if (Record.size() != 1) { - Error("Incorrect encoding of rvalue reference type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - return Context->getRValueReferenceType(PointeeType); - } - - case pch::TYPE_MEMBER_POINTER: { - if (Record.size() != 2) { - Error("Incorrect encoding of member pointer type"); - return QualType(); - } - QualType PointeeType = GetType(Record[0]); - QualType ClassType = GetType(Record[1]); - return Context->getMemberPointerType(PointeeType, ClassType.getTypePtr()); - } - - case pch::TYPE_CONSTANT_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - unsigned Idx = 3; - llvm::APInt Size = ReadAPInt(Record, Idx); - return Context->getConstantArrayType(ElementType, Size, - ASM, IndexTypeQuals); - } - - case pch::TYPE_INCOMPLETE_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - return Context->getIncompleteArrayType(ElementType, ASM, IndexTypeQuals); - } - - case pch::TYPE_VARIABLE_ARRAY: { - QualType ElementType = GetType(Record[0]); - ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; - unsigned IndexTypeQuals = Record[2]; - SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); - SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); - return Context->getVariableArrayType(ElementType, ReadExpr(), - ASM, IndexTypeQuals, - SourceRange(LBLoc, RBLoc)); - } - - case pch::TYPE_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of vector type in PCH file"); - return QualType(); - } - - QualType ElementType = GetType(Record[0]); - unsigned NumElements = Record[1]; - unsigned AltiVecSpec = Record[2]; - return Context->getVectorType(ElementType, NumElements, - (VectorType::AltiVecSpecific)AltiVecSpec); - } - - case pch::TYPE_EXT_VECTOR: { - if (Record.size() != 3) { - Error("incorrect encoding of extended vector type in PCH file"); - return QualType(); - } - - QualType ElementType = GetType(Record[0]); - unsigned NumElements = Record[1]; - return Context->getExtVectorType(ElementType, NumElements); - } - - case pch::TYPE_FUNCTION_NO_PROTO: { - if (Record.size() != 4) { - Error("incorrect encoding of no-proto function type"); - return QualType(); - } - QualType ResultType = GetType(Record[0]); - FunctionType::ExtInfo Info(Record[1], Record[2], (CallingConv)Record[3]); - return Context->getFunctionNoProtoType(ResultType, Info); - } - - case pch::TYPE_FUNCTION_PROTO: { - QualType ResultType = GetType(Record[0]); - bool NoReturn = Record[1]; - unsigned RegParm = Record[2]; - CallingConv CallConv = (CallingConv)Record[3]; - unsigned Idx = 4; - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<QualType, 16> ParamTypes; - for (unsigned I = 0; I != NumParams; ++I) - ParamTypes.push_back(GetType(Record[Idx++])); - bool isVariadic = Record[Idx++]; - unsigned Quals = Record[Idx++]; - bool hasExceptionSpec = Record[Idx++]; - bool hasAnyExceptionSpec = Record[Idx++]; - unsigned NumExceptions = Record[Idx++]; - llvm::SmallVector<QualType, 2> Exceptions; - for (unsigned I = 0; I != NumExceptions; ++I) - Exceptions.push_back(GetType(Record[Idx++])); - return Context->getFunctionType(ResultType, ParamTypes.data(), NumParams, - isVariadic, Quals, hasExceptionSpec, - hasAnyExceptionSpec, NumExceptions, - Exceptions.data(), - FunctionType::ExtInfo(NoReturn, RegParm, - CallConv)); - } - - case pch::TYPE_UNRESOLVED_USING: - return Context->getTypeDeclType( - cast<UnresolvedUsingTypenameDecl>(GetDecl(Record[0]))); - - case pch::TYPE_TYPEDEF: { - if (Record.size() != 2) { - Error("incorrect encoding of typedef type"); - return QualType(); - } - TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0])); - QualType Canonical = GetType(Record[1]); - return Context->getTypedefType(Decl, Canonical); - } - - case pch::TYPE_TYPEOF_EXPR: - return Context->getTypeOfExprType(ReadExpr()); - - case pch::TYPE_TYPEOF: { - if (Record.size() != 1) { - Error("incorrect encoding of typeof(type) in PCH file"); - return QualType(); - } - QualType UnderlyingType = GetType(Record[0]); - return Context->getTypeOfType(UnderlyingType); - } - - case pch::TYPE_DECLTYPE: - return Context->getDecltypeType(ReadExpr()); - - case pch::TYPE_RECORD: { - if (Record.size() != 2) { - Error("incorrect encoding of record type"); - return QualType(); - } - bool IsDependent = Record[0]; - QualType T = Context->getRecordType(cast<RecordDecl>(GetDecl(Record[1]))); - T->Dependent = IsDependent; - return T; - } - - case pch::TYPE_ENUM: { - if (Record.size() != 2) { - Error("incorrect encoding of enum type"); - return QualType(); - } - bool IsDependent = Record[0]; - QualType T = Context->getEnumType(cast<EnumDecl>(GetDecl(Record[1]))); - T->Dependent = IsDependent; - return T; - } - - case pch::TYPE_ELABORATED: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - QualType NamedType = GetType(Record[Idx++]); - return Context->getElaboratedType(Keyword, NNS, NamedType); - } - - case pch::TYPE_OBJC_INTERFACE: { - unsigned Idx = 0; - ObjCInterfaceDecl *ItfD = cast<ObjCInterfaceDecl>(GetDecl(Record[Idx++])); - return Context->getObjCInterfaceType(ItfD); - } - - case pch::TYPE_OBJC_OBJECT: { - unsigned Idx = 0; - QualType Base = GetType(Record[Idx++]); - unsigned NumProtos = Record[Idx++]; - llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); - return Context->getObjCObjectType(Base, Protos.data(), NumProtos); - } - - case pch::TYPE_OBJC_OBJECT_POINTER: { - unsigned Idx = 0; - QualType Pointee = GetType(Record[Idx++]); - return Context->getObjCObjectPointerType(Pointee); - } - - case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - QualType Parm = GetType(Record[Idx++]); - QualType Replacement = GetType(Record[Idx++]); - return - Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), - Replacement); - } - - case pch::TYPE_INJECTED_CLASS_NAME: { - CXXRecordDecl *D = cast<CXXRecordDecl>(GetDecl(Record[0])); - QualType TST = GetType(Record[1]); // probably derivable - // FIXME: ASTContext::getInjectedClassNameType is not currently suitable - // for PCH reading, too much interdependencies. - return - QualType(new (*Context, TypeAlignment) InjectedClassNameType(D, TST), 0); - } - - case pch::TYPE_TEMPLATE_TYPE_PARM: { - unsigned Idx = 0; - unsigned Depth = Record[Idx++]; - unsigned Index = Record[Idx++]; - bool Pack = Record[Idx++]; - IdentifierInfo *Name = GetIdentifierInfo(Record, Idx); - return Context->getTemplateTypeParmType(Depth, Index, Pack, Name); - } - - case pch::TYPE_DEPENDENT_NAME: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); - QualType Canon = GetType(Record[Idx++]); - return Context->getDependentNameType(Keyword, NNS, Name, Canon); - } - - case pch::TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - ElaboratedTypeKeyword Keyword = (ElaboratedTypeKeyword)Record[Idx++]; - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - const IdentifierInfo *Name = this->GetIdentifierInfo(Record, Idx); - unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(Record, Idx)); - return Context->getDependentTemplateSpecializationType(Keyword, NNS, Name, - Args.size(), Args.data()); - } - - case pch::TYPE_DEPENDENT_SIZED_ARRAY: { - unsigned Idx = 0; - - // ArrayType - QualType ElementType = GetType(Record[Idx++]); - ArrayType::ArraySizeModifier ASM - = (ArrayType::ArraySizeModifier)Record[Idx++]; - unsigned IndexTypeQuals = Record[Idx++]; - - // DependentSizedArrayType - Expr *NumElts = ReadExpr(); - SourceRange Brackets = ReadSourceRange(Record, Idx); - - return Context->getDependentSizedArrayType(ElementType, NumElts, ASM, - IndexTypeQuals, Brackets); - } - - case pch::TYPE_TEMPLATE_SPECIALIZATION: { - unsigned Idx = 0; - bool IsDependent = Record[Idx++]; - TemplateName Name = ReadTemplateName(Record, Idx); - llvm::SmallVector<TemplateArgument, 8> Args; - ReadTemplateArgumentList(Args, Record, Idx); - QualType Canon = GetType(Record[Idx++]); - QualType T; - if (Canon.isNull()) - T = Context->getCanonicalTemplateSpecializationType(Name, Args.data(), - Args.size()); - else - T = Context->getTemplateSpecializationType(Name, Args.data(), - Args.size(), Canon); - T->Dependent = IsDependent; - return T; - } - } - // Suppress a GCC warning - return QualType(); -} - -namespace { - -class TypeLocReader : public TypeLocVisitor<TypeLocReader> { - PCHReader &Reader; - const PCHReader::RecordData &Record; - unsigned &Idx; - -public: - TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record, - unsigned &Idx) - : Reader(Reader), Record(Record), Idx(Idx) { } - - // We want compile-time assurance that we've enumerated all of - // these, so unfortunately we have to declare them first, then - // define them out-of-line. -#define ABSTRACT_TYPELOC(CLASS, PARENT) -#define TYPELOC(CLASS, PARENT) \ - void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); -#include "clang/AST/TypeLocNodes.def" - - void VisitFunctionTypeLoc(FunctionTypeLoc); - void VisitArrayTypeLoc(ArrayTypeLoc); -}; - -} - -void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { - // nothing to do -} -void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { - TL.setBuiltinLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - if (TL.needsExtraLocalData()) { - TL.setWrittenTypeSpec(static_cast<DeclSpec::TST>(Record[Idx++])); - TL.setWrittenSignSpec(static_cast<DeclSpec::TSS>(Record[Idx++])); - TL.setWrittenWidthSpec(static_cast<DeclSpec::TSW>(Record[Idx++])); - TL.setModeAttr(Record[Idx++]); - } -} -void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { - TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { - TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { - TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { - TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - if (Record[Idx++]) - TL.setSizeExpr(Reader.ReadExpr()); - else - TL.setSizeExpr(0); -} -void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitDependentSizedArrayTypeLoc( - DependentSizedArrayTypeLoc TL) { - VisitArrayTypeLoc(TL); -} -void TypeLocReader::VisitDependentSizedExtVectorTypeLoc( - DependentSizedExtVectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { - TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); - } -} -void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { - VisitFunctionTypeLoc(TL); -} -void TypeLocReader::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { - TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { - TL.setTypeofLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setUnderlyingTInfo(Reader.GetTypeSourceInfo(Record, Idx)); -} -void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( - SubstTemplateTypeParmTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTemplateSpecializationTypeLoc( - TemplateSpecializationTypeLoc TL) { - TL.setTemplateNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) - TL.setArgLocInfo(i, - Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(i).getKind(), - Record, Idx)); -} -void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); -} -void TypeLocReader::VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitDependentNameTypeLoc(DependentNameTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitDependentTemplateSpecializationTypeLoc( - DependentTemplateSpecializationTypeLoc TL) { - TL.setKeywordLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setQualifierRange(Reader.ReadSourceRange(Record, Idx)); - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) - TL.setArgLocInfo(I, - Reader.GetTemplateArgumentLocInfo(TL.getTypePtr()->getArg(I).getKind(), - Record, Idx)); -} -void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { - TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) { - TL.setHasBaseTypeAsWritten(Record[Idx++]); - TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} - -TypeSourceInfo *PCHReader::GetTypeSourceInfo(const RecordData &Record, - unsigned &Idx) { - QualType InfoTy = GetType(Record[Idx++]); - if (InfoTy.isNull()) - return 0; - - TypeSourceInfo *TInfo = getContext()->CreateTypeSourceInfo(InfoTy); - TypeLocReader TLR(*this, Record, Idx); - for (TypeLoc TL = TInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) - TLR.Visit(TL); - return TInfo; -} - -QualType PCHReader::GetType(pch::TypeID ID) { - unsigned FastQuals = ID & Qualifiers::FastMask; - unsigned Index = ID >> Qualifiers::FastWidth; - - if (Index < pch::NUM_PREDEF_TYPE_IDS) { - QualType T; - switch ((pch::PredefinedTypeIDs)Index) { - case pch::PREDEF_TYPE_NULL_ID: return QualType(); - case pch::PREDEF_TYPE_VOID_ID: T = Context->VoidTy; break; - case pch::PREDEF_TYPE_BOOL_ID: T = Context->BoolTy; break; - - case pch::PREDEF_TYPE_CHAR_U_ID: - case pch::PREDEF_TYPE_CHAR_S_ID: - // FIXME: Check that the signedness of CharTy is correct! - T = Context->CharTy; - break; - - case pch::PREDEF_TYPE_UCHAR_ID: T = Context->UnsignedCharTy; break; - case pch::PREDEF_TYPE_USHORT_ID: T = Context->UnsignedShortTy; break; - case pch::PREDEF_TYPE_UINT_ID: T = Context->UnsignedIntTy; break; - case pch::PREDEF_TYPE_ULONG_ID: T = Context->UnsignedLongTy; break; - case pch::PREDEF_TYPE_ULONGLONG_ID: T = Context->UnsignedLongLongTy; break; - case pch::PREDEF_TYPE_UINT128_ID: T = Context->UnsignedInt128Ty; break; - case pch::PREDEF_TYPE_SCHAR_ID: T = Context->SignedCharTy; break; - case pch::PREDEF_TYPE_WCHAR_ID: T = Context->WCharTy; break; - case pch::PREDEF_TYPE_SHORT_ID: T = Context->ShortTy; break; - case pch::PREDEF_TYPE_INT_ID: T = Context->IntTy; break; - case pch::PREDEF_TYPE_LONG_ID: T = Context->LongTy; break; - case pch::PREDEF_TYPE_LONGLONG_ID: T = Context->LongLongTy; break; - case pch::PREDEF_TYPE_INT128_ID: T = Context->Int128Ty; break; - case pch::PREDEF_TYPE_FLOAT_ID: T = Context->FloatTy; break; - case pch::PREDEF_TYPE_DOUBLE_ID: T = Context->DoubleTy; break; - case pch::PREDEF_TYPE_LONGDOUBLE_ID: T = Context->LongDoubleTy; break; - case pch::PREDEF_TYPE_OVERLOAD_ID: T = Context->OverloadTy; break; - case pch::PREDEF_TYPE_DEPENDENT_ID: T = Context->DependentTy; break; - case pch::PREDEF_TYPE_NULLPTR_ID: T = Context->NullPtrTy; break; - case pch::PREDEF_TYPE_CHAR16_ID: T = Context->Char16Ty; break; - case pch::PREDEF_TYPE_CHAR32_ID: T = Context->Char32Ty; break; - case pch::PREDEF_TYPE_OBJC_ID: T = Context->ObjCBuiltinIdTy; break; - case pch::PREDEF_TYPE_OBJC_CLASS: T = Context->ObjCBuiltinClassTy; break; - case pch::PREDEF_TYPE_OBJC_SEL: T = Context->ObjCBuiltinSelTy; break; - } - - assert(!T.isNull() && "Unknown predefined type"); - return T.withFastQualifiers(FastQuals); - } - - Index -= pch::NUM_PREDEF_TYPE_IDS; - //assert(Index < TypesLoaded.size() && "Type index out-of-range"); - if (TypesLoaded[Index].isNull()) { - TypesLoaded[Index] = ReadTypeRecord(TypeOffsets[Index]); - TypesLoaded[Index]->setFromPCH(); - if (DeserializationListener) - DeserializationListener->TypeRead(ID, TypesLoaded[Index]); - } - - return TypesLoaded[Index].withFastQualifiers(FastQuals); -} - -TemplateArgumentLocInfo -PCHReader::GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, - const RecordData &Record, - unsigned &Index) { - switch (Kind) { - case TemplateArgument::Expression: - return ReadExpr(); - case TemplateArgument::Type: - return GetTypeSourceInfo(Record, Index); - case TemplateArgument::Template: { - SourceRange QualifierRange = ReadSourceRange(Record, Index); - SourceLocation TemplateNameLoc = ReadSourceLocation(Record, Index); - return TemplateArgumentLocInfo(QualifierRange, TemplateNameLoc); - } - case TemplateArgument::Null: - case TemplateArgument::Integral: - case TemplateArgument::Declaration: - case TemplateArgument::Pack: - return TemplateArgumentLocInfo(); - } - llvm_unreachable("unexpected template argument loc"); - return TemplateArgumentLocInfo(); -} - -TemplateArgumentLoc -PCHReader::ReadTemplateArgumentLoc(const RecordData &Record, unsigned &Index) { - TemplateArgument Arg = ReadTemplateArgument(Record, Index); - - if (Arg.getKind() == TemplateArgument::Expression) { - if (Record[Index++]) // bool InfoHasSameExpr. - return TemplateArgumentLoc(Arg, TemplateArgumentLocInfo(Arg.getAsExpr())); - } - return TemplateArgumentLoc(Arg, GetTemplateArgumentLocInfo(Arg.getKind(), - Record, Index)); -} - -Decl *PCHReader::GetExternalDecl(uint32_t ID) { - return GetDecl(ID); -} - -TranslationUnitDecl *PCHReader::GetTranslationUnitDecl() { - if (!DeclsLoaded[0]) { - ReadDeclRecord(DeclOffsets[0], 0); - if (DeserializationListener) - DeserializationListener->DeclRead(0, DeclsLoaded[0]); - } - - return cast<TranslationUnitDecl>(DeclsLoaded[0]); -} - -Decl *PCHReader::GetDecl(pch::DeclID ID) { - if (ID == 0) - return 0; - - if (ID > DeclsLoaded.size()) { - Error("declaration ID out-of-range for PCH file"); - return 0; - } - - unsigned Index = ID - 1; - if (!DeclsLoaded[Index]) { - ReadDeclRecord(DeclOffsets[Index], Index); - if (DeserializationListener) - DeserializationListener->DeclRead(ID, DeclsLoaded[Index]); - } - - return DeclsLoaded[Index]; -} - -/// \brief Resolve the offset of a statement into a statement. -/// -/// This operation will read a new statement from the external -/// source each time it is called, and is meant to be used via a -/// LazyOffsetPtr (which is used by Decls for the body of functions, etc). -Stmt *PCHReader::GetExternalDeclStmt(uint64_t Offset) { - // Since we know tha this statement is part of a decl, make sure to use the - // decl cursor to read it. - DeclsCursor.JumpToBit(Offset); - return ReadStmtFromStream(DeclsCursor); -} - -bool PCHReader::FindExternalLexicalDecls(const DeclContext *DC, - llvm::SmallVectorImpl<Decl*> &Decls) { - assert(DC->hasExternalLexicalStorage() && - "DeclContext has no lexical decls in storage"); - - uint64_t Offset = DeclContextOffsets[DC].first; - if (Offset == 0) { - Error("DeclContext has no lexical decls in storage"); - return true; - } - - // Keep track of where we are in the stream, then jump back there - // after reading this context. - SavedStreamPosition SavedPosition(DeclsCursor); - - // Load the record containing all of the declarations lexically in - // this context. - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - if (RecCode != pch::DECL_CONTEXT_LEXICAL) { - Error("Expected lexical block"); - return true; - } - - // Load all of the declaration IDs - for (RecordData::iterator I = Record.begin(), E = Record.end(); I != E; ++I) - Decls.push_back(GetDecl(*I)); - ++NumLexicalDeclContextsRead; - return false; -} - -DeclContext::lookup_result -PCHReader::FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) { - assert(DC->hasExternalVisibleStorage() && - "DeclContext has no visible decls in storage"); - uint64_t Offset = DeclContextOffsets[DC].second; - if (Offset == 0) { - Error("DeclContext has no visible decls in storage"); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - // Keep track of where we are in the stream, then jump back there - // after reading this context. - SavedStreamPosition SavedPosition(DeclsCursor); - - // Load the record containing all of the declarations visible in - // this context. - DeclsCursor.JumpToBit(Offset); - RecordData Record; - unsigned Code = DeclsCursor.ReadCode(); - unsigned RecCode = DeclsCursor.ReadRecord(Code, Record); - if (RecCode != pch::DECL_CONTEXT_VISIBLE) { - Error("Expected visible block"); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - llvm::SmallVector<VisibleDeclaration, 64> Decls; - if (Record.empty()) { - SetExternalVisibleDecls(DC, Decls); - return DeclContext::lookup_result(DeclContext::lookup_iterator(), - DeclContext::lookup_iterator()); - } - - unsigned Idx = 0; - while (Idx < Record.size()) { - Decls.push_back(VisibleDeclaration()); - Decls.back().Name = ReadDeclarationName(Record, Idx); - - unsigned Size = Record[Idx++]; - llvm::SmallVector<unsigned, 4> &LoadedDecls = Decls.back().Declarations; - LoadedDecls.reserve(Size); - for (unsigned I = 0; I < Size; ++I) - LoadedDecls.push_back(Record[Idx++]); - } - - ++NumVisibleDeclContextsRead; - - SetExternalVisibleDecls(DC, Decls); - return const_cast<DeclContext*>(DC)->lookup(Name); -} - -void PCHReader::PassInterestingDeclsToConsumer() { - assert(Consumer); - while (!InterestingDecls.empty()) { - DeclGroupRef DG(InterestingDecls.front()); - InterestingDecls.pop_front(); - Consumer->HandleTopLevelDecl(DG); - } -} - -void PCHReader::StartTranslationUnit(ASTConsumer *Consumer) { - this->Consumer = Consumer; - - if (!Consumer) - return; - - for (unsigned I = 0, N = ExternalDefinitions.size(); I != N; ++I) { - // Force deserialization of this decl, which will cause it to be queued for - // passing to the consumer. - GetDecl(ExternalDefinitions[I]); - } - - PassInterestingDeclsToConsumer(); -} - -void PCHReader::PrintStats() { - std::fprintf(stderr, "*** PCH Statistics:\n"); - - unsigned NumTypesLoaded - = TypesLoaded.size() - std::count(TypesLoaded.begin(), TypesLoaded.end(), - QualType()); - unsigned NumDeclsLoaded - = DeclsLoaded.size() - std::count(DeclsLoaded.begin(), DeclsLoaded.end(), - (Decl *)0); - unsigned NumIdentifiersLoaded - = IdentifiersLoaded.size() - std::count(IdentifiersLoaded.begin(), - IdentifiersLoaded.end(), - (IdentifierInfo *)0); - unsigned NumSelectorsLoaded - = SelectorsLoaded.size() - std::count(SelectorsLoaded.begin(), - SelectorsLoaded.end(), - Selector()); - - std::fprintf(stderr, " %u stat cache hits\n", NumStatHits); - std::fprintf(stderr, " %u stat cache misses\n", NumStatMisses); - if (TotalNumSLocEntries) - std::fprintf(stderr, " %u/%u source location entries read (%f%%)\n", - NumSLocEntriesRead, TotalNumSLocEntries, - ((float)NumSLocEntriesRead/TotalNumSLocEntries * 100)); - if (!TypesLoaded.empty()) - std::fprintf(stderr, " %u/%u types read (%f%%)\n", - NumTypesLoaded, (unsigned)TypesLoaded.size(), - ((float)NumTypesLoaded/TypesLoaded.size() * 100)); - if (!DeclsLoaded.empty()) - std::fprintf(stderr, " %u/%u declarations read (%f%%)\n", - NumDeclsLoaded, (unsigned)DeclsLoaded.size(), - ((float)NumDeclsLoaded/DeclsLoaded.size() * 100)); - if (!IdentifiersLoaded.empty()) - std::fprintf(stderr, " %u/%u identifiers read (%f%%)\n", - NumIdentifiersLoaded, (unsigned)IdentifiersLoaded.size(), - ((float)NumIdentifiersLoaded/IdentifiersLoaded.size() * 100)); - if (TotalNumSelectors) - std::fprintf(stderr, " %u/%u selectors read (%f%%)\n", - NumSelectorsLoaded, TotalNumSelectors, - ((float)NumSelectorsLoaded/TotalNumSelectors * 100)); - if (TotalNumStatements) - std::fprintf(stderr, " %u/%u statements read (%f%%)\n", - NumStatementsRead, TotalNumStatements, - ((float)NumStatementsRead/TotalNumStatements * 100)); - if (TotalNumMacros) - std::fprintf(stderr, " %u/%u macros read (%f%%)\n", - NumMacrosRead, TotalNumMacros, - ((float)NumMacrosRead/TotalNumMacros * 100)); - if (TotalLexicalDeclContexts) - std::fprintf(stderr, " %u/%u lexical declcontexts read (%f%%)\n", - NumLexicalDeclContextsRead, TotalLexicalDeclContexts, - ((float)NumLexicalDeclContextsRead/TotalLexicalDeclContexts - * 100)); - if (TotalVisibleDeclContexts) - std::fprintf(stderr, " %u/%u visible declcontexts read (%f%%)\n", - NumVisibleDeclContextsRead, TotalVisibleDeclContexts, - ((float)NumVisibleDeclContextsRead/TotalVisibleDeclContexts - * 100)); - if (TotalSelectorsInMethodPool) { - std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", - NumMethodPoolSelectorsRead, TotalSelectorsInMethodPool, - ((float)NumMethodPoolSelectorsRead/TotalSelectorsInMethodPool - * 100)); - std::fprintf(stderr, " %u method pool misses\n", NumMethodPoolMisses); - } - std::fprintf(stderr, "\n"); -} - -void PCHReader::InitializeSema(Sema &S) { - SemaObj = &S; - S.ExternalSource = this; - - // Makes sure any declarations that were deserialized "too early" - // still get added to the identifier's declaration chains. - for (unsigned I = 0, N = PreloadedDecls.size(); I != N; ++I) { - SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(PreloadedDecls[I])); - SemaObj->IdResolver.AddDecl(PreloadedDecls[I]); - } - PreloadedDecls.clear(); - - // If there were any tentative definitions, deserialize them and add - // them to Sema's list of tentative definitions. - for (unsigned I = 0, N = TentativeDefinitions.size(); I != N; ++I) { - VarDecl *Var = cast<VarDecl>(GetDecl(TentativeDefinitions[I])); - SemaObj->TentativeDefinitions.push_back(Var); - } - - // If there were any unused static functions, deserialize them and add to - // Sema's list of unused static functions. - for (unsigned I = 0, N = UnusedStaticFuncs.size(); I != N; ++I) { - FunctionDecl *FD = cast<FunctionDecl>(GetDecl(UnusedStaticFuncs[I])); - SemaObj->UnusedStaticFuncs.push_back(FD); - } - - // If there were any locally-scoped external declarations, - // deserialize them and add them to Sema's table of locally-scoped - // external declarations. - for (unsigned I = 0, N = LocallyScopedExternalDecls.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(LocallyScopedExternalDecls[I])); - SemaObj->LocallyScopedExternalDecls[D->getDeclName()] = D; - } - - // If there were any ext_vector type declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) - SemaObj->ExtVectorDecls.push_back( - cast<TypedefDecl>(GetDecl(ExtVectorDecls[I]))); - - // FIXME: Do VTable uses and dynamic classes deserialize too much ? - // Can we cut them down before writing them ? - - // If there were any VTable uses, deserialize the information and add it - // to Sema's vector and map of VTable uses. - unsigned Idx = 0; - for (unsigned I = 0, N = VTableUses[Idx++]; I != N; ++I) { - CXXRecordDecl *Class = cast<CXXRecordDecl>(GetDecl(VTableUses[Idx++])); - SourceLocation Loc = ReadSourceLocation(VTableUses, Idx); - bool DefinitionRequired = VTableUses[Idx++]; - SemaObj->VTableUses.push_back(std::make_pair(Class, Loc)); - SemaObj->VTablesUsed[Class] = DefinitionRequired; - } - - // If there were any dynamic classes declarations, deserialize them - // and add them to Sema's vector of such declarations. - for (unsigned I = 0, N = DynamicClasses.size(); I != N; ++I) - SemaObj->DynamicClasses.push_back( - cast<CXXRecordDecl>(GetDecl(DynamicClasses[I]))); -} - -IdentifierInfo* PCHReader::get(const char *NameStart, const char *NameEnd) { - // Try to find this name within our on-disk hash table - PCHIdentifierLookupTable *IdTable - = (PCHIdentifierLookupTable *)IdentifierLookupTable; - std::pair<const char*, unsigned> Key(NameStart, NameEnd - NameStart); - PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key); - if (Pos == IdTable->end()) - return 0; - - // Dereferencing the iterator has the effect of building the - // IdentifierInfo node and populating it with the various - // declarations it needs. - return *Pos; -} - -std::pair<ObjCMethodList, ObjCMethodList> -PCHReader::ReadMethodPool(Selector Sel) { - if (!MethodPoolLookupTable) - return std::pair<ObjCMethodList, ObjCMethodList>(); - - // Try to find this selector within our on-disk hash table. - PCHMethodPoolLookupTable *PoolTable - = (PCHMethodPoolLookupTable*)MethodPoolLookupTable; - PCHMethodPoolLookupTable::iterator Pos = PoolTable->find(Sel); - if (Pos == PoolTable->end()) { - ++NumMethodPoolMisses; - return std::pair<ObjCMethodList, ObjCMethodList>();; - } - - ++NumMethodPoolSelectorsRead; - return *Pos; -} - -void PCHReader::SetIdentifierInfo(unsigned ID, IdentifierInfo *II) { - assert(ID && "Non-zero identifier ID required"); - assert(ID <= IdentifiersLoaded.size() && "identifier ID out of range"); - IdentifiersLoaded[ID - 1] = II; -} - -/// \brief Set the globally-visible declarations associated with the given -/// identifier. -/// -/// If the PCH reader is currently in a state where the given declaration IDs -/// cannot safely be resolved, they are queued until it is safe to resolve -/// them. -/// -/// \param II an IdentifierInfo that refers to one or more globally-visible -/// declarations. -/// -/// \param DeclIDs the set of declaration IDs with the name @p II that are -/// visible at global scope. -/// -/// \param Nonrecursive should be true to indicate that the caller knows that -/// this call is non-recursive, and therefore the globally-visible declarations -/// will not be placed onto the pending queue. -void -PCHReader::SetGloballyVisibleDecls(IdentifierInfo *II, - const llvm::SmallVectorImpl<uint32_t> &DeclIDs, - bool Nonrecursive) { - if (CurrentlyLoadingTypeOrDecl && !Nonrecursive) { - PendingIdentifierInfos.push_back(PendingIdentifierInfo()); - PendingIdentifierInfo &PII = PendingIdentifierInfos.back(); - PII.II = II; - for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) - PII.DeclIDs.push_back(DeclIDs[I]); - return; - } - - for (unsigned I = 0, N = DeclIDs.size(); I != N; ++I) { - NamedDecl *D = cast<NamedDecl>(GetDecl(DeclIDs[I])); - if (SemaObj) { - // Introduce this declaration into the translation-unit scope - // and add it to the declaration chain for this identifier, so - // that (unqualified) name lookup will find it. - SemaObj->TUScope->AddDecl(Action::DeclPtrTy::make(D)); - SemaObj->IdResolver.AddDeclToIdentifierChain(II, D); - } else { - // Queue this declaration so that it will be added to the - // translation unit scope and identifier's declaration chain - // once a Sema object is known. - PreloadedDecls.push_back(D); - } - } -} - -IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) { - if (ID == 0) - return 0; - - if (!IdentifierTableData || IdentifiersLoaded.empty()) { - Error("no identifier table in PCH file"); - return 0; - } - - assert(PP && "Forgot to set Preprocessor ?"); - if (!IdentifiersLoaded[ID - 1]) { - uint32_t Offset = IdentifierOffsets[ID - 1]; - const char *Str = IdentifierTableData + Offset; - - // All of the strings in the PCH file are preceded by a 16-bit - // length. Extract that 16-bit length to avoid having to execute - // strlen(). - // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as - // unsigned integers. This is important to avoid integer overflow when - // we cast them to 'unsigned'. - const unsigned char *StrLenPtr = (const unsigned char*) Str - 2; - unsigned StrLen = (((unsigned) StrLenPtr[0]) - | (((unsigned) StrLenPtr[1]) << 8)) - 1; - IdentifiersLoaded[ID - 1] - = &PP->getIdentifierTable().get(Str, StrLen); - } - - return IdentifiersLoaded[ID - 1]; -} - -void PCHReader::ReadSLocEntry(unsigned ID) { - ReadSLocEntryRecord(ID); -} - -Selector PCHReader::DecodeSelector(unsigned ID) { - if (ID == 0) - return Selector(); - - if (!MethodPoolLookupTableData) - return Selector(); - - if (ID > TotalNumSelectors) { - Error("selector ID out of range in PCH file"); - return Selector(); - } - - unsigned Index = ID - 1; - if (SelectorsLoaded[Index].getAsOpaquePtr() == 0) { - // Load this selector from the selector table. - // FIXME: endianness portability issues with SelectorOffsets table - PCHMethodPoolLookupTrait Trait(*this); - SelectorsLoaded[Index] - = Trait.ReadKey(MethodPoolLookupTableData + SelectorOffsets[Index], 0); - } - - return SelectorsLoaded[Index]; -} - -Selector PCHReader::GetExternalSelector(uint32_t ID) { - return DecodeSelector(ID); -} - -uint32_t PCHReader::GetNumExternalSelectors() { - return TotalNumSelectors + 1; -} - -DeclarationName -PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) { - DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++]; - switch (Kind) { - case DeclarationName::Identifier: - return DeclarationName(GetIdentifierInfo(Record, Idx)); - - case DeclarationName::ObjCZeroArgSelector: - case DeclarationName::ObjCOneArgSelector: - case DeclarationName::ObjCMultiArgSelector: - return DeclarationName(GetSelector(Record, Idx)); - - case DeclarationName::CXXConstructorName: - return Context->DeclarationNames.getCXXConstructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXDestructorName: - return Context->DeclarationNames.getCXXDestructorName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXConversionFunctionName: - return Context->DeclarationNames.getCXXConversionFunctionName( - Context->getCanonicalType(GetType(Record[Idx++]))); - - case DeclarationName::CXXOperatorName: - return Context->DeclarationNames.getCXXOperatorName( - (OverloadedOperatorKind)Record[Idx++]); - - case DeclarationName::CXXLiteralOperatorName: - return Context->DeclarationNames.getCXXLiteralOperatorName( - GetIdentifierInfo(Record, Idx)); - - case DeclarationName::CXXUsingDirective: - return DeclarationName::getUsingDirectiveName(); - } - - // Required to silence GCC warning - return DeclarationName(); -} - -TemplateName -PCHReader::ReadTemplateName(const RecordData &Record, unsigned &Idx) { - TemplateName::NameKind Kind = (TemplateName::NameKind)Record[Idx++]; - switch (Kind) { - case TemplateName::Template: - return TemplateName(cast_or_null<TemplateDecl>(GetDecl(Record[Idx++]))); - - case TemplateName::OverloadedTemplate: { - unsigned size = Record[Idx++]; - UnresolvedSet<8> Decls; - while (size--) - Decls.addDecl(cast<NamedDecl>(GetDecl(Record[Idx++]))); - - return Context->getOverloadedTemplateName(Decls.begin(), Decls.end()); - } - - case TemplateName::QualifiedTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - bool hasTemplKeyword = Record[Idx++]; - TemplateDecl *Template = cast<TemplateDecl>(GetDecl(Record[Idx++])); - return Context->getQualifiedTemplateName(NNS, hasTemplKeyword, Template); - } - - case TemplateName::DependentTemplate: { - NestedNameSpecifier *NNS = ReadNestedNameSpecifier(Record, Idx); - if (Record[Idx++]) // isIdentifier - return Context->getDependentTemplateName(NNS, - GetIdentifierInfo(Record, Idx)); - return Context->getDependentTemplateName(NNS, - (OverloadedOperatorKind)Record[Idx++]); - } - } - - assert(0 && "Unhandled template name kind!"); - return TemplateName(); -} - -TemplateArgument -PCHReader::ReadTemplateArgument(const RecordData &Record, unsigned &Idx) { - switch ((TemplateArgument::ArgKind)Record[Idx++]) { - case TemplateArgument::Null: - return TemplateArgument(); - case TemplateArgument::Type: - return TemplateArgument(GetType(Record[Idx++])); - case TemplateArgument::Declaration: - return TemplateArgument(GetDecl(Record[Idx++])); - case TemplateArgument::Integral: { - llvm::APSInt Value = ReadAPSInt(Record, Idx); - QualType T = GetType(Record[Idx++]); - return TemplateArgument(Value, T); - } - case TemplateArgument::Template: - return TemplateArgument(ReadTemplateName(Record, Idx)); - case TemplateArgument::Expression: - return TemplateArgument(ReadExpr()); - case TemplateArgument::Pack: { - unsigned NumArgs = Record[Idx++]; - llvm::SmallVector<TemplateArgument, 8> Args; - Args.reserve(NumArgs); - while (NumArgs--) - Args.push_back(ReadTemplateArgument(Record, Idx)); - TemplateArgument TemplArg; - TemplArg.setArgumentPack(Args.data(), Args.size(), /*CopyArgs=*/true); - return TemplArg; - } - } - - assert(0 && "Unhandled template argument kind!"); - return TemplateArgument(); -} - -TemplateParameterList * -PCHReader::ReadTemplateParameterList(const RecordData &Record, unsigned &Idx) { - SourceLocation TemplateLoc = ReadSourceLocation(Record, Idx); - SourceLocation LAngleLoc = ReadSourceLocation(Record, Idx); - SourceLocation RAngleLoc = ReadSourceLocation(Record, Idx); - - unsigned NumParams = Record[Idx++]; - llvm::SmallVector<NamedDecl *, 16> Params; - Params.reserve(NumParams); - while (NumParams--) - Params.push_back(cast<NamedDecl>(GetDecl(Record[Idx++]))); - - TemplateParameterList* TemplateParams = - TemplateParameterList::Create(*Context, TemplateLoc, LAngleLoc, - Params.data(), Params.size(), RAngleLoc); - return TemplateParams; -} - -void -PCHReader:: -ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, - const RecordData &Record, unsigned &Idx) { - unsigned NumTemplateArgs = Record[Idx++]; - TemplArgs.reserve(NumTemplateArgs); - while (NumTemplateArgs--) - TemplArgs.push_back(ReadTemplateArgument(Record, Idx)); -} - -/// \brief Read a UnresolvedSet structure. -void PCHReader::ReadUnresolvedSet(UnresolvedSetImpl &Set, - const RecordData &Record, unsigned &Idx) { - unsigned NumDecls = Record[Idx++]; - while (NumDecls--) { - NamedDecl *D = cast<NamedDecl>(GetDecl(Record[Idx++])); - AccessSpecifier AS = (AccessSpecifier)Record[Idx++]; - Set.addDecl(D, AS); - } -} - -CXXBaseSpecifier -PCHReader::ReadCXXBaseSpecifier(const RecordData &Record, unsigned &Idx) { - bool isVirtual = static_cast<bool>(Record[Idx++]); - bool isBaseOfClass = static_cast<bool>(Record[Idx++]); - AccessSpecifier AS = static_cast<AccessSpecifier>(Record[Idx++]); - QualType T = GetType(Record[Idx++]); - SourceRange Range = ReadSourceRange(Record, Idx); - return CXXBaseSpecifier(Range, isVirtual, isBaseOfClass, AS, T); -} - -NestedNameSpecifier * -PCHReader::ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx) { - unsigned N = Record[Idx++]; - NestedNameSpecifier *NNS = 0, *Prev = 0; - for (unsigned I = 0; I != N; ++I) { - NestedNameSpecifier::SpecifierKind Kind - = (NestedNameSpecifier::SpecifierKind)Record[Idx++]; - switch (Kind) { - case NestedNameSpecifier::Identifier: { - IdentifierInfo *II = GetIdentifierInfo(Record, Idx); - NNS = NestedNameSpecifier::Create(*Context, Prev, II); - break; - } - - case NestedNameSpecifier::Namespace: { - NamespaceDecl *NS = cast<NamespaceDecl>(GetDecl(Record[Idx++])); - NNS = NestedNameSpecifier::Create(*Context, Prev, NS); - break; - } - - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: { - Type *T = GetType(Record[Idx++]).getTypePtr(); - bool Template = Record[Idx++]; - NNS = NestedNameSpecifier::Create(*Context, Prev, Template, T); - break; - } - - case NestedNameSpecifier::Global: { - NNS = NestedNameSpecifier::GlobalSpecifier(*Context); - // No associated value, and there can't be a prefix. - break; - } - } - Prev = NNS; - } - return NNS; -} - -SourceRange -PCHReader::ReadSourceRange(const RecordData &Record, unsigned &Idx) { - SourceLocation beg = SourceLocation::getFromRawEncoding(Record[Idx++]); - SourceLocation end = SourceLocation::getFromRawEncoding(Record[Idx++]); - return SourceRange(beg, end); -} - -/// \brief Read an integral value -llvm::APInt PCHReader::ReadAPInt(const RecordData &Record, unsigned &Idx) { - unsigned BitWidth = Record[Idx++]; - unsigned NumWords = llvm::APInt::getNumWords(BitWidth); - llvm::APInt Result(BitWidth, NumWords, &Record[Idx]); - Idx += NumWords; - return Result; -} - -/// \brief Read a signed integral value -llvm::APSInt PCHReader::ReadAPSInt(const RecordData &Record, unsigned &Idx) { - bool isUnsigned = Record[Idx++]; - return llvm::APSInt(ReadAPInt(Record, Idx), isUnsigned); -} - -/// \brief Read a floating-point value -llvm::APFloat PCHReader::ReadAPFloat(const RecordData &Record, unsigned &Idx) { - return llvm::APFloat(ReadAPInt(Record, Idx)); -} - -// \brief Read a string -std::string PCHReader::ReadString(const RecordData &Record, unsigned &Idx) { - unsigned Len = Record[Idx++]; - std::string Result(Record.data() + Idx, Record.data() + Idx + Len); - Idx += Len; - return Result; -} - -CXXTemporary *PCHReader::ReadCXXTemporary(const RecordData &Record, - unsigned &Idx) { - CXXDestructorDecl *Decl = cast<CXXDestructorDecl>(GetDecl(Record[Idx++])); - return CXXTemporary::Create(*Context, Decl); -} - -DiagnosticBuilder PCHReader::Diag(unsigned DiagID) { - return Diag(SourceLocation(), DiagID); -} - -DiagnosticBuilder PCHReader::Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID); -} - -/// \brief Retrieve the identifier table associated with the -/// preprocessor. -IdentifierTable &PCHReader::getIdentifierTable() { - assert(PP && "Forgot to set Preprocessor ?"); - return PP->getIdentifierTable(); -} - -/// \brief Record that the given ID maps to the given switch-case -/// statement. -void PCHReader::RecordSwitchCaseID(SwitchCase *SC, unsigned ID) { - assert(SwitchCaseStmts[ID] == 0 && "Already have a SwitchCase with this ID"); - SwitchCaseStmts[ID] = SC; -} - -/// \brief Retrieve the switch-case statement with the given ID. -SwitchCase *PCHReader::getSwitchCaseWithID(unsigned ID) { - assert(SwitchCaseStmts[ID] != 0 && "No SwitchCase with this ID"); - return SwitchCaseStmts[ID]; -} - -/// \brief Record that the given label statement has been -/// deserialized and has the given ID. -void PCHReader::RecordLabelStmt(LabelStmt *S, unsigned ID) { - assert(LabelStmts.find(ID) == LabelStmts.end() && - "Deserialized label twice"); - LabelStmts[ID] = S; - - // If we've already seen any goto statements that point to this - // label, resolve them now. - typedef std::multimap<unsigned, GotoStmt *>::iterator GotoIter; - std::pair<GotoIter, GotoIter> Gotos = UnresolvedGotoStmts.equal_range(ID); - for (GotoIter Goto = Gotos.first; Goto != Gotos.second; ++Goto) - Goto->second->setLabel(S); - UnresolvedGotoStmts.erase(Gotos.first, Gotos.second); - - // If we've already seen any address-label statements that point to - // this label, resolve them now. - typedef std::multimap<unsigned, AddrLabelExpr *>::iterator AddrLabelIter; - std::pair<AddrLabelIter, AddrLabelIter> AddrLabels - = UnresolvedAddrLabelExprs.equal_range(ID); - for (AddrLabelIter AddrLabel = AddrLabels.first; - AddrLabel != AddrLabels.second; ++AddrLabel) - AddrLabel->second->setLabel(S); - UnresolvedAddrLabelExprs.erase(AddrLabels.first, AddrLabels.second); -} - -/// \brief Set the label of the given statement to the label -/// identified by ID. -/// -/// Depending on the order in which the label and other statements -/// referencing that label occur, this operation may complete -/// immediately (updating the statement) or it may queue the -/// statement to be back-patched later. -void PCHReader::SetLabelOf(GotoStmt *S, unsigned ID) { - std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID); - if (Label != LabelStmts.end()) { - // We've already seen this label, so set the label of the goto and - // we're done. - S->setLabel(Label->second); - } else { - // We haven't seen this label yet, so add this goto to the set of - // unresolved goto statements. - UnresolvedGotoStmts.insert(std::make_pair(ID, S)); - } -} - -/// \brief Set the label of the given expression to the label -/// identified by ID. -/// -/// Depending on the order in which the label and other statements -/// referencing that label occur, this operation may complete -/// immediately (updating the statement) or it may queue the -/// statement to be back-patched later. -void PCHReader::SetLabelOf(AddrLabelExpr *S, unsigned ID) { - std::map<unsigned, LabelStmt *>::iterator Label = LabelStmts.find(ID); - if (Label != LabelStmts.end()) { - // We've already seen this label, so set the label of the - // label-address expression and we're done. - S->setLabel(Label->second); - } else { - // We haven't seen this label yet, so add this label-address - // expression to the set of unresolved label-address expressions. - UnresolvedAddrLabelExprs.insert(std::make_pair(ID, S)); - } -} - - -PCHReader::LoadingTypeOrDecl::LoadingTypeOrDecl(PCHReader &Reader) - : Reader(Reader), Parent(Reader.CurrentlyLoadingTypeOrDecl) { - Reader.CurrentlyLoadingTypeOrDecl = this; -} - -PCHReader::LoadingTypeOrDecl::~LoadingTypeOrDecl() { - if (!Parent) { - // If any identifiers with corresponding top-level declarations have - // been loaded, load those declarations now. - while (!Reader.PendingIdentifierInfos.empty()) { - Reader.SetGloballyVisibleDecls(Reader.PendingIdentifierInfos.front().II, - Reader.PendingIdentifierInfos.front().DeclIDs, - true); - Reader.PendingIdentifierInfos.pop_front(); - } - - // We are not in recursive loading, so it's safe to pass the "interesting" - // decls to the consumer. - if (Reader.Consumer) - Reader.PassInterestingDeclsToConsumer(); - } - - Reader.CurrentlyLoadingTypeOrDecl = Parent; -} |